Arduinoと加速度センサを使った水平器
Arduinoと加速度センサを使用して水平器の作成
今回は3軸加速度センサを使用して、物体の角度の取得をしてみました。
そして、角度を取得するだけでは楽しくないので、水平器を作ってみました。
<a href="https://amzn.to/4b18Juz"><img class="wp-image-860 alignnone" src="https://electwork.net/wp-content/uploads/2023/12/V-ARD-UNO-R4-a-1000x750-1.jpg" alt="" width="413" height="310" /></a>
<span style="font-size: 150%;"><a href="https://amzn.to/4b18Juz">Amazonで購入 </a> <a href="https://a.r10.to/hUrfbc">楽天で購入</a></span>
準備するもの
今回、準備したものはこちらになります。
- Auduino UNO
- 3軸アナログ加速度センサ KXR94-2050
- 赤色LED ×11
- カーボン抵抗 220Ω
- ジャンパー線 たくさん
となります。
3軸加速度センサ"KXR94-2050"とは
加速度センサとは、文字通りセンサに加わっている加速度を取得できるセンサになっています。
加速度センサでできること
-
- 加速度を取得することができれば、時間で積分することで速度が取得できる。
- 速度を積分することで、距離を取得することができる。
- どの軸に重力加速度が加わっているかを検出して、平行度や傾き角度を取得できる。
- 3軸あることで平行移動の動きや衝撃、振動、落下など、物体の状態確認にも利用できる。
など、とても便利なセンサで、加速度センサ自体は、振動計などの測定機器からロボットやロケットの姿勢制御などあらゆるところで使用されています。
使用する、3軸加速度センサ"KXR94-2050"は、図のようにDIP化されたものを秋月電子やアマゾンで購入することができます。
3軸加速度センサ KXR94-2050 DIP化モジュール
データシートや取扱説明書はこちらになります。
<KXR94-2050>DataSheet
<KXR94-2050>DIPモジュール取扱説明書
早速、この三軸加速度センサを使用して、物体の角度を検出し、Arduinoで水平器を作成していきます。
Arduino水平器の回路図と配線図の作成
以下が、回路図と配線図になっています。
今回は加速度センサを載せているブレッドボードと、LEDを載せているブレッドボードを分けて、加速度センサ部だけを動かせるようにしています。
また、今回使用する水平器自体には、加速度センサのX軸の値しか使用しませんが、Y軸・Z軸の数値も読み取れるようにしています。
実際に組み立てた配線がこちらになります。
水平器のArduinoプログラム作成
加速度センサを使用した水平器のプログラムはこのように作成しました。
#define AXISXPIN 0 #define AXISYPIN 1 #define AXISZPIN 2 #ifndef M_PI #define M_PI (3.1415926535897932384626433832795) #endif int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; //LEDに使用するピン番号 int a, a_before; int numberOfledPins = sizeof(ledPins) / sizeof(ledPins[0]); // 使用するLEDの数 void setup() { for (int i = 0; i < numberOfledPins; i++) { pinMode(ledPins[i], OUTPUT); // ledPinsを出力モードに設定する } // ボーレートを指定して通信開始 //Serial.begin(9600); } double Map( int iIn, int iIn1, int iIn2, double dOut1, double dOut2, boolean bConstrain = false ) //iTn センサから出力されるAD変換値 //iTn1, iTn2 使用範囲での最大、最小AD変換値 { double dValue = (iIn - iIn1) * (dOut2 - dOut1) / (iIn2 - iIn1) + dOut1; if( bConstrain ) { double dOutMin, dOutMax; if( dOut1 < dOut2 ) { dOutMin= dOut1; dOutMax= dOut2; } else { dOutMin= dOut2; dOutMax= dOut1; } if( dOutMin > dValue ) { return dOutMin; } if( dOutMax < dValue ) { return dOutMax; } } return dValue; } void loop() { // ピン値の読み取り int ADC_X = analogRead(AXISXPIN); int ADC_Y = analogRead(AXISYPIN); int ADC_Z = analogRead(AXISZPIN); // ピン値の出力 //Serial.print( "Value : " ); //Serial.print( ADC_X ); //Serial.print( ", " ); //Serial.print( ADC_Y ); //Serial.print( ", " ); //Serial.print( ADC_Z ); //Serial.print( "\n" ); // ピン値をsinθ値に変換(第2、第3引数は各軸の-90度、90度における値を使用する) double rotateX = Map( ADC_X, 292, 732, -1.0, 1.0, true ); double rotateY = Map( ADC_Y, 310, 740, -1.0, 1.0, true ); double rotateZ = Map( ADC_Z, 384, 780, -1.0, 1.0, true ); double dAngleX = asin(rotateX) * 180.0 / M_PI; double dAngleY = asin(rotateY) * 180.0 / M_PI; double dAngleZ = asin(rotateZ) * 180.0 / M_PI; a = 12 -((ADC_X - 292)/40) ; if(a<2){ a = 2; }else if(a>12){ a = 12; } digitalWrite(a, HIGH); if (a != a_before){ digitalWrite(a_before, LOW); } a_before = a; //Serial.println( a ); // 角度の出力 /*Serial.print( "Angle[deg] : " ); Serial.print( dAngleX ); Serial.print( ", " ); Serial.print( dAngleY ); Serial.print( ", " ); Serial.print( dAngleZ ); Serial.print( "\n" ); Serial.print( "\n" ); Serial.print( a ); */ delay( 5 ); }
24行目から49行目は出力されたアナログ値をsinθ値に変換する関数です。
この時、iTn1, iTn2はセンサを90° と-90° に傾けた時のAD変換値が挿入されれます。
69行目から75行目は取得したAD変換値から角度を計算しています。
この時、
double rotateX = Map( ADC_X, 292, 732, -1.0, 1.0, true );
の292が加速度センサをX軸を中心に-90° 、732が90° 傾けた値です。
この数値はセンサの個体によって変わってくるので、各自で調整が必要になります。
77行目から87行目はLEDを点灯させるためのプログラムです。
使用する出力ピンによって数字が変わるので注意してください。
各箇所でコメントアウトしていますが、シリアル通信によって角度祖取得できるようになっています。
実際に動かすと以下の動画のようになります。
角度によってLEDの光が移動しているのがわかると思います
また、水平移動に合わせてLEDの光が移動しています。
このような動作になれば正常に動いています。
今回は1軸しか使用しませんでしたが、多くの軸を使うことでもっといろいろなことができるようになります。
今後は、2軸の水平器とかを作成してみたいと思っています。