こんばんは、Tomです。今日は、昨日とは異なり、曇りそして雨の寒々しい日でした。昨日の様な日だと、春が近づいた様な気がしますが、今日の様な日は、まだまだ冬だなぁ〜〜と思ってしまいます。でもね、確実に春は近づいていますね。
さて、今日うちのカミさんは、地域の婦人部で日帰り温泉のイベントだとかで不在になるし、外も寒いので、インドアの活動を行うことにしました。
今日の様に纏まって時間が取れる日は、Arduinoのプログラムを行うのにもってこいですね。
1. ワイヤレスリモコンの材料
さて、念願のパワーアンプの調整も昨日終了し、とても綺麗な音でタンノイ君をドライヴしてくれる様になりました。
そこで、次のステップは、そのパワーアンプ達電源をワイヤレスリモコンでON/OFFする事が課題です。
それをコントロールするのが、このArduinoです。
これは、Tomの様なオッサンでも、簡単にプログラムを組んで、様々な入出力をコントロールする事ができる、魔法の様なワンチップマイコンです。
そして、今回インターフェイスとして使用するのが、赤外線リモコンを受信するためのセンサーです。
アンプを製作していたので暫く、Arduinoを弄っていなかったので、オジサンのTomはすっかり使い方を忘れてしまいました。そこで、今日はこの本の力を借りて、おさらいをしながら、進めます。
2. Arduinog繋がらない!
前回Arduinoを弄っていたのは、確か5〜6月の事でした。
http://d.hatena.ne.jp/tomtom1ono/20160531/1464694079
記事一覧から。この記事の戦後の記事をご覧ください。
その後、Microsoftの半強制的なWindows10へのアップグレードがあった為、TomはArduinoが上手く接続出来るかどうか、とても不安でした。何故なら、Windows10にアップデートしたため、デジタルオシロも動かなくなり、四苦八苦したからです。なので、USBからハードを直接コントロールするArduinoなら、絶対におかしくなると思っていたのです。
そしたら案の定、以前動いていたプログラムをArduino に書き込もうとしたら、全く書き込めませんでした。
そこで、Arduinoのサイトから最新のIDEとドライバーをダウンロードして、インストール。
それでも、最初はNGでした。
でも、デバイスマネージャのドライバーから最新のドライバーを上書きしたら、なんとか通信できる様になりました。 メデタシ、めでたし。
3. 基本動作の確認
Arduinoの良いところは、様々なライブラリーが有って、それを組み合わせる事で、割と簡単にプログラムを組む事ができます。
今回は、以前使用した初心者が一番最初に使用する、brinkと言うLEDをオンオフするプログラムと、赤外線リモコンを受信して、シリアルモニターに文字を出力するプログラムを組み合わせてプログラムします。
先ずは、Arduinoが繋がったのでbrinkのプログラムをArduinoに書き込みます。
これで無事に動作することを確認出来ました。
4. リモコンプログラムを編集
つぎは、リモコンプログラムにbrinkのLED点灯プログラムを編集し、『1』の信号が来たらLEDを点灯し、『0』の信号が来たら消灯するプログラムを作ります。
結果、バッチリ上手く行きました。
5. 出力ポートを3個に増設
パワーアンプは、現在最低でも3台あり、タンノイ君とYAMAHAのNS1000Mは、パワーアンプで切り替えています。
そこで、このリモコン装置では、最低2個のON/OFF、拡張で3個のON/OFFが必要です。
そこで、今度は!出力ポートを3個に増設してLEDを点灯してみることにしました。
『1』の ボタン、『2』 のボタン、『3』のボタンをそれぞれ独立してONさせ、『0』のボタンで全ての電源が切れると言うプログラムです。
6.確認結果
確認結果は、OKです。
ウ〜ム、なかなかエ〜エンでないかい?
7. パネルのスモークを通しての受信確認
最後にフロントパネルのスモークアクリル板を通して、キチンと受信出来るかどうかを確認しました。
結果はバッチリです。
8.今回のスケッチ(プログラム)をご紹介します。(恥ずかしい〜。)
//IRリモコンコントローラ
#define IR_IN 9
#define IR_DATA_SIZE 100
byte ir_data[IR_DATA_SIZE];
byte ir_code[32];
byte ir_result;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
Serial.begin(9600);
pinMode(IR_IN, INPUT_PULLUP);
}
void loop() {
ir_result = ir_read(IR_IN);
if (ir_result > 0){
//Serial.println(ir_result,DEC);
print_comand(ir_result);
}
}
//データ受信
byte ir_read(byte ir_pin){
unsigned long now, last, start_at;
boolean stat;
start_at = micros();
//2.5秒以上入力がなかったら終了
while(stat = digitalRead(ir_pin)){
if(micros() - start_at > 2500000) return 0;
}
digitalWrite(13,HIGH);
for(int i = 0; i < IR_DATA_SIZE; i++){
ir_data[i] = 0;
}
start_at = last = micros();
for(int i = 0; i < IR_DATA_SIZE; i++){
//入力が反転するまで待ち(上限25ms)
while(1){
if(stat != digitalRead(ir_pin)) break;
//信号終了
if(micros() - last > 25000){
digitalWrite(13,LOW);
return ir_get_data();
}
}
now = micros();
ir_data[i] = (now - last)/100; //byteに格納するあため
last = now;
stat = !stat;
}
}
//データ解析
byte ir_get_data(){
int j = 0;
byte result = 0;
//1or0判定
for (int i = 3; i < 66; i+=2){
if(ir_data[i] > 10){
ir_code[j] = 1;
}else{
ir_code[j] = 0;
}
j++;
}
//データを数値化
for (int i = 0; i < 8; i++){
if(ir_code[i+16] == ir_code[i+24]){ //反転データチェック
result = 0;
break;
}else{
bitWrite(result,i,ir_code[i+16]);
}
}
return result;
}
//コマンド出力
void print_comand(byte ir){
switch (ir){
case 12:
digitalWrite(12, LOW); // turn the LED off by making the voltage LOW
digitalWrite(11, LOW); // turn the LED off by making the voltage LOW
digitalWrite(10, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
break;
case 16:
digitalWrite(12, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
break;
case 17:
digitalWrite(11, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
break;
case 18:
digitalWrite(10, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
break;
default:
;
}
}