Help us understand the problem. What is going on with this article?

micro:bit / MicroPython & Mbed / オンボード加速度センサーのさまざまな読み出しかた

More than 1 year has passed since last update.

概要

micro:bit は I2C バスに加速度センサー MMA8653FC が接続されている。この加速度センサーからさまざまな方法で加速度を読み出してみる。

(1) 一番簡単な方法 (MicroPython)

microbit.accelerometer オブジェクトから get_ ~ () メソッドで読み出す。単位は約 mg (ミリ・ジー)。

from microbit import *

while True:
    # 軸ごとに読み出す。
    x = accelerometer.get_x()
    y = accelerometer.get_y()
    z = accelerometer.get_z()
    print("%d, %d, %d" % (x, y, z))

    # 3 軸を一遍に tuple として読み出すこともできる。
    xyz = accelerometer.get_values()
    print(xyz)

    sleep(500)

実行結果:

検知方向:

(2) I2C バスから読み出す方法 (MicroPython)

10 ビットの測定データが OUT_X(Y,Z)_MSB と OUT_X(Y,Z)_LSB とに分けてに格納される。

from microbit import *

# 10 ビットの生データを ± 2 g に変換するための函数
def raw2g(raw):
    if 0b1000000000 == (0b1000000000 & raw): # 最上位ビットに 1 が立っていたら負数なので
        raw -= 2**10                         # -0d1 ~ -0d512 に変換する。

    return 4/(2**10) * raw                   # 1 LSB = 4 / 2**10 = 0.00390625g

while True:
    # 0x1d がディバイスアドレス。レジスタアドレス 0x00 から 7 バイトを読み出す。
    # (もちろんレジスタアドレス 0x01 から 6 バイトを読み出すことにしてもよい)
    raw = i2c.read(0x1d, 7)

    # 2 つの 8 ビットデータを 10 ビットデータに並べ換える。
    raw_x = raw[1]<<2 | raw[2]>>6
    raw_y = raw[3]<<2 | raw[4]>>6
    raw_z = raw[5]<<2 | raw[6]>>6

    g_x = raw2g(raw_x)
    g_y = raw2g(raw_y)
    g_z = raw2g(raw_z)

    print("x: %.8f, y: %.8f, z: %.8f" % (g_x, g_y, g_z))
    sleep(500)

実行結果:

検知方向:

(3) MicroBitAccelerometer オブジェクトから読み出す方法 (mbed)

mbed でコンパイルする。加速度だけでなくピッチ、ロールを取得するためのメソッドも用意されている。

#include "MicroBit.h"
MicroBit              uBit;
MicroBitI2C           i2c           = MicroBitI2C(I2C_SDA0, I2C_SCL0);
MicroBitAccelerometer accelerometer = MicroBitAccelerometer(i2c);

int main(void){
    uBit.init();
    //accelerometer.setPeriod(100);

    while(1){
        // 3 軸の加速度を取得する (単位は約 mg)。
        int g_x = accelerometer.getX();
        int g_y = accelerometer.getY();
        int g_z = accelerometer.getZ();

        // ピッチを角度単位、ラジアン単位で取得する。
        int   pitch    = accelerometer.getPitch();
        float pitchRad = accelerometer.getPitchRadians();

        // ロールを角度単位、ラジアン単位で取得する。
        int   roll    = accelerometer.getRoll();
        float rollRad = accelerometer.getRollRadians();

        printf("x: %d, y: %d, z: %d\n", g_x, g_y, g_z);
        printf("pitch(deg): %d, pitchRad(rad): %.3f\n", pitch, pitchRad);
        printf("roll(deg) : %d, rollRad(rad) : %.3f\n", roll, rollRad);
        printf("\n");

        wait_ms(500);
    }

    release_fiber();
    return 0;
}

実行結果:

検知方向:

(4) I2C バスから読み出す方法 (mbed)

mbed でコンパイルする。

ディバイスアドレス (7 ビットアドレッシング) は 0x1d (0b 001 1101) であるが 8 ビット幅の Bit7-1 として送信されるので 0x1d<<1 のようにして左に 1 ビットシフトする (0b 0011 101?)。Bit0 には R/!W のどちらかが入る。

レジスタアドレス 0x01 から 6 バイトを読み出す。

#include "MicroBit.h"
MicroBit uBit;

float raw2g(int raw){
    if(0x200 == (0x200 & raw)){     // 0x200 = 0b 10 0000 0000
        raw -= 1024;                // 1024 = 2^10
    }
    return 0.00390625 * (float)raw; // 1 LSB = 0.00390625 = 4/(2^10)
}

int main(void){
    uBit.init();

    char buf1[] = {0x01};
    char buf2[6];

    while(1){
        uBit.i2c.write(0x1d<<1, buf1, 1, true); // true を指定して repeated START にする。
        uBit.i2c.read(0x1d<<1, buf2, 6);

        int raw_x = buf2[0]<<2 | buf2[1]>>6;
        int raw_y = buf2[2]<<2 | buf2[3]>>6;
        int raw_z = buf2[4]<<2 | buf2[5]>>6;

        float x = raw2g(raw_x);
        float y = raw2g(raw_y);
        float z = raw2g(raw_z);

        printf("x: %.8f, y: %.8f, z: %.8f\n", x, y, z);
        wait_ms(500);
    }

    release_fiber();
    return 0;
}

実行結果:

検知方向:

参考

関連

micro:bit I2C バス / オンボード加速度計

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away