Uno / Leonardo用のPWMを使用した赤外線リモコン [Arduino]
以前、ATtiny13Aで作ったもののアレンジです。
delayMicroseconds() を使って疑似的にキャリア周波数を作ることもできるのですが、あまりエレガントな感じがしないので、キャリア周波数(38-40kHz)はPWMで作成し、信号の波形の作成はdelayMicroseconds() を使用することとしました。
UnoとLeonardoで動作確認しました。
デジタル10ピンとGNDに赤外線LEDを直結しています。(AVRの駆動力という点と、パルス出力をするという点でたぶん大丈夫?)
UnoとLeonardoとのスケッチ共用とするため、Timer/Counter 1 (16bit)を8bitで使用しています。
デジタル9ピンのAnalogWrite()は競合するので使えません。
delayMicroseconds() を使って疑似的にキャリア周波数を作ることもできるのですが、あまりエレガントな感じがしないので、キャリア周波数(38-40kHz)はPWMで作成し、信号の波形の作成はdelayMicroseconds() を使用することとしました。
UnoとLeonardoで動作確認しました。
デジタル10ピンとGNDに赤外線LEDを直結しています。(AVRの駆動力という点と、パルス出力をするという点でたぶん大丈夫?)
// PWMで38kHzをつくる赤外線リモコン (Arduino Uno, Leonardo共通版)
#include "wiring_private.h" // sbi(), cbi() を使うため
#define F_IR 38000L // キャリア周波数 (NEC, AEHAは38kHz, SONYは40kHz)
void setup() { // OC1B (Arduino的には10番ピン) を 38kHz PWM 出力にする。
pinMode( 10, OUTPUT ); // 出力方向にする
TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (1<<WGM11) | (1<<WGM10);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (0<<CS02) | (1<<CS01) | (0<<CS00);
// 比較出力選択 COM1B1-0 : 10 で 高速PWM時OC1Bが BOTTOMでHIGH、比較一致でLOW, 00で切断
// 波形生成種別 WGM13-0 : 1111 で 高速PWM動作
// クロック選択 CS12-0 : 010 で 8分周 (000 で停止、001で分周なし など)
OCR1AL = F_CPU / F_IR / 8 - 1; // (( 16MHz / 38kHz ) / 8(分周) ) - 1 = 51
OCR1BL = OCR1AL / 3; // duty比を1/3にする OCR1B / 3 = 17
}
void loop() {
sendIrNEC( 0xE41BBF40 ); // REGZA: 0x40 0xBF (TOSHIBA), 0x1B (Ch.Up), 0xE4 (~Ch.Up)
sendIrNEC( 0xE41BBF40 ); // 2回送ってみる。
delay(5000); // 5秒のdelay
}
void sendIrNEC( uint32_t d ) {
// NEC形式の時間単位(T)は、9/16 msec = 562.5usec
sbi(TCCR1A, COM1B1); delayMicroseconds( 9000 ); // リーダ ON (16T)
cbi(TCCR1A, COM1B1); delayMicroseconds( 4500 ); // リーダ OFF (8T)
for(uint16_t i=0; i<32; i++) { // データ 32ビット分処理
sbi(TCCR1A, COM1B1); delayMicroseconds( 562 ); // データ ON (1T)
cbi(TCCR1A, COM1B1); delayMicroseconds( (d>>i) % 2 ? 1687 : 562 ); // データ OFF (0:1T/1:3T)
}
sbi(TCCR1A, COM1B1); delayMicroseconds( 562 ); // トレーラ ON (1T)
cbi(TCCR1A, COM1B1); delayMicroseconds( 39937 ); // トレーラ OFF (71T) (計192T)
}
UnoとLeonardoとのスケッチ共用とするため、Timer/Counter 1 (16bit)を8bitで使用しています。
デジタル9ピンのAnalogWrite()は競合するので使えません。