Can't get an IR receiver and remote to work properly using the IRremote library

I have a 3-pin IR receiver module that I’m trying to use with a generic remote control (taken from a random set of string lights) to turn on an LED through a Mega 2560 and the IRremote.h library. I‘m using an older version of the library (2.6.0) because I was having compatibility issues with the newest version. I was able to use some example code I found online to display the hex code of each button when pressed in the Serial Monitor without issue, so I know all the hardware is working as it should. When I try to run my own code however, it runs through perfectly the first time, but then subsequent times it won’t pick up the button press. Here’s my code:

In setup():

irrecv.enableIRIn();

In loop():

void readIR(void) {

decode_results results;  

int ret = 0;

  while (ret == 0) {

    irrecv.decode(&results);

    if (results.value == 0xFFB04F) {

      ret = 1;

    }

  }

  irrecv.resume();

}

This function is followed by another function in the main loop, which turns on an LED. So the first time I hit the button on the remote, the LED comes on, but then nothing happens after. Through use of some Serial Monitor debug statements, I checked the values of results.value and irrecv.decode(&results). On the first run they are both at 0, I press the button and irrecv.decode(&results) goes to 1 and results.value changes to 0xFFB04F (which is the hex code for the button I’m pressing). The light comes on and it cycles back into the readIR function. This time though, irrecv.decode(&results) is still at 1, and there is a random hex value for results.value. When I press the remote button again however, nothing happens. In checking the same values for the example script I successfully used, irrecv.decode(&results) returns to 0 after each trigger, while mine does not for some reason. I thought it was something to do with irrecv.resume(), but that seems to be in order. Has anybody ever messed around with this library? Thanks.

Provide a complete sketch that can be compiled that demonstrates the problem, please. Snippets are a waste of time.

Apologies. Here’s the full script (including debug statements):

#include <Servo.h>

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <IRremote.h>




#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 32

#define OLED_RESET -1

#define SCREEN_ADDRESS 0x3C




Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Servo gateServo;

int SERVO = 48, BUZZER = 52, R1 = 40, R2 = 42, R3 = 44, G = 46, SENSOR = A13, SCLPIN = 21, SDAPIN = 20, IR = 53;

unsigned long STARTBUTTON = 50;

float startTime, endTime;

IRrecv irrecv(IR);


void setup() {

  Serial.begin(9600);

  gateServo.attach(SERVO);

  pinMode(STARTBUTTON, INPUT);

  pinMode(IR, INPUT);

  pinMode(BUZZER, OUTPUT);

  pinMode(R1, OUTPUT);

  pinMode(R2, OUTPUT);

  pinMode(R3, OUTPUT);

  pinMode(G, OUTPUT);

  pinMode(SENSOR, INPUT);

  pinMode(SCLPIN, OUTPUT);

  pinMode(SDAPIN, OUTPUT);

  irrecv.enableIRIn();

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

    Serial.println(F("SSD1306 allocation failed"));

    for (;;)

      ;

  }

  raiseGate();

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(SSD1306_WHITE);

}




void loop() {

  raiseGate();

  delay(100);

  introBanner();

  //detectButton();

  readIR();

  startLights();

  runRace();

}




void dropGate(void) {

  gateServo.write(90);

}




void raiseGate(void) {

  gateServo.write(0);

}




void startLights(void) {

  digitalWrite(R1, HIGH);

  beep(200);

  delay(750);

  digitalWrite(R1, LOW);

  digitalWrite(R2, HIGH);

  beep(200);

  delay(750);

  digitalWrite(R2, LOW);

  digitalWrite(R3, HIGH);

  beep(200);

  delay(750);

  digitalWrite(R3, LOW);

  digitalWrite(G, HIGH);

  dropGate();

  startTime = millis();

  digitalWrite(BUZZER, HIGH);

  flashText("GO!!!!", 500, 3);

  digitalWrite(BUZZER, LOW);

  digitalWrite(G, LOW);

}




void beep(int duration) {

  digitalWrite(BUZZER, HIGH);

  delay(duration);

  digitalWrite(BUZZER, LOW);

}




void detectButton(void) {

  while (digitalRead(STARTBUTTON) == LOW)

    ;

}




void runRace(void) {

  int sensorVal = 0;

  while (sensorVal < 10) {

    sensorVal = analogRead(SENSOR);

  }

  endTime = millis();

  displayTime();

}




void displayTime(void) {

  float time = (endTime - startTime) / 1000;

  display.setTextSize(2);

  display.setCursor(22, 13);

  display.print(time);

  display.print(" sec");

  display.display();

  strobe();

  //detectButton();

  readIR();

}




void displayText(char* content) {

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(SSD1306_WHITE);

  display.setCursor(26, 13);

  display.println(content);

  display.display();

}




void scrollText(char* content) {

  display.clearDisplay();

  display.setTextSize(1, 2);

  display.setCursor(10, 13);

  display.println(content);

  display.display();

  display.startscrollleft(0x00, 0x0F);

}




void introBanner(void) {

  display.clearDisplay();

  display.setCursor(31, 13);

  display.println("START");

  display.display();

  delay(1000);

  display.clearDisplay();

  display.setCursor(35, 13);

  display.println("YOUR");

  display.display();

  delay(1000);

  display.clearDisplay();

  display.setCursor(23, 13);

  display.println("ENGINES");

  display.display();

  delay(1000);

  scrollText("GET READY TO RACE");

}




void flashText(char* content, int interval, int iterations) {

  display.stopscroll();

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(SSD1306_WHITE);

  for (int i = 0; i < iterations; i++) {

    display.setCursor(33, 13);

    display.println(content);

    display.display();

    delay(interval);

    display.clearDisplay();

    display.display();

    delay(interval);

  }

}




void strobe(void) {

  for (int i = 0; i < 3; i++) {

    digitalWrite(R1, HIGH);

    delay(50);

    digitalWrite(R1, LOW);

    delay(50);

    digitalWrite(R2, HIGH);

    delay(50);

    digitalWrite(R2, LOW);

    delay(50);

    digitalWrite(R3, HIGH);

    delay(50);

    digitalWrite(R3, LOW);

    delay(50);

    digitalWrite(G, HIGH);

    delay(50);

    digitalWrite(G, LOW);

    delay(50);

  }

}




void readIR(void) {

  decode_results results;

  int ret = 0;

  Serial.println("1");

  Serial.println(irrecv.decode(&results));

  Serial.println(results.value, HEX);

  delay(1000);

  while (ret == 0) {

    irrecv.decode(&results);

    Serial.println("2");

    Serial.println(irrecv.decode(&results));

    Serial.println(results.value, HEX);

    delay(1000);

    if (results.value == 0xFFB04F) {

      ret = 1;

      Serial.println("3");

      Serial.println(irrecv.decode(&results));

      Serial.println(results.value, HEX);

      delay(1000);

    }

  }

  irrecv.resume();

}

I would be asking myself if the delay(1000); call before irrecv.resume(); is a good idea.

But I would also be asking myself what happens when irrecv.decode(...) is called multiple times without irrecv.resume(); being called in your loop if neither of the if statements is executed because you aren't checked the return result of irrecv.decode(...) first to see if it's non-zero.

Those delays are just so that I can see the Serial Monitor statements before they cycle through. It behaves the exact same way without the degub blocks though. i.e. if it looked like this it would behave the same:

while (ret == 0) {
irrecv.decode(&results);
if (results.value == 0xFFB04F) {
ret = 1;
}
}
irrecv.resume();

}

I begin to see @LarryD's point about not putting two things in the same reply. People seem to stop reading after the first thing.

Good luck with your project.

Sorry, who is LarryD?

Show this code. Start with something that works.

Because... void readIR(void) seems to get stuck in a 3 seconds, endless loop.

Post the pictures/model/type of your IR Receiver and the Remote Control. Also, attach the zip file of IR Library you are using.

You call irrecv.decode(&results) multiple times without checking its return value properly.

You print results.value even when decode() returned false, so the value is undefined.

Inside the while loop you never call irrecv.resume(), so after one successful decode the receiver stops and the loop blocks forever.

The correct logic is to call decode() once, test its boolean return, use results.value only if it is true, then call irrecv.resume() immediately.

Also, I2C pins must not be configured as outputs when using Wire, just let Wire handle that.

Here’s the example scanner code I found online:

#include <IRremote.h>

int RECV_PIN = 53;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup() {

  Serial.begin(9600);

  irrecv.enableIRIn();  // Start the receiver

}

void loop() {

  if (irrecv.decode(&results)) {

    if (results.value != 0xFFFFFFFF) {
      Serial.println(results.value, HEX);
    }

    irrecv.resume();  // Receive the next value

  }

  delay(100);

}

Also, here is the sensor module:

And here is the library:

IRremote.zip (130.0 KB)

What are your results of this sketch?

Thanks for all the input guys. J-M-L here’s the code with your instructions implemented. Still the same behaviour unfortunately though:

#include <Servo.h>

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <IRremote.h>




#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 32

#define OLED_RESET -1

#define SCREEN_ADDRESS 0x3C




Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Servo gateServo;

int SERVO = 48, BUZZER = 52, R1 = 40, R2 = 42, R3 = 44, G = 46, SENSOR = A13, IR = 53;

unsigned long STARTBUTTON = 50;

float startTime, endTime;

IRrecv irrecv(IR);




void setup() {

  Serial.begin(9600);

  gateServo.attach(SERVO);

  pinMode(STARTBUTTON, INPUT);

  pinMode(IR, INPUT);

  pinMode(BUZZER, OUTPUT);

  pinMode(R1, OUTPUT);

  pinMode(R2, OUTPUT);

  pinMode(R3, OUTPUT);

  pinMode(G, OUTPUT);

  pinMode(SENSOR, INPUT);


  irrecv.enableIRIn();

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

    Serial.println(F("SSD1306 allocation failed"));

    for (;;)

      ;

  }

  raiseGate();

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(SSD1306_WHITE);

}




void loop() {

  raiseGate();

  delay(100);

  introBanner();

  //detectButton();

  readIR();

  startLights();

  runRace();

}




void dropGate(void) {

  gateServo.write(90);

}




void raiseGate(void) {

  gateServo.write(0);

}




void startLights(void) {

  digitalWrite(R1, HIGH);

  beep(200);

  delay(750);

  digitalWrite(R1, LOW);

  digitalWrite(R2, HIGH);

  beep(200);

  delay(750);

  digitalWrite(R2, LOW);

  digitalWrite(R3, HIGH);

  beep(200);

  delay(750);

  digitalWrite(R3, LOW);

  digitalWrite(G, HIGH);

  dropGate();

  startTime = millis();

  digitalWrite(BUZZER, HIGH);

  flashText("GO!!!!", 500, 3);

  digitalWrite(BUZZER, LOW);

  digitalWrite(G, LOW);

}




void beep(int duration) {

  digitalWrite(BUZZER, HIGH);

  delay(duration);

  digitalWrite(BUZZER, LOW);

}




void detectButton(void) {

  while (digitalRead(STARTBUTTON) == LOW)

    ;

}




void runRace(void) {

  int sensorVal = 0;

  while (sensorVal < 10) {

    sensorVal = analogRead(SENSOR);

  }

  endTime = millis();

  displayTime();

}




void displayTime(void) {

  float time = (endTime - startTime) / 1000;

  display.setTextSize(2);

  display.setCursor(22, 13);

  display.print(time);

  display.print(" sec");

  display.display();

  strobe();

  //detectButton();

  readIR();

}




void displayText(char* content) {

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(SSD1306_WHITE);

  display.setCursor(26, 13);

  display.println(content);

  display.display();

}




void scrollText(char* content) {

  display.clearDisplay();

  display.setTextSize(1, 2);

  display.setCursor(10, 13);

  display.println(content);

  display.display();

  display.startscrollleft(0x00, 0x0F);

}




void introBanner(void) {

  display.clearDisplay();

  display.setCursor(31, 13);

  display.println("START");

  display.display();

  delay(1000);

  display.clearDisplay();

  display.setCursor(35, 13);

  display.println("YOUR");

  display.display();

  delay(1000);

  display.clearDisplay();

  display.setCursor(23, 13);

  display.println("ENGINES");

  display.display();

  delay(1000);

  scrollText("GET READY TO RACE");

}




void flashText(char* content, int interval, int iterations) {

  display.stopscroll();

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(SSD1306_WHITE);

  for (int i = 0; i < iterations; i++) {

    display.setCursor(33, 13);

    display.println(content);

    display.display();

    delay(interval);

    display.clearDisplay();

    display.display();

    delay(interval);

  }

}




void strobe(void) {

  for (int i = 0; i < 3; i++) {

    digitalWrite(R1, HIGH);

    delay(50);

    digitalWrite(R1, LOW);

    delay(50);

    digitalWrite(R2, HIGH);

    delay(50);

    digitalWrite(R2, LOW);

    delay(50);

    digitalWrite(R3, HIGH);

    delay(50);

    digitalWrite(R3, LOW);

    delay(50);

    digitalWrite(G, HIGH);

    delay(50);

    digitalWrite(G, LOW);

    delay(50);

  }

}




void readIR(void) {

  decode_results results;

  int ret = 0;

  while (ret == 0) {

    irrecv.decode(&results);

    if (results.value == 0xFFB04F) {

      irrecv.resume();

      ret = 1;

    }

  }

}

The example code prints the hex code for any given button to the serial monitor.

Add to this IR code, the OLED code (configuration, setup, function). Describe the results.

Sorry I don’t follow. You want me to add one of my functions to the example code?

The issue starts with "can't get IR receiver to work"....
Step 1. Get a working IR sketch... which you have done.
Step 2. add a device to the working sketch... OLED... get that working with the IR code.
Step 3. add a device... Servo.

It's still bad.

void readIR(void) {
  decode_results results;
  int ret = 0;
  while (ret == 0) {
    irrecv.decode(&results);
    if (results.value == 0xFFB04F) {
      irrecv.resume();  //  ****
      ret = 1;
    }
  }
}

It only decodes again if the received code is 0xFFB04F.

That’s a good point. Changed it to this:

void readIR(void) {

  decode_results results;

  int ret = 0;

  while (ret == 0) {

    irrecv.decode(&results);

    if (results.value == 0xFFB04F) {

      ret = 1;

    }

  }

  irrecv.resume();

  delay(100);

}

Unfortunately it didn't fix it though. Exact same behaviour.

Yes the thing is though, the example sketch as written scans for any button at all. I want to use only a specific button (0xFFB04F), so I have to change it in order to accomplish that. Secondly, the example is designed to be constantly looping in the main loop, which I had to again change to accommodate integration into my complete sketch (by using the ret flag). So adding my code into the working example won’t really solve my problem, as the example doesn’t exactly do what I need it to do. But my readIR function is the example exactly, with those two changes implemented.