delayMicroseconds()
パラメータで指定した時間(マイクロ秒単位)だけプログラムを一時停止する。1秒は1,000,000マイクロ秒である。
Arduinoリファレンス delayMicroseconds()
赤外線LEDとArduino M0 Proで学習リモコンをつくりかたかった
家にあるリモコンの赤外線信号をArduino M0 Proに接続した赤外線受信モジュール(動作電源3.3Vで使えるやつ)で読み取り、その情報をそのまま赤外線LEDで出力して学習リモコンを作ることにしました。
が、受信をうまくいっても送信がうまく行かず、、、試しに手元にあったArduino UNOで出力するとうまくいく。念のため、赤外線受信モジュールで赤外線LEDの信号をキャッチして調べてみると、Arduino UNOではほぼ近い値だったのに対し、Arduino M0 Proでは信号が凸凹と数値がずれていました。
原因はdelayMicroseconds()の精度
途方に暮れているときに出会った記事「Intel Edison for Arduino の delayMicrosecondsの精度が悪い件」が解決のヒントに。なんと、ArduinoのモデルによってdelayMicroseconds()
の精度が変わってくるらしい。。。
対処法
先ほどの記事「Intel Edison for Arduino の delayMicrosecondsの精度が悪い件」を参考に独自でwait()を実装。delayMicroseconds()
と差し替えると無事動作しました。
int ledPin = 13;
// 赤外線信号
unsigned int data[] = {▲▲,▲▲,▲▲,▲▲,▲▲,▲▲...};
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
sendSignal();
delay(3000);
}
/*
dataからリモコン信号を送信
*/
void sendSignal() {
int dataSize = sizeof(data) / sizeof(data[0]);
for (int cnt = 0; cnt < dataSize; cnt++) {
unsigned long len = data[cnt]*10;
unsigned long us = micros();
do {
// cntが偶数なら赤外線ON、奇数ならOFFのまま
digitalWrite(ledPin, 1 - (cnt&1));
// キャリア周波数38kHzでON/OFFするよう時間調整
wait(8);
digitalWrite(ledPin, 0);
wait(7);
// 送信時間に達するまでループ
} while (long(us + len - micros()) > 0);
}
}
/*
マイクロ秒単位で待つ
*/
void wait(signed long wait_time) {
signed long start_time = micros();
while ( micros() - start_time < wait_time) {};
}
おまけ
Arduino M0 Proは動作電源が3.3Vなため、そのままデジタルピンの出力で光らせようとすると電流が弱く全然家電が反応しません。そういうときはトランジスタを使って5Vから電源を確保するようにします。その辺りはまた改めてまとめたいと思います。