As I was not sure if I can port existing IR control libs to 3pi I try my own.
I use as receiver tsop4138 …works well with my sony IR remote control.
I did the first tests with the pololu programmer oszi and ended up in this
The decoding of the sony protocol is not that difficult. I found a good explanation here:
http://avrprogrammers.com/proj_sirc_1.php
To make it easy … the information is finaly in the low pulse length.
if it is short it is a 0;
if it is longer it is 1;
if it is extra long it is the start token.
if you have 12 bits (and use a 12 bit IR control) you have the IRcode which is devided in addr and cmd.
I used the inpulse lib which makes it quiet easy to react on the falling edge of the IR sensor.
The example decoder looks like this one
while (1) {
get_pulse_info(0, &pulse_info); // get pulse info 0=1st channel of the pulseInPins[]
// we wait for the first falling edge ..could not get triggered that by the function?
if (pulse_info.newPulse == LOW_PULSE) {
// we only care for the low pulse as here is the info
//we are high and can check the last low pulse length
//ToDo ..make it portable to different CPU clocks
if ((pulse_info.lastLowPulse > 1000) && (pulse_info.lastLowPulse < 2000)) {
bits++; //we have a zero bit ..nothing to do with IRcode as 0 is default set
}
else if (pulse_info.lastLowPulse < 3500) {
// we have a 1 and need to set the bit in IRcode
IRcode|= (uint16_t)(1<< bits); bits++;
}
else if (pulse_info.lastLowPulse < 7000) {
IRtoken++; // we have a start token
};
//everything else is a problem we might add error counter and handling
if ((IRtoken > 1) || //we should not see more than 1 token
((bits > 0) && (IRtoken != 1)) || // we have bits before token
(bits > 12) // we have too many bits
) // we should also care for the high pulse errors ..but works
{ // reset everything; some debug output would be nice
IRtoken = 0; bits=0; IRcode=0;
}
else if (bits == 12) { // we have the code
IRcmd = IRcode & (int) 0b1111111; // lowest 7 bit are the cmd
IRaddr = IRcode >> 7; //upper 5 (of 12) bits are the address
//ToDo ..what we are doing with the IRcmd
//we might have a nice callback function
//should we care about the 3x replications typical for sony?
// we could determine the distance between the IRtokens ..
// now we can reset everything
IRtoken = 0; bits=0; IRcode=0;
}
}
}
Where is room for improvement …handling the error noise … high pulse length are simply ignored.
But so far it works fine …its more the button of the 15 years old IR control which make some problems.
So far not bad …but now comes the problem with the 3pi. The shortest low pulse wide is about 500us.
As the inpulse lib makes you polling and the IRsensor for the line follower is blocking upto 2 ms …
you could not use both.
Current approach to get around it: shift the bit decoding into the ISR of the Pin Change Interrupt and provide
the decoded cmd. That should not happen faster than every 45 ms.
(which makes also clear …why IR controls are not the best way for movement control of a robot, delay and
number of cmd per second is not good)
The downside of the own ISR …first it takes longer …second it will mostlikely conflict with the inpulse lib.
May be I find a way to extend the InPulse lib in a compatible way …
Or I focus on that IRSensor lib …