3軸加速度センサで傾斜角度を測定してみます

〔PICの動かせ方入門に戻る〕


最近加速度センサは色々な物に応用されています、ロボットの姿勢制御や車エアーバッグの衝突検出
に、カメラの手ぶれ検出、携帯電話など、電話の縦横を変えると画面方向が変わったりしますよね。

加速度センサはモーションセンサとも言い、物体が動く速度(1秒あたりの速度の変化を検出)を測定
する物で、傾き(重力)や動きに振動と衝撃を検出する事が出来ます。

また、加速度センサと似た様な物で角速度センサ(ジャイロセンサ)が有りますが、
これはセンサを軸にして回転方向の運動を測定する物で、物体が1秒間に何度の回転運動(角速度)を
しているのかを検出する事が出来ます。

加速度センサは"重力"・"振動(動き)"・"衝撃"を検出できますが、
今回は"重力"を検出し、センサから読み込んだ値を利用して傾斜させた場合の
角度(重力方向に対する角度)を表示させて見ようと思います。

ここで使用する加速度センサは、秋月電子のADXL345を使ってみます。
このモジュールはピンの半田付けが必要です。

ADXL345-1  このセンサは各方向X軸Y軸Z軸の3方向をSPIかI2Cで
 接続する事により速度の変化量を読み取る事が出来ます。
 (LCD表示器がI2C接続なのでセンサもI2C接続としています)

 各軸の水平方向(0度)が0gで、垂直方向(90度)が1gです。
 なのでZ軸は垂直状態なので1gが既に加かっています。
 地球上では全ての物体に1Gの重力が加かっているらしい

図1  このセンサの測定のレンジは±2/4/8/16gから選択可能です。
 出力値は±2gの設定で、+256(1g)〜0(0g)〜256(-1g)位です。
 今回は重力の測定なので±2gで十分ですが、
 衝撃の検出等を行う場合は±16gとかに設定をしましょう。


図2 ここのスケッチでは左図の様にXZの2軸を使い360度の測定が
出来ます。またYZ軸を使うと左右方向を測定できます。
(1軸のみでの計算では360度の測定が出来ないので2軸使用)

ここでは計算式の説明は省きます、興味ある人は他のサイト様を
検索して下さい。(実はうまく説明出来なかったりします...えへ)

《配線図》

16F1827ピン構成図 左図はPIC16F1827のピン構成図です。

今回使用するピンは、
電源ピンの14番(VDD)と5番(VSS)に
I2Cピンの7番(SDA1)と10番(SCL1)です。

電源はセンサとLCD表示器が3.3Vなので
回路も3.3V電源で統一しています。

16F1827にはMSSP機能が2個有りますが、ここではMSSP1(SDA1/SCL1)のみ対応

配線図  左が実態配線図で下がセンサのピン構成図です。
 センサピンの使い方等のデータシートは、こちらのHPから
 ダウンロードして下さい。
 尚、センサのCSピンをVDDに配線するとI2C駆動になりますが、
 モジュール内部で10K抵抗を通してVDDに配線されているので
 このまま配線しなくても良いでしょう。

  ADXL345-2

 LCDは秋月電子の"I2C接続小型LCDモジュール"
 使っています、LCDの詳しい記事はこちらを参照下さい。

 I2C用のプルアップ抵抗は、センサモジュールで10K抵抗が配線済みなのでこれを使用します。
 なので、PIC内部ではプルアップなし、LCDのプルアップ用の半田盛りは行いません。

SDOピンについて

I2Cにて利用する場合、このピンでアドレスを選択する事が出来ます。
ピンをハイレベル(VDDに接続)にするとアドレスは0x1Dで、ローレベル(GNDに接続)にすると0x53の
2種類から選べます。
但し、このモジュールは内部で10KΩ抵抗を解してVDDに配線されているので何も配線しないと
アドレスは0x1Dとなります。

《ダウンロードプログラムについて》

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
ADXL345.lzh(Ver1.00:2014/01/29)
ADXL345I2C.lzh(Ver1.01:2014/03/29) ファイル名を変更 *2)
ADXL345I2C.lzh(2015/10/10) MPLAB X/XC8(V1.32)に対応 *3)

プログラムソースをダウンロードしたら、MPLAB X(v2.15)にてプロジェクトを作成します。
以下のファイルをプロジェクトディレクトリにコピーしてプロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。 *3)
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。

ダウンロードしたら解凍して下さい、以下のファイル構成です。 *3)
 acceler1.c・・・・・・・・・本体のサンプルソースプログラム1(各軸読込み値表示用)
 acceler2.c・・・・・・・・・本体のサンプルソースプログラム2(傾斜角度表示用)
 skADXL345I2C.c・・・ADXL345関数ライブラリソースファイル(I2Cバージョン)
 skADXL345I2C.h・・・ADXL345ライブラリ用インクルードファイル(I2Cバージョン)
 skI2CLCDlib.c・・・・・・I2C接続LCD関数ライブラリソースファイル
 skI2CLCDlib.h・・・・・・I2C接続LCDライブラリ用インクルードファイル
 skI2Clib.c・・・・・・・・・・I2C通信を行う関数ソースファイル
 skI2Clib.h・・・・・・・・・・I2C通信を行う関数のインクルードファイル

ここの実験はPICのシステムクロック 8MHzでの実験となっています。

acceler1.c

このサンプルプログラムは、センサが出力するそのままの値を、各軸100回読み込んで単純平均化
させた値を表示させる物です。
このセンサにはFIFO型バッファ機能が有るのでこれをうまく利用すれば移動平均などを行わせる事が
出来ると思うのですがぁ....

実行結果表示画面1  左写真は、センサが水平時の値で、表示1行目左側がX軸で、
 表示1行目右側がY軸、表示2行目がZ軸です。
 XY軸は0gでZ軸は1gでの内容です。(センサにより値は変わります)
 センサを動かせば表示が変わると思います。
 尚、Z軸を水平(0g)にした場合の値は1位でした。

このサンプルプログラムの様に値を表示させるだけならPIC12F1822でも可能です。(下記記事参照)

acceler2.c

acceler1.cはセンサ値をそのまま表示させたものでした、acceler2.cはその値から傾斜角度を計算させ
表示します。

実行結果表示画面2  左写真は、センサを+X軸方向(前後方向)に8度程傾けた場合の表示内容です
 尚、+X軸方向を水平より前側に傾けて行けば-1〜-180度になります。
 Y軸方向(左右方向)に傾ければ2行目が変化するでしょう。

 精度的には1度以内の感じがします。

 プログラム内に下記の記述が有りますが、
 Xangle = (int)(atan2(X-15,Z-1) / 3.14159 * 180.0) ; // X方向
 Yangle = (int)(atan2(Y-1,Z-1) / 3.14159 * 180.0) ; // Y方向
 このX-15/Y-1/Z-1はacceler1.cで表示させた0g時の値をいれます。
 0G水平時の値を0にする為のオフセット値です。
 但し注意としては、センサの個体差等で値も異なります
 尚、傾斜計の様な物を製作する場合は、このオフセット値を簡単に設定出来るような操作の仕掛けが
 必要になるでしょう。

 又、今回の実験の様にセンサを動かさない固定した状態に、重力方向の角度を測定する場合には
 上手く角度を得る事が可能です。
 ですがぁ、検出物体が動いている所にセンサを設置して角度を得ようとすると、重力方向以外の
 外部的な加速(G)が加わりまので、この様な場合は上手く角度が得られません、
 そんな場合はジャイロセンサを使いましょう。 *4)

skADXL345I2C.h

ADXL345にアクセスする為のライブラリ用のインクルードファイルです。
"skADXL345I2C.c"を利用する場合に
#include "skADXL345I2C.h" をプログラムの先頭で記述して下さい。

今回は8MHzで利用しているので、
#ifndef _XTAL_FREQ
 // Unless already defined assume 8MHz system frequency
 // This definition is required to calibrate __delay_us() and __delay_ms()
 #define _XTAL_FREQ 8000000    // 使用するPIC等により動作周波数値を設定する
#endif
と記述しています、8MHz以外で利用する人は"8000000"を書き換えて下さい。

I2Cスレーブアドレスについて

アドレス設定  アドレスは7ビットで表します、左図の1〜7ビットです。
 0ビット目はR/Wでこれはスレーブに対する読書き指示ビットです。
 R/W=0 : 書き込み要求です(スレーブは受信モード)
 R/W=1 : 読み込み要求です(スレーブは送信モード)

今回はADXL345センサのアドレスは、"0011101"(0x1D)です。("0011101"+R/W)
R/W=0書き込みなら"0011101"+"0"で0x3A、R/W=1読み込みなら"0011101"+"1"で0x3Bとなります。
よってここでは
#define ADXL345_ADRES 0x1D    // ADXL345のアドレス(ALT ADDRESSピンがHIGHの時)
となっています。

skADXL345I2C.c

このライブラリはADXL345を使った3軸加速度センサモジュールにアクセスする為の関数集です。
センサには色々な機能が有るのですが、このライブラリは各軸の値を読み込む機能のみ対応です。
その他の機能についてはいずれ試そうと思いますが....いつになるやら...

この関数集にはskI2Clib.c/skI2Clib.hのファイルが必要です。
また、この関数集自体は他のPICでも利用可能でしょう。

この関数集を利用する場合は、"skI2Clib.c"の"InitI2C_Master( )"関数を呼び出した後使います、
使い方の例は、"acceler1.c"を参照下さい。 *3)

ADXL345にアクセスを行う関数の使い方を説明します。

 ans = acceler_Init( )
  ADXL345の初期化を行う処理です。
  分解能は10bitモードで出力、使用するレンジは±2Gで出力データレートは200Hz、
  またFIFOは使用しないで初期化しています。
   ans : -1ならADXL345が応答していない、正常ならADXL345のID(0xE5)が返ります。

 ans = acceler_Read(*X,*Y,*Z)
  ADXL345の各軸の値を読み込む処理です。
  XYZ軸のセンサ値を読み込んで指定の変数にデータを返します、大体±300内位の値です。
   *X : X軸の値を読み込みこの変数にデータを設定
   *Y : Y軸の値を読み込みこの変数にデータを設定
   *Z : Z軸の値を読み込みこの変数にデータを設定
   ans : 0=正常 −1=読込み失敗(I2C異常)
  例)
    int X , Y , Z , ans ;

    ans = acceler_Read(&X,&Y,&Z) ;
    if (ans == 0) {
         // 各軸の表示を行うなどの処理を行う
    }

skI2CLCDlib.h/skI2CLCDlib.c

I2C接続LCDにアクセス(表示)を行う為の関数集群です。
この内容はこちらの「秋月電子I2C接続小型LCDモジュールに表示を行う」を参照下さい。

skI2Clib.h/skI2Clib.c

このライブラリはI2Cデバイス(RTC/EEPROM等)と接続を行う為の関数集です。
この内容も「秋月電子I2C接続小型LCDモジュールに表示を行う」を参照下さい。

《PIC12F1822の場合》  *1)

配線図   ADXL345-2
 左図は、12F1822の場合での配線です。

 12F1822では傾斜角度の表示は浮動小数点(float)を扱うので
 プログラムメモリ容量が足りなくなります。
 ですのでセンサ値を表示するだけのプログラムとなります。

 プログラムは、上記サンプルプログラムソースファイルを
 ダウンロード後、こちらのプログラム(acceler1.c)と
 入換えてコンパイルをして下さい。
 (ちなみにこれをコンパイルすると、Program space=72.3%使用)

《その他》

実験風景
 左は実験風景です。
 (センサの前側を9度程傾けています)
 中央の丸い物は水平器です。

 このセンサは、タップ/ダブル・タップ機能や
 自由落下機能にFIFO型バッファ内蔵など
 色々機能を持っていますが、今回は利用して
 いないのでその内にでも実験をして見ようとは
 思っていますがぁ.....
 このセンサでSPI接続の記事こちらを見て下さい。

 尚、こちら(MMA7361)のモジュールは、
 計測レンジは±1.5/6gのみですが
 アナログでの出力となっています。

 また、こちら(KXR94-2050)のセンサを使ったArduinoの記事は、こちらの頁を参照下さい。

 その内に"振動(動き)"を検出して万歩計の実験を行おうと思っていますがぁ....



記事一部追記(*4) 2016/07/23
MPLAB X用に記事変更(*3) 2015/10/10
追記(*2) 2014/03/29
追記(*1) 2014/03/21


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.