これは MMA7361 3軸アナログ加速度センサ の Nucleo F401RE 用のライブラリです。詳しい説明はLibrary中のReadMe.hに記載しています。文字化けや開けない場合はダウンロードしてみてください。Google Chrome では見れるはずです。

Dependents:   Nucleo_L3GD20_MMA7361_Kalman

ReadMe.h

Committer:
hirokimineshita
Date:
2016-09-30
Revision:
6:ca882e5e2686
Parent:
2:78a6ee76433c

File content as of revision 6:ca882e5e2686:

/*
これは MMA7361 3軸アナログ加速度センサ の Nucleo F401RE 用のライブラリです。AnalogInポート によるA/D変換をしています。
センサのスリープモードを解除するためにSLピンにVDDを入れてください。
0gピンを使うことでセンサが自由落下しているときにhighを返すらしいですが、試してはいません。
今まで使ってきて、STピンが働いているのかはよくわかりませんでした。最初コンパイルする際注意が出てくるかもしれませんが、
無視してください。
参考:http://shokai.org/blog/archives/7701

初期化(nameはなんでもいいです)

mma7361 name;

 Xピン:PA_0  Yピン:PA_1  Zピン:PA_4  gSピン:PH_1  STピン:PH_0
 で接続します。


mma7361 name(X,Y,Z);

 Xピン:X  Yピン:Y  Zピン:Z  gSピン:PH_1  STピン:PH_0
 で接続します。


mma7361 name(X,Y,Z,ST);

 Xピン:X  Yピン:Y  Zピン:Z  gSピン:PH_1  STピン:ST
 で接続します。


mma7361 name(X,Y,Z,ST,gS);

 Xピン:X  Yピン:Y  Zピン:Z  gSピン:gS  STピン:ST
 で接続します。


関数

name.calibration();

 PCでターミナルソフトを用いて使います。Serialの設定は必要ありません。
 TeraTerm での動作確認済みです。センサの値を取得、
 初期値等を2次元配列 mat[4][3] (3×4行列) に入れます。
 ターミナルソフト上に出る指示に従ってやれば問題ないです。
 配列 mat[4][3] については mma7361.cpp に記載してます。

name.set_each_num(A00,A10,A20,A01,A11,A21,G00,G10,G20,G01,G11,G21,range);

       | A00 A10 A20 |
 mat = | A01 A11 A21 |
       | G00 G10 G20 |
       | G01 G11 G21 |

 測定範囲:range (=0のとき1.5G  =1のとき6.0G)
 に設定します。
 A00~G21の値を def (=-1) にするとその値は変更しません。


name.set_num(&new_mat,range);

 配列 mat に new_mat をうつします。並び方を間違えないように注意してください。
 new_mat = {A00,A10,A20,A01,A11,A21,G00,G10,G20,G01,G11,G21}としてもいい。
 測定範囲を range に設定します。
 A00~G21の値を def (=-1) にすると変更しません。


name.set_range(range);

 測定範囲を range に設定


name.clear_mat();

 配列 mat に mma7361.h で定義された A00 から G21 までを代入します。初期化の際に使われていて、
 実際のプログラム中では使う必要はありません。


var = name.read_bit(axis);

 var:int型の戻り値(12bit)
 axis: x_axis (=0)、y_axis (=1)、z_axis (=2) で軸を指定します。
 指定した軸の加速度をA/D変換したのを何もせずに返します。
 name.read_u16 を軸指定で簡単にできるようにしただけです。


var = name.read_bit_0(axis);

 var:int型の戻り値
 axis: x_axis、y_axis、z_axis で軸を指定。
 指定した軸の加速度をA/D変換したのを配列 mat にしたがって加速度がないときに
 0になるように引き算したものです。


var = name.read_by_g(axis);

 var:float型の戻り値
 axis: x_axis、y_axis、z_axis で軸を指定。
 指定した軸の加速度を配列 mat に従って計算し、何Gかを返します。


name.low_pass_filter(&int_bit,axis);

 int_bit:前回のこの関数で得られたセンサ値(int)を保持している変数。
 axis: x_axis、y_axis、z_axis で軸を指定。
 これは擬似的にローパスフィルタをやっています。これによりノイズを消去します。
 ただ、反応が鈍くなったり、遅くなったりします。変数を1つ用意してください。やってる計算は下の通りです。
 現在の値 = 0.9 × ひとつ前の値 + 0.1 × センサの値
 参考:http://android.ohwada.jp/archives/334
 純粋に加速度を得たときはあまり使わない方がいいかもしれないです。
 bit値に対して行っており、戻り値は name.read_bit(axis) の値にローパスフィルタを掛けたものになっています。
 最初は収束するまでに時間がかかるので何百個かのデータをとって捨てるか、後述の関数 name.set_1st_bit() を
 つかって初期化してください。


name.show_mat();
 配列 mat をターミナルソフトに表示させます。形は3×4です。


var = name.bit_to_g(bit,axis);

 var:float型の戻り値
 bit:変換したいデジタル値(int)
 axis: x_axis、y_axis、z_axis で軸を指定。
 与えられたデジタル値を配列 mat にしたがって0にあわせ、重力加速度に変換します。


name.set_1st_bit(&var,axis,dir);

 var:int型の変数
 axis: x_axis、y_axis、z_axis で軸を指定。
 dir:float型の値。重力加速度を打ち消す加速度がその軸に対してどのくらい働いているか。大まかでいい。(-1~1)
 ローパスフィルタを使う前にこれを使ってセンサ値を格納する変数を初期化しておくと
 早くセンサ値に収束します。これを使わなくてもいいですが、フィルタを通した最初の300個ぐらいの値
 は正しくなくなります。dirの値が正確であればあるほど速く収束します。dirの値が毎回異なるときは
 0を入れておくことで、収束にかかる時間を減らすことができます。


var = name.rotate(&var_a,a_axis,&var_b,b_axis);

 var:int型の戻り値
 var_a: aのセンサ値を保管している場所
 a_axis: aの軸、x_axis、y_axis、z_axis で軸を指定。
 var_b: bのセンサ値を保管している場所
 b_axis: bの軸、x_axis、y_axis、z_axis で軸を指定。
 軸 b から軸 a への回転の角加速度(ラジアン)を計算します。なかで上述の関数 name.bit_to_g() を使っているので
 そこを考慮してください。並進方向が入ると正しい値を返せません。
 加速度が0.01Gより小さいときは0Gとしています。軸 b が 0G のときは返る値も0となります。


var = name.rad_to_deg(rad);

 var:float型の戻り値(度)
 rad:変換したい値(ラジアン)
 値をラジアンから度に変換してそれを返します。角度、角速度、角加速度に対して使えます。
 πを初期では3.1415926535にしていますが、mma7361.h のなかで define されている PI の値を変更する
 ことで変えることができます。


サンプルプログラム

#include "mbed.h"
#include "mma7361.h"

Serial pc(USBTX,USBRX);

DigitalOut myled(LED1);
mma7361 a;

int main() {
    a.clear_mat();
    a.show_mat();
    int x,y;
    a.set_1st_bit(&x,x_axis,0);
    a.set_1st_bit(&y,y_axis,0);
    float gx,gy,theta;
    while(1){
        a.low_pass_filter(&x,x_axis);
        a.low_pass_filter(&y,y_axis);
        gx=a.bit_to_g(x,x_axis);
        gy=a.bit_to_g(y,y_axis);
        theta=a.rotate(&x,x_axis,&y,y_axis);
        theta=a.rad_to_deg(theta);
        pc.printf("%.3fG %.3fG %.3f\n\r",gx,gy,theta);
    }
}


実行結果

31356 34040 28639
32717 33388 31475
15633 15797 15187
5416 3220 7131
-0.100G -0.130G 37.606
-0.164G -0.233G 35.183
-0.216G -0.321G 33.904
-0.262G -0.401G 33.177
-0.300G -0.470G 32.591
-0.339G -0.535G 32.352
-0.374G -0.593G 32.223
-0.404G -0.645G 32.071
-0.428G -0.689G 31.840
*/