Arduinoと加速度センサを用いて,加速度の増減によってLEDの状態が変化するプログラムを書いているのですがうまくanalogWrite()が作動しません。
具体的な挙動目標としては、
Arduino本体をゆすり続ける(加速度の値が蓄積される)とLEDの点滅がだんだんと早くなり、しまいにLEDが消えるというものです。
また、ここでいう点滅とはdigitalWrite()のようなONE,OFFの二通りではなくanalogWriteを用いた穏やかな点滅です。(こちらのサイトを参考にさせていただきました。)
当初はこちらのサイトのように、点滅をdelay()を使って制御するつもりだったのですが、私のプログラムは常に加速度の値を取得し続けているため、delay()のかわりに、MsTimer2というライブラリを用いてタイマー割り込みを利用することにしました。
[i]の数値の数値は予想通りに変化することを確認ため、あとはanalogWrite(3, i)を用いて動くぞーと思っていたのですが、iの値はうまく変化しているのになぜかLEDが点灯せず。
どこが悪いかわからなかった為、いろいろ検証したところ
・iの値が255の時は正常に点灯する。(それ以外の値では点かない)
・タイマー割り込みの部分をコメントアウトするとanalogWrite()がどんな値でも正常に作動することが分かりました。
このMsTimerが悪さをしているだろうなというところまではわかったのですが、具体的になぜこのライブラリを使用するとanalogWrite()が正常に作動しなくなるのか理由がわかりませんでした。
具体的な改善案などを教えてくださるとありがたいです。
#include <MsTimer2.h> #include <Wire.h> // デバイスアドレス(スレーブ) uint8_t DEVICE_ADDRESS = 0x53; // XYZレジスタ用のテーブル(6byte) uint8_t RegTbl[6]; //加速度の変化を保存する変数 double trans = 0; //加速度変化の蓄積ステータス double state = 0; //複数のプログラムが同時に動くことを防ぐ int MODE = 0; //一回前の加速度を保存する変数 double oldX = 0; double oldY = 0; double oldZ = 0; //時間 unsigned long stay = 0; unsigned long atTime = 0; volatile boolean tim1msF; volatile boolean tim5msF; volatile boolean tim10msF; volatile boolean tim100msF; // タイマー 100msフラグ volatile boolean tim1SecF; // タイマー 1Secmsフラグ int tim1msCnt = 0; int tim5msCnt = 0; int tim10msCnt = 0; int tim100msCnt = 0; //照度 int i = 0; int flag = 0; void setup() { Serial.begin(9600); // マスタとしてI2Cバスに接続する Wire.begin(); // DATA_FORMAT(データ形式の制御) Wire.beginTransmission(DEVICE_ADDRESS); // DATA_FORMATのアドレス Wire.write(0x31); // 「最大分解能モード」 及び 「±16g」 (0x0B == 1011) Wire.write(0x0B); // 「10bit固定分解能モード」 及び 「±16g」にする場合 (0x03 == 0011) // Wire.write(0x03); Wire.endTransmission(); // POWER_TCL(節電機能の制御) Wire.beginTransmission(DEVICE_ADDRESS); // POWER_CTLのアドレス Wire.write(0x2d); // 測定モードにする Wire.write(0x08); Wire.endTransmission(); //D3pinをアウトプットに設定 pinMode(3, OUTPUT); MsTimer2::set(1, timer1mS); MsTimer2::start(); } void timer1mS() { tim1msF = true ; // 1mSec毎 tim1msCnt += 1; if (tim1msCnt >= 5) { tim1msCnt = 0; tim5msF = true; //10mSec毎 tim5msCnt += 1; if (tim5msCnt >= 2) { tim5msCnt = 0; tim10msF = true;// 10mSec毎 tim10msCnt += 1; if (tim10msCnt >= 10) { tim10msCnt = 0; tim100msF = true;// 100mSec毎 tim100msCnt += 1; if (tim100msCnt >= 10) { tim100msCnt = 0; tim1SecF = true;// 1Sec毎 } } } } } void loop() { // ******* 毎1mS の処理******************* if (tim1msF) { tim1msF = false ; if ((MODE == 3 || MODE == 4) && state >= 40000 && state < 60000) { MODE = 4; if (flag == 0) { i += 2; //analogWrite(3, i); if (i > 255) { flag = 1; } } if (flag == 1) { i -= 2; //analogWrite(3, i); if (i < 0) { flag = 0; } } } } // ******* 毎5mS の処理******************* if (tim5msF) { tim5msF = false ; if ((MODE == 2 || MODE == 3 || MODE == 4) && state >= 20000 && state < 40000) { MODE = 3; if (flag == 0) { i += 2; //analogWrite(3, i); if (i > 255) { flag = 1; } } if (flag == 1) { i -= 2; //analogWrite(3, i); if (i < 0) { flag = 0; } } } } // ******* 毎10mS の処理******************* if (tim10msF) { tim10msF = false ; if ((MODE == 1 || MODE ==2 ||MODE == 3) && state >= 200 && state < 20000) { MODE = 2; if (flag == 0) { i += 2; if (i > 255) { flag = 1; i = 255; } } if (flag == 1) { i -= 2; if (i < 0) { flag = 0; i = 0; } } } } // ******* 毎100mS の処理******************* if (tim100msF) { tim100msF = false ; search(); } // ******* 毎1Sec の処理******************* if (tim1SecF) { tim1SecF = false ; lights(); } //Serial.println(state); //Serial.println(stay); Serial.println(i); //Serial.println(MODE); analogWrite(3, i); }
void lights () { //スイッチON if (MODE == 0 && state > 150) { i = 255; MODE = 1; } //加速度に30秒以上変化がないときOFF if (MODE == 1 && state == 0 && stay > 30000) { i = 0; oldX = 0; oldY = 0; oldZ = 0; stay = 0; state = 0; trans = 0; MODE = 0; } //動きがなくても30秒間は点灯 if (MODE == 2 && state == 0 && stay <= 30000) { MODE = 1; i = 255; } //加速度の蓄積が一定量を超えたときライトをOFFにする。 if (MODE == 4 && state >= 60000) { i = 0; oldX = 0; oldY = 0; oldZ = 0; stay = 0; state = 0; trans = 0; MODE = 0; delay(5000); } }
void search() { // XYZの先頭アドレスに移動する Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(0x32); Wire.endTransmission(); // デバイスへ6byteのレジスタデータを要求する Wire.requestFrom(DEVICE_ADDRESS, 6); // 6byteのデータを取得する int i; for (i = 0; i < 6; i++) { while (Wire.available() == 0 ) {} RegTbl[i] = Wire.read(); } // データを各XYZの値に変換する(LSB単位) int16_t x = (((int16_t)RegTbl[1]) << 8) | RegTbl[0]; int16_t y = (((int16_t)RegTbl[3]) << 8) | RegTbl[2]; int16_t z = (((int16_t)RegTbl[5]) << 8) | RegTbl[4]; //前回の計測からの加速度の変化を計算 //その時三軸の中で最も大きい値を保存 trans = abs(oldX - x * 0.0392266); if (trans < abs(oldY - y * 0.0392266)) { trans = abs(oldY - y * 0.0392266); } if (trans < abs(oldZ - z * 0.0392266)) { trans = abs(oldZ - z * 0.0392266); } //150は静止した状態でも計測される誤差 if (trans > 200) { state = state + trans; } // 各XYZ軸の加速度(m/s^2)を出力する //Serial.print("X : "); //Serial.print( x * 0.0392266 ); //Serial.print(x); oldX = x * 0.0392266; //Serial.print(" Y : "); //Serial.print( y * 0.0392266 ); //Serial.print(y); oldY = y * 0.0392266; //Serial.print(" Z : "); //Serial.print( z * 0.0392266 ); oldZ = z * z * 0.0392266; //Serial.println(" m/s^2"); //時間経過とともに加速度変化の蓄積地(move)の蓄積地を減らす(つまり点滅を減らす) if (state > 0) { state -= 100; stay = 0; atTime = millis(); //動きがなくなったら待機時間を保持するよう } else if (state <= 0) { stay = millis() - atTime; state = 0; } }
回答2件
あなたの回答
tips
プレビュー