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

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

ただいまの
回答率

90.83%

  • Arduino

    475questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 105

yosei1127

score 1

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • y_waiwai

    2018/05/29 07:30

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

    キャンセル

  • yosei1127

    2018/05/29 10:48

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

    キャンセル

回答 2

checkベストアンサー

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/29 10:46

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

    キャンセル

0

解決の参考になったサイト

http://blog.livedoor.jp/kan0ken1/archives/51843697.html
https://plaza.rakuten.co.jp/cpu4edu/diary/201312030000/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.83%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Arduino

    475questions

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