202duino でPWMを使ってリモコン送信 [Arduino]
ATtiny202 の PWM の練習にリモコン信号の作成をしてみました。
2年ほど前にテレビをSONY製に替えたので、それで試してみます。
通常のリモコンでは電源はトグル操作になっていますが、テレビの状態にかかわらずON/OFFを操作する隠しコードがあるということでネットから探してきました。
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番となります。
修正:usTrailer = 70 x 0.6msec = 420usecでなくて42000usecだった。
2年ほど前にテレビをSONY製に替えたので、それで試してみます。
通常のリモコンでは電源はトグル操作になっていますが、テレビの状態にかかわらずON/OFFを操作する隠しコードがあるということでネットから探してきました。
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だった。
2023-06-01 09:48
nice!(0)
コメント(0)
コメント 0