Go Down

Topic: B&O infrared protocol (Read 3482 times) previous topic - next topic

Ion2

Mar 25, 2014, 10:02 am Last Edit: Mar 25, 2014, 06:50 pm by Ion2 Reason: 1
Hi,

I am trying to use my Arduino as a remote control for my Bang & Olufsen sound system. So far I found out the following about the protocol:
















Frequency:455 kHz
Coding: pulse distance (manchester biphase code)
Frame: 4 start bits + 16 data bits + 1 trailer bit + 1 stopbit
Data: 8 address bits + 8 command bits
Start-Bit 1: 200µs puls, 3125µs pause
Start-Bit 2: 200µs puls, 3125µs pause
Start-Bit 3: 200µs puls, 15625µs pause
Start-Bit 4: 200µs puls, 3125µs pause
0-Bit: 200µs puls, 3125µs pause
1-Bit: 200µs puls, 9375µs pause
R-Bit: 200µs puls, 6250µs pause, repetition of last bit
Trailer bit: 200µs puls, 12500µs pause
Stop bit: 200µs puls
Repetition: none
Pushbutton repetition: N-times repetition of original-frames within 100ms
Bit order: MSB first

(Source: http://www.mikrocontroller.net/articles/IRMP#B.26O & https://github.com/christianlykke9/Beomote/blob/master/Beomote.h line 9)

The GitHub Beomote project is a receiver only. The IR commands can be found here: https://github.com/christianlykke9/Beomote/blob/master/Commands.h

I would like to send IR commands and wrote the following little sketch for testing:

Code: [Select]
const int TVbuttonPin = 2;
const int BEO_IR =  13;

int TVbuttonState = 0;

void setup() {
 pinMode(BEO_IR, OUTPUT);      
 pinMode(TVbuttonPin, INPUT);    
}

void loop(){
 TVbuttonState = digitalRead(TVbuttonPin);

 if (TVbuttonState == HIGH) {      
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(3125);  // start bit 1
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(3125);  // start bit 2
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(15625); // start bit 3
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(3125);  // start bit 4
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 01: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 02: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 03: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 04: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 05: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 06: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 07: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 08: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(9375);  // data bit 09: 1 bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(3125);  // data bit 10: 0 bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 11: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 12: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 13: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 14: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 15: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(6250);  // data bit 16: repeat bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW); delayMicroseconds(12500); // trailer bit
   digitalWrite(BEO_IR, HIGH); delayMicroseconds(200); digitalWrite(BEO_IR, LOW);                           // stop bit
 }

}


The HEX code for "TV on" is: 0080
The BIN code for "TV on" is:  0000 0000 1000 0000

I believe, I am missing the carrier frequency to get it to work.
Is there somebody who can help me to understand how to do that?

Thank you!

AnalysIR

I manged to do it before using PWM, but you will need to study up on how to do it.

Try the timer1 ot Timerone library, as it supports PWM * should be able to do it using timer one.

If my memory is correct, you only get to within +/-  20khz of the 455 kHz, which is due to the granularity of the 16MHz timer & PWM.

IF you serach, you will find online clock calculators for AVR, which can also help.

Once you have PWM working just toglle it on & off to generate the marks/spaces of your signal.

Another option is to create a 555 timer circuit (ggogle) which generates the 455khz modulation signal & toggle that on/off from your sketch (which is lacking the modulation)

exidyboy

Hi,

Thanks for moving this discussion off Github https://github.com/shirriff/Arduino-IRremote/issues/56 onto the Arduino forum proper.

I will have a look at the Arduino-IRremote library over the next couple and see how Ken is generating the carrier frequency.
It might offer some clues. As I suggested on Github, as a test, you could also use a 2nd Arduino to just be a carrier frequency generator/oscillator and you would not necessarily need to grapple with PWM. You could just trigger the 2nd Arduino with the pulse distance modulation you want to send.

Stay tuned,

Mike

AnalysIR

I had a quick look at the IRremote library

Using timer1, which is the default, it looks like it should work for 455kHz, using the sendRAW feature as follows:

irsend.sendRaw(buffer, length,455);

...put the timings in buffer (uSecs), with a mark first.


As per my previous post, the frequency will be a little out, but should work.
If you use 455, you will actually get 470 kHz, and if you use 444 you will get 444 kHz.
If there are any issues try 455, 444 & 470


Go Up