SSブログ

202duino でPWMを使ってリモコン送信 [Arduino]

ATtiny202 の PWM の練習にリモコン信号の作成をしてみました。
2年ほど前にテレビをSONY製に替えたので、それで試してみます。
sirc_remocon.jpg
通常のリモコンでは電源はトグル操作になっていますが、テレビの状態にかかわらずON/OFFを操作する隠しコードがあるということでネットから探してきました。
sirc_tvpwrcode.png
PWMは40kHzです。8bitのPWMだと、CPUが20MHzの場合、20MHz / 256(8bitの最大パルス周期) = 78.125 KHz となり、これより周波数を上げることはできても下げることはできません。そこで2分周して、20MHz / 2分周 / 40kHz = 250 で、TOP値を255 (8bit)以内に収めました。

TCA(16-bit Timer/Counter Type A) は megaTinyCore の時間関連で使われているようなので、TCB(16-Bit Timer/Counter Type B) (tone()やServoで使用?)を使用しました。

ATtiny202の場合、TCB0からのPWM出力はWO (Waveform Output)であり、SOIC(8-Pin)の2番、Pin nameでPA6、megaTinyCore での 0番となります。
// Infrared remote control with 40kHz PWM (ATtiny202, SIRC version)
inline void   TCB0_PWM_ON()   { TCB0.CTRLB |=  TCB_CCMPEN_bm; }     // CCMPEN enable
inline void   TCB0_PWM_OFF()  { TCB0.CTRLB &= ~TCB_CCMPEN_bm; }     // CCMPEN disable

void setup() {                                          // Create 40kHz
  TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm;   // 20MHz / 2 / 250 -> 40kHz
  TCB0.CTRLB = TCB_CNTMODE_PWM8_gc;                     // 8-Bit PWM mode
  TCB0.CCMPL = F_CPU / 2 / 40000 - 1;                   // top value (249@20MHz, 199@16MHz for 40kHz)
  TCB0.CCMPH = F_CPU / 2 / 40000 / 3;                   // duty cycle = 1/3
  PORTA.DIRSET = PIN6_bm;                               // WO (PA6, megaTinyCore:P0)
}

void loop() {
  sendIrSIRC202( 46 | 1UL << 7 );                       // SONY TV ON  (cmd:46(7bit), adrs:1(5bit))
  sendIrSIRC202( 46 | 1UL << 7 );                       //   repeat 3 times
  sendIrSIRC202( 46 | 1UL << 7 );
  delay( 5000 );
  sendIrSIRC202( 47 | 1UL << 7 );                       // SONY TV OFF (cmd:47(7bit), adrs:1(5bit))
  sendIrSIRC202( 47 | 1UL << 7 );                       //   repeat 3 times
  sendIrSIRC202( 47 | 1UL << 7 );
  delay( 5000 );
}

void sendIrSIRC202( uint32_t d ) {                      //   T = 0.60msec
  uint8_t  b = (d & 0xF8000) ? 20 : 
               (d & 0x07000) ? 15 : 12;                 // number of bits
  uint16_t usON, usTrailer = 42000;                     // 70T = interval(75T) - leader(5T)
  TCB0_PWM_ON();  delayMicroseconds( 2400 );            // leader ON  (4T)
  TCB0_PWM_OFF(); delayMicroseconds(  600 );            // leader OFF (1T)
  for(uint8_t i = 0; i < b; i++) {                      // data(command + address)
    usON = ((d>>i)&1) ? 1200 : 600;                     // data(0:1T / 1:2T)
    TCB0_PWM_ON();  delayMicroseconds( usON );          // data ON
    TCB0_PWM_OFF(); delayMicroseconds(  600 );          // data OFF (1T)
    usTrailer -= (usON + 600);                          // trailer
  }
  delayMicroseconds( usTrailer );
}

修正:usTrailer = 70 x 0.6msec = 420usecでなくて42000usecだった。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

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