IR Remote

Hello my friends!

I programmed an Arduino to respond to a remote control and control LEDs to be installed in a model car.

My program worked using delays and I produced the PCBs. While that was happening I thought about getting rid of the delays via adapting my program using millis() for a future version.

When I tested this new program measuring times and led states in a separate program it works like a charm. However, when I plug everything into my main program the Arduino starts acting weird. I mean, the program seems to be doing the same, but the blinking LEDs do not show the same behavior. Sometimes they just stay on until I press another button in the remote.

I have a bunch of Serial.prints along the way to track where the logic goes and it’s correct. However, I am starting to believe the IR Remote library messes up with the mills().

Any feedback would be appreciated. I’m at a loss here. Logic tells me it should work but it doesn’t…

This is my program (a part of it). I deleted the functions that don’t have anything to do with my questions to simplify it.

#include <IRremote.h>

//DEFINE PINS

#define testPin 13 // TEST MANUAL PWM
#define leftTurnLights A0
#define rightTurnLights A1

//DEFINE VARIABLES & CONSTANTS FOR REMOTE CONTROL
const uint16_t BUTTON_POWER = 0xD827; // i.e. 0x10EFD827
const uint16_t BUTTON_A = 0xF807;
const uint16_t BUTTON_B = 0x7887;
const uint16_t BUTTON_C = 0x58A7;
const uint16_t BUTTON_UP = 0xA05F;
const uint16_t BUTTON_DOWN = 0x00FF;
const uint16_t BUTTON_LEFT = 0x10EF;
const uint16_t BUTTON_RIGHT = 0x807F;
const uint16_t BUTTON_CIRCLE = 0x20DF;
const uint16_t CHECK_INTERIOR = 0xF1F1;

int delayTurnLights = 800; //DELAY FOR TURN SIGNALS


long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 200; // the debounce time; increase if the output flickers

//DEFINE VARIALBES FOR TRANSITION STATES
int frontLightsTransition=0;
int backLightsTransition=0;
int stopLightsTransition=0;

boolean leftTransition=false;
boolean rightTransition = false;
boolean hazardTransition=false;
boolean lightsOnTransition=false;
boolean backUpLightTransition=false;

//DEFINE VARIABLES FOR REMOTE CONTROL
IRrecv irrecv(RECV_PIN); // create instance of IRrecv
decode_results results;
uint16_t lastCode = 0; // This keeps track of the last code RX’d
uint16_t resultCode = 0; //initialize for IR Remote

//**********

class Flasher
{
// Class Member Variables
// These are initialized at startup
int ledPin;
long OnTime;

//These maintain the current state
int ledState; // ledState
unsigned long previousMillis; // will store last time led transitioned

// Constructor - creates a Flasher
// and initializes the member variables and state
public:
Flasher(int pin, long on)
{
ledPin = pin;
pinMode(ledPin, OUTPUT);

OnTime = on;

ledState = LOW;
previousMillis = 0;
}

void Update()
{
//check to see if it’s time to change the state of the led
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > OnTime) {
previousMillis = currentMillis;

if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

digitalWrite(ledPin, ledState);
}
}
};

Flasher turnToTheLeft(leftTurnLights, delayTurnLights);
Flasher turnToTheRight(rightTurnLights, delayTurnLights);
Flasher testFlasher(testPin, delayTurnLights);

//**********
// SETUP
void setup ()
{
pinMode(doorSensors, INPUT);
pinMode(interiorRoofAndDoors, OUTPUT);
pinMode(frontLights, OUTPUT);
pinMode(backLightsStop, OUTPUT);
pinMode(dashboardLight, OUTPUT);
pinMode(leftTurnLights, OUTPUT);
pinMode(rightTurnLights, OUTPUT);
pinMode(backLightsAndLicense, OUTPUT);
pinMode(quarterLights, OUTPUT);
pinMode(backUpLights, OUTPUT);
pinMode(testPin, OUTPUT);
Serial.begin(9600);
irrecv.enableIRIn(); // Start the IR receiver
}

//Function to perform actions if BUTTON B is pressed
void hazardLights() // BUTTON B
{
leftTransition=false;
rightTransition=false;
digitalWrite(leftTurnLights, LOW);
digitalWrite(rightTurnLights, LOW);
}

//Function to perform actions if BUTTON LEFT ARROW is pressed
void leftTurn() //BUTTON LEFT ARROW
{
rightTransition=false;
hazardTransition=false;
digitalWrite(leftTurnLights, LOW);
digitalWrite(rightTurnLights, LOW);
}

//Function to perform actions if BUTTON RIGHT ARROW is pressed
void rightTurn() //BUTTON RIGHT ARROW
{
leftTransition=false;
hazardTransition=false;
digitalWrite(leftTurnLights, LOW);
digitalWrite(rightTurnLights, LOW);
}

}
/*
//Manual PWM on LED 13 SUCCESS!!!
void testCircuit()
{
testFlasher.Update();
}
*/

// MAIN LOOP
void loop()
{
testFlasher.Update();
checkDoor(); // check if door is open or closed as it does not depend on IRremote

if(leftTransition){
turnToTheLeft.Update();
Serial.println(“Pass L”);
}
else{
digitalWrite(leftTurnLights, LOW);
}

if(rightTransition){
turnToTheRight.Update();
Serial.println(“Pass R”);
}
else {
digitalWrite(rightTurnLights, LOW);
}

if(hazardTransition){
turnToTheLeft.Update();
turnToTheRight.Update();
Serial.println(“Pass HL”);
} else {
digitalWrite(leftTurnLights, LOW);
digitalWrite(rightTurnLights, LOW);
}

//REMOTE CONTROL
if(irrecv.decode(&results))
{
resultCode = (results.value & 0xFFFF); // Read the RX’d into a 16-bit variable
lastDebounceTime = millis();

if (resultCode == 0xFFFF)
resultCode = lastCode;
else if ((millis() - lastDebounceTime) > debounceDelay) {
lastCode = resultCode;
}

switch (resultCode)
{
case BUTTON_POWER: // IMPLEMENTED
Serial.println(“Power”);
powerOff();
break;
case BUTTON_A: //IMPLEMENTED
Serial.println(“A”);
lightsOnTransition=!lightsOnTransition;
backLightsTransition++;
lightsOn();
break;
case BUTTON_B: // IMPLEMENTED
Serial.println(“B”);
hazardTransition=!hazardTransition;
hazardLights();
break;
case BUTTON_C: // IMPLEMENTED
Serial.println(“C”);
demo();
break;
case BUTTON_UP: // IMPLEMENTED
Serial.println(“Up”);
frontLightsTransition++;
nightLights();
break;
case BUTTON_DOWN: // IMPLEMENTED
Serial.println(“Down”);
backUpLightTransition=!backUpLightTransition;
backUpLighting();
break;
case BUTTON_LEFT: // IMPLEMENTED
Serial.println(“Left”);
leftTransition=!leftTransition;
Serial.println(leftTransition);
leftTurn();
break;
case BUTTON_RIGHT: // IMPLEMENTED
Serial.println(“Right”);
rightTransition=!rightTransition;
rightTurn();
break;
case BUTTON_CIRCLE: // IMPLEMENTED
Serial.println(“Circle”);
stopLightsTransition++;
Serial.print("stopLightsTransition is ");
Serial.println(stopLightsTransition);
stop();
break;
default:
Serial.print(“Unrecognized code received: 0x”);
Serial.println(results.value, HEX);
break;
} // switch statement
irrecv.resume(); // receive the next value
} // if irrecv.decode
} // void loop

Please modify your post and put your code in its own window as seen in other posts. This can be done by placing     [code] and [/code]  around the code. This makes it easier for others to read.

Weedpharma

Yes, please put the code in 'code tags', to make it easier to read. You will likely get more & better assistance.

I deleted the functions that don't have anything to do with my questions to simplify it.

You can only be sure of that if you know where the problem is. Even more difficult to follow, with parts of the code missing! In my opinion you complicated it by deleting part of the code.

Hello!

I created a second, simplified program based on the first one, from scratch. Started with the Class Flasher, then added the IR, then other functions. Stopped when the same problem presented again. The leftTurn() and rightTurn() functions work well. What doesn’t work well are the hazardLights().

Well, they do work, but sometimes the LEDs do not blink in sync. If the left or right clicker were on, the hazard lights do not blink in sync. If the left or right clicker are turned off using its buttons, then the hazard lights do blink in sync.

Here it is the complete simplified program.

#include <IRremote.h>

#define RECV_PIN 2 // input from remote control *******used to be 4
#define leftTurnLights A0 
#define rightTurnLights A1 
#define testPin 13

//DEFINE VARIABLES & CONSTANTS FOR REMOTE CONTROL
const uint16_t BUTTON_POWER = 0xD827; // i.e. 0x10EFD827
const uint16_t BUTTON_A = 0xF807;
const uint16_t BUTTON_B = 0x7887;
const uint16_t BUTTON_C = 0x58A7;
const uint16_t BUTTON_UP = 0xA05F;
const uint16_t BUTTON_DOWN = 0x00FF;
const uint16_t BUTTON_LEFT = 0x10EF;
const uint16_t BUTTON_RIGHT = 0x807F;
const uint16_t BUTTON_CIRCLE = 0x20DF;
const uint16_t CHECK_INTERIOR = 0xF1F1;

int delayTurnLights = 300; //DELAY FOR TURN SIGNALS
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 200;    // the debounce time; increase if the output flickers
//int delayTurnLightsLeft

boolean leftTransition=false;
boolean rightTransition = false;
boolean hazardTransition=false;


//DEFINE VARIABLES FOR REMOTE CONTROL
IRrecv irrecv(RECV_PIN); // create instance of IRrecv
decode_results results;
uint16_t lastCode = 0; // This keeps track of the last code RX'd
uint16_t resultCode = 0; //initialize for IR Remote


class Flasher
{
  // Class Member Variables
  // These are initialized at startup
  int ledPin;
  long OnTime;
  long OffTime;
  
  //These maintain the current state
  int ledState; // ledState
  unsigned long previousMillis; // will store last time led transitioned
 
  // Constructor - creates a Flasher
  // and initializes the member variables and state
  public:
  Flasher(int pin, long on, long off)
  {
    ledPin = pin;
    pinMode(ledPin, OUTPUT);
    
    OnTime = on;
    OffTime = off;
    
    ledState = LOW;
    previousMillis = 0;
  }  

  void Update()
    {
      //check to see if it's time to change the state of the led
      unsigned long currentMillis = millis();
 
      if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) {
        ledState = LOW; //turn it off
        previousMillis = currentMillis; // Remember the time
        digitalWrite(ledPin, ledState);
      }
      else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
      {
        ledState = HIGH;
        previousMillis = currentMillis;
        digitalWrite(ledPin, ledState);
      }
    }
};

Flasher turnToTheLeft(leftTurnLights, delayTurnLights, delayTurnLights);
Flasher turnToTheRight(rightTurnLights, delayTurnLights, delayTurnLights);
Flasher testFlasher(testPin, 3, 800);

void setup()
{
  pinMode(leftTurnLights, OUTPUT); //NOT NEEDED
  pinMode(rightTurnLights, OUTPUT); //NOT NEEDED
  pinMode(testPin, OUTPUT); //NOT NEEDED
  Serial.begin(9600);
  irrecv.enableIRIn();  // Start the IR receiver
}

//Function to perform actions if BUTTON B is pressed
void hazardLights() // BUTTON B
{ 
  digitalWrite(leftTurnLights, LOW);
  digitalWrite(rightTurnLights, LOW);
  leftTransition=false;
  rightTransition=false;
}

//Function to perform actions if BUTTON LEFT ARROW is pressed
void leftTurn() //BUTTON LEFT ARROW
{
  digitalWrite(leftTurnLights, LOW);
  digitalWrite(rightTurnLights, LOW); 
  rightTransition=false;
  hazardTransition=false;
}

void rightTurn() //BUTTON RIGHT ARROW
{
  digitalWrite(leftTurnLights, LOW);
  digitalWrite(rightTurnLights, LOW);  
  leftTransition=false;
  hazardTransition=false;

}

void loop()
{
  testFlasher.Update();
  
  if(leftTransition){
    turnToTheLeft.Update();
  }
  
  if(rightTransition){
    turnToTheRight.Update();
  }
  
 if(hazardTransition){
    turnToTheLeft.Update();
    turnToTheRight.Update();
  }
  
  if(irrecv.decode(&results))
  {
    resultCode = (results.value & 0xFFFF); // Read the RX'd into a 16-bit variable
    lastDebounceTime = millis();
    
    if (resultCode == 0xFFFF)
      resultCode = lastCode;
    else if ((millis() - lastDebounceTime) > debounceDelay) {
      lastCode = resultCode;
    }
    
     switch (resultCode)
      {
        case BUTTON_POWER: //  IMPLEMENTED
          Serial.println("Power"); 
          break;
        case BUTTON_A: //IMPLEMENTED
          Serial.println("A");
          break;
        case BUTTON_B: // IMPLEMENTED
          Serial.println("B");
          hazardTransition=!hazardTransition;
          Serial.println(hazardTransition);
          hazardLights();
          break;
        case BUTTON_C: //  IMPLEMENTED
          Serial.println("C");
          break;
        case BUTTON_UP: //  IMPLEMENTED
          Serial.println("Up");
          break;
        case BUTTON_DOWN:  // IMPLEMENTED
          Serial.println("Down");
          break;
        case BUTTON_LEFT: // IMPLEMENTED
          Serial.println("Left");
          leftTransition=!leftTransition;
          Serial.println(leftTransition);
          leftTurn();
          break;
        case BUTTON_RIGHT: // IMPLEMENTED
          Serial.println("Right"); 
          rightTransition=!rightTransition;
          Serial.println(rightTransition);
          rightTurn();
          break;
        case BUTTON_CIRCLE: //  IMPLEMENTED
          Serial.println("Circle");
          break;  
        default:
          Serial.print("Unrecognized code received: 0x");
          Serial.println(results.value, HEX);
          break; 
    } // switch statement
    irrecv.resume();  // receive the next value
  } // if irrecv.decode
  
}

Please edit your first post to put it in a code window.

Weedpharma

Well, they do work, but sometimes the LEDs do not blink in sync. If the left or right clicker were on, the hazard lights do not blink in sync. If the left or right clicker are turned off using its buttons, then the hazard lights do blink in sync.

Sounds like you just need to set you left & right signals to the same state just before you call your 'hazard stuff.

Otherwise, just add in some serial prints, to make sure your variables are in the correct state, before you call the hazard stuff.

PS: Surely it cant be that hard to add in the code tags in your first post as requested???