ふわっとLチカをスイッチでオンオフ【マイコンLチカ道場 Arduino編 1-5】

スイッチオンでPWMでLEDが点灯し始める時の波形Arduino
スポンサーリンク

はじめに

このページは「マイコンLチカ道場 Arduino編」の「1-5:ふわっとLチカをスイッチでオンオフ」に対応するページです。PWMでふわっと点滅しているLEDをスイッチでオンオフするような動作をさせてみます。
今回は、MsTimer2ライブラリを使用して、割り込みでスイッチ入力を使う方法を試してみました。

前回の「1-4:ふわっとLチカ」と「1-2:ボタンを押す度にLチカの状態が反転」の合わせ技のようなイメージです。

スポンサーリンク

回路図とブレッドボード接続図

今回の回路図・接続は上記の「1-2:ボタンを押す度にLチカの状態が反転」と同じです。
1個の青色LEDと、1個のタクトスイッチを使用します。プルアップ抵抗は内蔵ではなく、外付けとしています。
ピン9に並列で追加しているコンデンサと抵抗は、PWM波形を鈍らせてオシロで見るためのCRフィルタです。(C=1μF、R=10kΩ)オシロで見ない場合は無くても問題ありません。

回路図
回路図
ブレッドボード接続イメージ
ブレッドボード接続イメージ

プログラムを書いてみる

今回のプログラムが下記になります。

#include <MsTimer2.h>

const int LED1 = 9; //LEDを接続するピン(PWM出力490Hz:3,9,10,11、980Hz:5,6)
const int wait = 2; // 点滅の速さを決めるウェイト時間(ms)
int led_width = 0; //ledのPWM幅用の変数

const int SW1 = 2; //スイッチを接続するピン
int sw_state = HIGH; //スイッチの状態保存用の変数
int sw_latch = HIGH; //スイッチのラッチ用の変数
int led_state = LOW; //LEDの状態保存用の変数

void setup() {
  pinMode(LED1, OUTPUT); //LED1ピンを出力にする
  pinMode(SW1, INPUT); //SW1を入力に設定
  MsTimer2::set(50, sw_time); //50ms毎に関数sw_timeを実行
  MsTimer2::start();  //割り込み有効
}

void loop() {
  for (led_width = 0; led_width <= 255; led_width +=1){
    if (led_state == HIGH){         //led_stateがHIGHの場合
      analogWrite(LED1, led_width); //LED1をPWMで点灯させる
    } else {
      analogWrite(LED1, 0); //LED1を消灯
    }
    delay(wait); //ウェイト時間
  }
  for (led_width = 255; led_width >= 0; led_width -=1){
    if (led_state == HIGH){         //led_stateがHIGHの場合
      analogWrite(LED1, led_width); //LED1をPWMで点灯させる
    } else {
      analogWrite(LED1, 0); //LED1を消灯
    }
    delay(wait); //ウェイト時間
  }
}

void sw_time(){
  sw_state = digitalRead(SW1); //SW1の状態を読み込み、sw_stateに代入
  if (sw_latch == HIGH && sw_state == LOW){
    led_state = !led_state; //led_stateの変数を反転
  }
  sw_latch = sw_state; //sw_stateの状態をsw_latchに代入
}

主な動作の説明はコメント文に記載しています。今回は、ミリ秒単位で指定した時間で関数を呼び出すことが出来る、MsTimer2ライブラリを使用しています。初っ端に「#include <MsTimer2.h>」でライブラリを呼び出します。インストールされていない方は下記の方法でライブラリをインストールできます。

ライブラリMsTimer2のインストール方法
  • Arduino IDEの上部メニューから「ツール」⇒「ライブラリを管理」を選択し「ライブラリマネージャ」を表示させます。
  • ライブラリマネージャの右上の入力部にMsTimer2と打ち込むと、検索結果に表示されるので、インストールをクリックします。
  • インストールされると、Arduino IDEの上部メニューの「スケッチ」⇒「ライブラリをインクルード」の”提供されたライブラリ“の一覧の中にMsTimer2があるので、選択するとスケッチに自動で「#include <MsTimer2.h>」が入力されます。

MsTimer2::set(50, sw_time)」で50ms毎に関数sw_timeを実行させています。関数はvoid sw_time()で記載している部分になります。ここで、スイッチの入力関係を処理しています。
なぜそうしたかと言うと、void loop()内のfor文のウェイト2ms×255で0.5秒以上、それが2つで1秒以上for文の中のループに捕まっていることになり、その間スイッチの入力判定が止まることになるからです。
MsTimer2で50ms毎にスイッチの処理を割り込ませることで、スイッチを押した時に直ちにLEDの点滅をON・OFFすることが出来ます。
実際の動作波形が下記になります。今回は50ms毎に割り込みを行っているので、その分のタイムラグがあります。

スイッチ入力でLED点滅開始時の波形
スイッチ入力でLED点滅開始時の波形
スイッチ入力でLED点滅停止時の波形
スイッチ入力でLED点滅停止時の波形

補足:上記スケッチの「analogWrite(LED1, 0);」がないとスイッチを押したら明るさの「増減が止まる」というような動作になります。

また、上記のプログラムだと点滅ON・OFFに関係なくマイコン内部のled_widthの値は増減しているため、スイッチを押したタイミングで光り初めの状態が安定しません。押したらふわっと光り始めるようにスケッチを直してみました。void loop()内の「if (led_state == HIGH)」をfor文のループの外に出しただけです。

#include <MsTimer2.h>

const int LED1 = 9; //LEDを接続するピン(PWM出力490Hz:3,9,10,11、980Hz:5,6)
const int wait = 2; // 点滅の速さを決めるウェイト時間(ms)
int led_width = 0; //ledのPWM幅用の変数

const int SW1 = 2; //スイッチを接続するピン
int sw_state = HIGH; //スイッチの状態保存用の変数
int sw_latch = HIGH; //スイッチのラッチ用の変数
int led_state = LOW; //LEDの状態保存用の変数

void setup() {
  pinMode(LED1, OUTPUT); //LED1ピンを出力にする
  pinMode(SW1, INPUT); //SW1を入力に設定
  MsTimer2::set(50, sw_time); //50ms毎に関数sw_timeを実行
  MsTimer2::start();          //割り込み有効
}

void loop() {
  if (led_state == HIGH){         //led_stateがHIGHの場合
    for (led_width = 0; led_width <= 255; led_width +=1){
      analogWrite(LED1, led_width); //LED1をPWMで点灯させる
      delay(wait); //ウェイト時間
    }
    for (led_width = 255; led_width >= 0; led_width -=1){
      analogWrite(LED1, led_width); //LED1をPWMで点灯させる
      delay(wait); //ウェイト時間
    }
  } else {
      analogWrite(LED1, 0); //LED1を消灯させる
  }
}

void sw_time(){
  sw_state = digitalRead(SW1); //SW1の状態を読み込み、sw_stateに代入
  if (sw_latch == HIGH && sw_state == LOW){
    led_state = !led_state; //led_stateの変数を反転
  }
  sw_latch = sw_state; //sw_stateの状態をsw_latchに代入
}

この時の動作波形が下記になります。スイッチを押してからPWM信号が増加し始めていることがわかります。
ただし、このプログラムではスイッチを押してからLEDがオフするまで、PWM信号が減少して0になるまで待つ必要が有ります。実際の動作を見ると、LEDがふわっと消えて終了するのでこちらのプログラムの方が自然な感じがしました。

スイッチ入力でLED点滅開始時の波形:スケッチ変更後
スイッチ入力でLED点滅開始時の波形:スケッチ変更後
スイッチ入力でLED点滅停止時の波形:スケッチ変更後
スイッチ入力でLED点滅停止時の波形:スケッチ変更後

まとめ

PWMでふわっと点滅しているLEDをスイッチでオンオフするような動作をさせることが出来ました。今回は、MsTimer2ライブラリを使用して、割り込みでスイッチ入力を使う方法を試してみました。
引き続き難しいLチカに挑戦していきましょう。

このページの実験は下記の商品で試すことが出来ます。
Arduino Uno Rev3 アルドゥイーノ ウノ ATmega328P【正規代理店品】プログラミング ロボット 電子工作 アルデュイーノ 正規品 アルディーノ 電子パーツ 電子工作キット
Arduinoオフィシャルストア
初めての方は正規品か、互換品でもUSB-シリアル変換にAtmega16U2が使われているものがオススメです。安価な互換品はCH340G等が使われており、トラぶると面倒かもしれません。
Arduino電子工作
スポンサーリンク
このページをシェアする
のぶをフォローする
スポンサーリンク
スポンサーリンク
のぶらぼ
タイトルとURLをコピーしました