SSブログ

Uno / Leonardo用のPWMを使用した赤外線リモコン [Arduino]

以前、ATtiny13Aで作ったもののアレンジです。
delayMicroseconds() を使って疑似的にキャリア周波数を作ることもできるのですが、あまりエレガントな感じがしないので、キャリア周波数(38-40kHz)はPWMで作成し、信号の波形の作成はdelayMicroseconds() を使用することとしました。

uno_ir_pwm.jpg
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()は競合するので使えません。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。