今回は、久々にマイコンボードArduino Nanoとロータリーエンコーダを使って、LEDの明るさを調整してみようという試みです。
ロータリーエンコーダの出力でPWM値を変化させて、その値を使ってLEDの明るさを変化させてみます。
このページは「マイコンLチカ道場 Arduino編」の「2-3:ロータリーエンコーダでLチカの明るさをコントロール」に対応するページです。
ロータリーエンコーダとは
ロータリーエンコーダとは、回転による機械的変位を電気信号に変換し、位置や速度を検出するセンサです。
今回使うのはインクリメンタル型とよばれるもので、回転に応じてパルスを出力するタイプです。
通常のボリューム(可変抵抗)は、一定の角度まで回しきると止まりますが、無限にクルクル回転するようなものが今回使うロータリーエンコーダです。
マウスのホイールなど、身近な物によく使われていますね。
今回使用するロータリーエンコーダ
アルプス電気製:EC12E2420801(24クリックタイプ)
秋月電子で購入しました。
ブレッドボードに挿せるようにリード線をはんだ付けしています。
ピン配列は左からA、C、Bです。
動作時の波形をオシロスコープで確認してみました。
右回り時の波形
A相(上側)がLoに変化時、B相(下側)はHiになっています。
左回り時の波形
A相(上側)がLoに変化時、B相はLoになっています。
このようなA相とB相の位相の違いを見て、回転方向を検出します。
※上記の波形は、フィルタ回路は無しの状態です。時間軸を拡大するとチャタリングが見られるため、メーカー推奨のフィルタ回路を入れてみました。
回路図
今回の実験での回路図は下記になります。
マイコンボードはArduino nanoを使用。
ロータリーエンコーダの回路は、5Vへのプルアップ抵抗と、
メーカーホームページ記載の推奨フィルタ回路(R3、R4とC1、C2)を入れています。
部品リスト
品名 | 参照名 | 数量 | 数値・仕様 |
マイコンボード | A1 | 1 | Arduino nano |
LED | D1 | 1 | 青色LED |
ロータリーエンコーダ | SW1 | 1 | アルプス電気製 EC12E2420801 |
抵抗器 | R1、R2 | 2 | 10kΩ |
抵抗器 | R3、R4 | 2 | 10kΩ |
抵抗器 | R5 | 1 | 220Ω |
コンデンサ | C1、C2 | 2 | 0.01μF(103) |
プログラム(スケッチ)
【やりたいこと】
・ロータリーエンコーダを回してPWM値を可変
・ロータリーエンコーダ用のライブラリ「Encoder.h」(Encoder by Paul Stoffregen)を使用
・PWM値でLEDを点灯
・確認用に、シリアルモニタでPWM値とロータリーエンコーダの値を表示させる
上記の内容でプログラムを作ってみました。
//ライブラリ読み込み
#include <MsTimer2.h> //タイマー割込み用ライブラリ
#include <Encoder.h> //ロータリーエンコーダ用ライブラリ
//ロータリーエンコーダのA相とB相を接続するピン番号を設定
const int pinA = 2;
const int pinB = 3;
Encoder myEnc(pinA, pinB);
//ロータリーエンコーダの現在位置と前回位置を保持する変数
volatile long oldPosition = 0;
volatile long newPosition = 0;
//LEDを接続するピン番号を設定
const int ledPin = 9;
// LEDの明るさ(PWM値)を保持する変数
volatile int brightness = 0;
//ロータリーエンコーダの割り込み処理関数
//ライブラリから得た数値を保存
void rotEnc() {
newPosition = myEnc.read();
}
void setup() {
//3ms毎にロータリーエンコーダ関数を実行
MsTimer2::set(3, rotEnc);
MsTimer2::start();
//デバッグ用のシリアル通信
Serial.begin(115200);
}
void loop() {
//ロータリーエンコーダの数値が変化した場合
if (newPosition != oldPosition) {
//回転方向が正方向だった場合brightness(明るさ)を1増やす
//負方向だった場合brightnessを1減らす
if (newPosition > oldPosition) {
brightness++;
} else {
brightness--;
}
//brightness(明るさ)がPWMの0から255の範囲内に収まるように調整
brightness = constrain(brightness,0,255);
//LED出力ピンにbrightnessの値でアナログ出力(PWM出力)する
analogWrite(ledPin, brightness);
//シリアルモニタ※デバッグ用
//現在位置newPosition、前回位置oldPosition、明るさbrightness の値を表示する。
Serial.print("newPosition:");
Serial.println(newPosition);
Serial.print("oldPosition:");
Serial.println(oldPosition);
Serial.print("brightness:");
Serial.println(brightness);
// 前回位置oldPosition を現在位置newPosition に更新する
oldPosition = newPosition;
}
delay(10);
}
動作確認
ブレッドボードで組んで動作確認してみました。
ロータリーエンコーダを回すと、PWMでLEDの明るさを増減させることが出来ました。
また、シリアルモニタでPCにPWM値とロータリーエンコーダの数値を送って表示させることが出来ます。
上記のプログラムでは、右回りで明るさが減少、左回りで明るさが増加という動作になりました。
右回りで増加の方が直感的なので、A相とB相の接続を逆に変更しました。
(プログラムでピンを変更しても良かったかも)
上記の写真では、A相を3番ピンへ、B相を2番ピンへ接続しています。
確認用のシリアルモニタ出力が下記になります。
ロータリーエンコーダを回転させると、newPositionの数値が変化します。
その変化が前回値(oldPosition)より大きいと、明るさ(brightness)を+1、
小さい場合-1とするようなプログラムです。
brightnessの範囲はPWM値の0~255で制限して、それ以上・以下にならない様にしています。
ちゃんと255でカンストしています。
反対に回すと、brightnessが減ってきます。
減らし続けた場合も、0以下にはなりません。
255に到達するまでかなり回転させないといけないので、2か3づつ数値を増加させるようにしても良いですね。
まとめ
秋月電子で買ったロータリーエンコーダ(EC12E2420801)とアルデュイーノナノを使って、PWMでLEDの明るさを可変させることが出来ました。
普通の可変抵抗と違って無限にクルクル出来るので、電子ボリュームや操作関係のスイッチとしても利用できそうですね。
参考リンク
ロータリーエンコーダには、軸を垂直に押し込むことでスイッチになるタイプのものもあります。
下記はその例です。(Amazonで購入しました。)
基板実装されたモジュールになっており、プルアップ抵抗も実装されています。
このモジュールを使っても、同様に動作を確認できました。