Fixing switch case statement for decoded IR Receiver buttons + LCD Keypad Shield

Hello All,

I’ve been making good progress on my project which expanded the Spotify Remote from Hackshed. Here’s the link

http://www.hackshed.co.uk/creating-a-spotify-remote-with-an-arduino-and-lcd-shield/

I attempted to replace the button functions for the LCD Keypad shield with the IR receiver and have it come from the decoded Hex values of each button on the remote.

Here is my code:

//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
#include <IRremote.h>  // use the library

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
String inData;
String currentSong;
String lastSong;

int receiver = A5; // pin 1 of IR receiver to Arduino digital pin A5
// define some values used by the panel and buttons (variables)
int lcd_key     = 0;
//int btn_val    = 0;

//define constants
const int BACK_LIGHT = 13; //Pin 13 will control the backlight
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define 0xFF22DD PLAY/PAUSE
#define 0xFF02FD PREV
#define 0xFFC23D NEXT

IRrecv irrecv(receiver); // create instance of 'irrecv'

decode_results results;

// read the buttons
int read_LCD_buttons()
{
 //btn_val = analogRead(0);      // read the value from the sensor 
 // my buttons when read are centered at these values: 0, 144, 329, 504, 741
 // we add approx 50 to those values and check to see if we are close
// if (btn_val > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result

 // For V1.1 us this threshold
 //if (btn_val < 100)   return btnRIGHT;  
 //if (btn_val < 200)  return btnUP; 
 //if (btn_val < 400)  return btnDOWN; 
 //if (btn_val < 600)  return btnLEFT; 
 //if (btn_val < 800)  return btnSELECT;  

 // For V1.0 comment the other threshold and use the one below:
/*
 if (adc_key_in < 50)   return btnRIGHT;  50
 if (adc_key_in < 195)  return btnUP;     250
 if (adc_key_in < 380)  return btnDOWN;   450
 if (adc_key_in < 555)  return btnLEFT;   650
 if (adc_key_in < 790)  return btnSELECT; 850  
*/


 return btnNONE;  // when all others fail, return this...
}

typedef struct Timer  {
    unsigned long tStart;
    unsigned long tTimeout;
};

bool tCheck (struct Timer *timer ) {
    if (millis() > timer->tStart + timer->tTimeout) 
        return true;

    return false;    
}

void tRun (struct Timer *timer) {
    timer->tStart = millis();
}

//Tasks and their Schedules.
Timer t_updateLCD = {0, 3500}; //Run every 2 seconds.

void setup()
{
  irrecv.enableIRIn(); // Start the receiver
  
  pinMode(BACK_LIGHT, OUTPUT);
  digitalWrite(BACK_LIGHT, HIGH);
  
 Serial.begin(9600); 
 lcd.clear(); 
 lcd.begin(16, 2);              // start the library

 
}
 
void translateIR() //takes action based on IR code received
// describing MP3 remote control IR codes on LCD.
{
  switch(results.value)
  {
 
    case 0xFFA25D:  lcd.println("POWER           "); break;
 
    case 0xFF629D:  lcd.println("MODE             "); break;
 
    case 0xFFE21D:  lcd.println("MUTE            "); break;
 
    case 0xFF22DD:  lcd.println("PLAY/PAUSE       "); break;
 
    case 0xFF02FD:  lcd.println("PREV             "); break;
 
    case 0xFFC23D:  lcd.println("NEXT             "); break;
 
    case 0xFFE01F:  lcd.println(" EQ              "); break;
 
    case 0xFFA857:  lcd.println(" -               "); break;
 
    case 0xFF906F:  lcd.println(" +                "); break;
 
    case 0xFF6897:  lcd.println(" 0                "); break;
 
    case 0xFF9867:  lcd.println(" SHUFFLE           "); break;
 
    case 0xFFB04F:  lcd.println(" U/SD           "); break;
 
    case 0xFF30CF:  lcd.println(" 1              "); break;
 
    case 0xFF18E7:  lcd.println(" 2              "); break;
 
    case 0xFF7A85:  lcd.println(" 3              "); break;
 
    case 0xFF10EF:  lcd.println(" 4              "); break;
 
    case 0xFF38C7:  lcd.println(" 5              "); break;
 
    case 0xFF5AA5:  lcd.println(" 6              "); break;
 
    case 0xFF42BD:  lcd.println(" 7              "); break;
 
    case 0xFF4AB5:  lcd.println(" 8              "); break;
 
    case 0xFF52AD:  lcd.println(" 9              "); break;
 
    default: lcd.println(" other button   ");
 
  }
  
  delay(500);
  lcd.clear();
  }
  
void loop()
{
//Call the main menu.
  mainMenu();

 while (Serial.available() > 0) {
        char recieved = Serial.read();
        inData += recieved; 

        // Process message when new line character is recieved
        if (recieved == '\n') {
            Serial.print("Arduino Received: ");
            Serial.print(inData);
            currentSong = inData;
            inData = ""; // Clear recieved buffer
        }
    }

    //Update LCD.
    if (tCheck(&t_updateLCD)) {
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Now Playing:");
          lcd.setCursor(0,1);
          int index = 0;
          int len = (currentSong.length() - 2);
          for (int i=0; i<len;i++) {
            if (index == 16) {
              lcd.setCursor(0,1);
              lcd.print("                "); //Clear line
              index = 0; 
              delay(200);
            }
            lcd.setCursor(index,1); 
            lcd.print(currentSong[i]);
            delay(150);
            index++;
          }
          lastSong = currentSong;

      tRun(&t_updateLCD);
    }
}
 //lcd.setCursor(0,1);            // move to the begining of the second line

void mainMenu(){
  {
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
 
    Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
    //lcd.print(results.value, HEX); // display it on serial monitor in hexadecimal
    translateIR();
 
    irrecv.resume(); // receive the next value
 
  }  // Your loop can do other things while waiting for an IR command
}
 //lcd_key = read_LCD_buttons();  // read the buttons
 lcd.setCursor(0,0);
 switch (results.value)               // depending on which button was pushed, we perform an action
 {
   case 0xFFC23D:
     {
     Serial.println("next|");
     break;
     delay(500);
     }
   case 0xFF02FD:
     {
     Serial.println("prev|");
     break;
     delay(500);
     }
   case 0xFF629D: //Nothing yet.
     {
     lcd.print("UP    ");
     break;
     delay(500);
     }
   case 0xFFE21D: //Nothing Yet. 
     {
     lcd.print("DOWN  ");
     break;
     delay(500);
     }
   case 0xFF22DD:
     {
     Serial.println("pause|");
     break;
     delay(500);
     }
     //case btnNONE:
     //{
     //lcd.print("NONE  ");
     //break;
     //}
     delay(50);
 }
}

The original code and .Net application can be accessed on the link.

I placed delays in the switch case statements because when I accessed the serial monitor and pressed the button, I saw that once it was pressed, the serial data would continuously loop until I pressed another button that hasn’t been assigned yet.

I’m an amateur programmer so any way to fix this problem is much appreciated. Thanks!

create a global boolean called printed and try putting ‘printed’ flag in your code and modifying the Serial.print()s like this:

lcd.setCursor(0,0);
  if ((results.value) != lastValue)
  {
    printed = false;
  }
  switch (results.value)               // depending on which button was pushed, we perform an action
  {
  case 0xFFC23D:
    {
    if (!printed)
    {
      Serial.println("next|");
      printed = true;
    }
    break;
    //delay(500);
    }

then set lastValue (declare as a global variable, FYI) like this after the switch/case:

  case 0xFF22DD:
    {
      if (!printed)
      {
        Serial.println("pause|");
        printed = true;
      }
      break;
      //delay(500);
    }
    //case btnNONE:
    //{
    //lcd.print("NONE  ");
    //break;
    //}
    //delay(50);
  }
  lastValue = (results.value);
}

add the print flag for each case

OK thanks I will try it!

What is the difference between : (printed = true) and printed = true; ?

it is kind of technical...

(printed = true)

is called a "stupid mistake"

printed = true;

is a proper assignment

:blush:

i fixed the example...

Oh ok, thanks!

Is it safe to declare the global variables as such?

bool printed = false; //For the remote buttons and application interaction
bool lastValue = false;

chaanceg123: Oh ok, thanks!

Is it safe to declare the global variables as such?

bool printed = false; //For the remote buttons and application interaction
bool lastValue = false;

lastValue has to be the same data type as what you have returning here:

results.value

OK. So I made the changes and still the serial would print continously, so I decided to take the switch case statement and make it it's own standalone void function

void recieveIR() //Interacts with buttons on the remote control, 
  {
    //lcd_key = read_LCD_buttons();  // read the buttons
 lcd.setCursor(0,0);

  if ((results.value) != lastValue)
  {
    printed = false;
  }
  
 switch (results.value)               // depending on which button was pushed, we perform an action
 {
   case 0xFFC23D:
     {
     if (!printed)
     {
     Serial.println("next|");
     printed = true;
     }
     break;
     //delay(500);
     }
     
   case 0xFF02FD:
     {
       if (!printed)
       {
     Serial.println("prev|");
     printed = true;
       }
     break;
     //delay(500);
     }
     
   case 0xFF629D: //Nothing yet.
     {
     lcd.print("UP    ");
     break;
     delay(500);
     }
     
   case 0xFFE21D: //Nothing Yet. 
     {
     lcd.print("DOWN  ");
     break;
     delay(500);
     }
     
   case 0xFF22DD:
     {
       if (!printed)
      {
     Serial.println("pause|");
     printed = true;
      }
     break;
    // delay(500);
     }
     //case btnNONE:
     //{
     //lcd.print("NONE  ");
     //break;
     //}
     //delay(50);
 }
 lastValue = (results.value);
}

now I put this in Main menu

void mainMenu(){
  {
  if (irrecv.decode(&results)) // have we received an IR signal?
  {

    Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
    //lcd.print(results.value, HEX); // display it on serial monitor in hexadecimal
    translateIR();
    
    irrecv.resume(); // receive the next value
    
    recieveIR();

  }  // Your loop can do other things while waiting for an IR command
}
}

When I open up the serial monitor, it successfully prints "|prev" or "|next", etc. when I press the button, but now when I run the Application it can't seem to find it?

Is this a serial communication problem? I am trying to have it read "|prev", "|next", and "|pause" only once.