質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

3971閲覧

ArduinoでanalogWrite()が正常に作動しない。

yosei1127

総合スコア5

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2018/05/28 13:16

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; } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/05/28 22:30

回路図はだせるでしょうか。LEDをどう接続してますか
yosei1127

2018/05/29 01:48

LEDはピン3番に接続していたのですが、ピン3番はMsTimerとPWN出力が競合するようで、ピンを5番に変えたところ正常に作動しました。 丁寧なご対応ありがとうございました。
guest

回答2

0

投稿2018/05/29 01:50

yosei1127

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

「analogWrite MsTimer2」で検索するとよいですが、analogWriteのPWM出力はタイマーを使用しますので場合により競合します。
出力ピンによって使うタイマーが異なるのでピンを変えればよいと思います。

投稿2018/05/29 00:59

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yosei1127

2018/05/29 01:46

昨日自分でも調べたところ、同様の内容の記事を見つけることができました。 ピン3番はMsTimerとPWN出力が競合するようで、ピンを5番に変えたところ正常に動作しました。 回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問