IR Receiver Decode

I have a problem in that when the irrecv.decode function fails to decode something on a given loop it can stop the sketch from executing as intended.

General description. I have a system which involves an IR receiver, a bank of position-sensing reed switches working through a shift register, and four motors to operate a loft ladder and hatch. Some IR commands need to be press and release (automatic sequences) and others, manually controlling individual motors so as to enable corrections, need to only take place while the button is held.

Full code as attachment; extracts and pseudo-code here.

long currentOrders = 0;
long lastOrders = 0;
int countOrdersNotDecoded = 0;

#define noChange 0xFFFFFFFF
#define extendAutomatic 0x52A3D41F
#define extendMotor0 0xC101E57B
//And a whole load definitions more for different buttons, you get the picture

const int IR_RECV_PIN = 12;
IRrecv irrecv(IR_RECV_PIN);
decode_results results;
unsigned long key_value = 0;

void setup(){

void loop(){
  //Check for new orders. If the irrecv class can decode the results, store the value.
  if (irrecv.decode(&results)){
    countOrdersNotDecoded = 0;
    currentOrders = results.value;
    if(currentOrders == noChange) //i.e. 0xFFFFFFFF, this and elsewhere is why I've #defined text in place of hex
      currentOrders = lastOrders;
  //This bit, and the delay below currently commented out, were put in as candidates to bodge a fix to the problem that I'm presenting on
    countOrdersNotDecoded += 1;
    //We default to stop if a signal hasn't been registered for some cycles (unless we're in automatic modes)
    if ((currentOrders != extendFully) && (currentOrders != retractFully) && (countOrdersNotDecoded >= 10))
      currentOrders = stopOther;

  ladderPosition = pollShiftRegister(latchPin, clockPin, dataPin);

  //If nothing's changed, don't change what the motors are doing. Speeds code execution.
  if((ladderPosition == lastLadderPosition) && (currentOrders == lastOrders))


  //Remember what the new orders are so that they can be compared on the next loop
  lastOrders = currentOrders;
  lastLadderPosition = ladderPosition;

Symptoms Observed
As stated, for some outcomes I want to press and hold the button and as soon as I release the button the motor stops. So, I put in the decode failure case (the ‘else’ clause) to default to currentOrders = stopOther.
However every 2-3 loops (varies depending on the time taken to complete the loop) the code fails to decode an IR signal. This breaks the cycle, and the motor stops. When, on the next loop, it receives 0xFFFFFFFF it doesn’t know what to do with it.

Theory & Attempted Solutions
It appears to be dependent on the time taken to execute the loop. Delays in the loop appear to resolve the problem. Also, allowing for a certain number of failed decodes before stopping the motor also appears to help.

However, I want the code to be responsive. If I allow for ten failed decodes, that can be a noticeable delay between letting go of the button and the motor stopping. If I put in a delay, that’s even more of an issue as when in the automatic regime I want the system to change action as soon as possible after any of the reed switches connected to the shift register are activated. With both of these ‘solutions’ I’m trading reliability of execution for precision.

Is there another way? I had considered connecting both IR Receiver and shift register to interrupts but the problems are (1) my boards are set up to use different pins, (2) that’s 9 potential interrupt sources and only 2 hardware interrupt pins, and (3) I don’t even know if it would solve the problem.

I’m open to a complete re-factor of the code. I’d also love criticism of the code structure - I’m considering taking large chunks of definitions and functions out of the actual code and putting it in header files.

IRMotorControl.ino (11.6 KB)

I'd fix this before going further.


:smiley: I did say pseudo-code. Transcription error, doesn't feature in the original.

Perhaps on the next loop it receives 0xFFFFFFFF but now it doesn't know what to do with it.

Use Serial.print() to find out exactly what is happening, then guessing is not required.

Use Serial.print() to find out exactly what is happening, then guessing is not required.

Hi jremington, thanks for reading. Sorry for not being clear. That is what is happening in many cases. I've extensively debugged this with Serial.print() and know that to be the case.
'Perhaps' was being used in place of 'hypothetically' and the line could read 'When, on the next loop, it receives 0xFFFFFFFF it now doesn't know what to do with it'.

it now doesn't know what to do with it

My approach would be to modify the program to do something sensible with that value. Ignore it, for example.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.