Need help loop in switch case

I am currently trying to get multiple pages to work by using case, i dont know if this is the best option, cause it only reads the data once and dosent loop, but i am very new to Arduino and the methods seemed simple.
Does anyone know if its possible to get i to loop in a case?

Plz let me know if you need any further information or code!

OBD_3_0_NoLive.ino (5.63 KB)

Plz let me know if you need any further information or code!

Posting the code here would be a help.

Loop in a case? Unless it's a quick loop for example to set multiple pins or something it should not loop. The loop is there to loop. Let the loop do it's looping and just do whatever you want to loop in the loop :slight_smile:

And a small fix:

Need Would like help with loop in switch case

And some tips:

  • Read the how to use the forum :wink: You clearly didn't.
  • Press Ctrl+T in the IDE. The code layout is a mess.
  • use the same style for variable names. aka, they should all start with a lowercase.
  • Use better variable names. "Yellow" is not. "yellowLedPin" is :wink:
  • Instead of a long delay, use a proper debounce. And if you don't want to write it, grab a library like Bounce2.
  • Try to break the code down in smaller (reuseable) pieces. Now it's just one big block.
  • You only need to begin() the lcd once :wink:
  • Do you have an external resistor on the switchPin?
  • A simplification:
digitalWrite(Green, rpm > 2500 ? HIGH : LOW);
//simpler to just write
digitalWrite(Green, rpm > 2500);
  • Do you really only want to set the cursor back when you have a reading? Or do you only want to print all the stuff if you have a reading?
if (obd.readPID(PID_ENGINE_OIL_TEMP, Oil))
            lcd.setCursor(0, 0);

Sorry septillion, yes i didn't read the "how to forum" but i have now, so in the future i will do better :slight_smile:
English is not my first language so sorry for any spelling errors, i hope i can keep them minor. Thank you for the tips, i am just starting out so it is really helpful, greatly appreciated. i know the code isn't pretty, it is a mix of codes we have found online :slight_smile:

As for the Loop situation, the thing we are trying to accomplish i having multiple "pages" on our little LCD, that all have live data, from the car that we are hooking it up to, when we create on page with RPM it is fine and showing nice data, where when we create more pages it only take like a screenshot, i think the problem is the break that we use for case, how does that sound?
I thought that Loop was the term used for when it is constantly going through the code "looping" it as i would say?

If you have any other suggestions to what would be a good method to creating these pages i would gladly hear them, especially if you also know some guides :smiley:

void loop()
{

  
 if (digitalRead(switchPin) == LOW){  
   delay(700);                                                    // delay to debounce switch, Hold it down for scroll

   Display = Display + 1;
   if(Display > 5){                                               
     lcd.clear();
     Display = 1;
   }
   
   switch (Display) {
     case 1: {    
       lcd.clear();
       int Speed;                                                        //Unit: km/h
  if (obd.readPID(PID_SPEED, Speed)) 
       lcd.setCursor(0, 0);
       lcd.print("Speed");
       lcd.setCursor(6, 0);
       lcd.print(Speed);
       lcd.setCursor(12, 0);
       lcd.print("km/t");
     }
     case 2: {
       etc...
     }
   }
 }
}

Here is an example of what the idea from us was.

UKhelibob sorry as septillion pointed out i didn't read the forum guide, i am sorry for that :slight_smile:

Also if you know what "pages" really should be called, if they have an actual unified name, that would help me research, it would be a great help :slight_smile:

I don't see where looping within cases comes in.

Using switch/case determine which data is to be displayed and display the text and data if this is the first time in this case. Next time through loop(), if you are still in the same case and the data has changed then display it (no need to rewrite the text)

Yea that was the same thought we had, but when we connect the board to a car, it takes a "data screen shot" of the exact moment and we can switch between them all, but none on them are live :slight_smile:

none on them are live

When and where are you reading the sensors ?
Please post an example of code that exhibits the problem. To keep it simple it only needs 2 sensors and cases.

  if (obd.readPID(PID_SPEED, Speed)) 
       lcd.setCursor(0, 0);
       lcd.print("Speed");
       lcd.setCursor(6, 0);
       lcd.print(Speed);

Does any of this code update the Speed variable ?

When the vehicle is turned on, we use an OBD converter and get the data from the cars own sensors through the plug.

Okay here are the 2 cases that we are trying to get working :slight_smile:

void loop()
{
//    int #;                                                      // save/initiate PID 'value' as new name, return true on success 
//    if (obd.readPID(PID_#, #)) 
  
 if (digitalRead(switchPin) == LOW){  
   delay(700);                                                    // delay to debounce switch, Hold it down for scroll

   Display = Display + 1;
   if(Display > 5){                                               // Number of pages (Display > #pages)
     lcd.clear();
     Display = 1;
   }
   
   switch (Display) {
     case 1: {    
       lcd.clear();
         
int Speed;                                                        //Unit: km/h
  if (obd.readPID(PID_SPEED, Speed)) 
       lcd.setCursor(0, 0);
       lcd.print("Speed");
       lcd.setCursor(6, 0);
       lcd.print(Speed);
       lcd.setCursor(12, 0);
       lcd.print("km/t");

int Water;                                                          //Unit: Degrees C
  if (obd.readPID(PID_COOLANT_TEMP, Water)) 
       lcd.setCursor(0, 1);
       lcd.print("Temp");
       lcd.setCursor(5, 1);
       lcd.print(Water);

int rpm;                                                          //Unit: Ratio
  if (obd.readPID(PID_RPM, rpm)) 

       lcd.setCursor(8, 1);
       lcd.print("RPM");
       lcd.setCursor(12, 1);
       lcd.print(rpm);
       
    {     digitalWrite(Green, rpm > 2500 ? HIGH : LOW);           // light the LED's when RPM exceeds wanted limit
          digitalWrite(Yellow, rpm > 3500 ? HIGH : LOW);
          digitalWrite(Red, rpm > 4000 ? HIGH : LOW);}
       
       break;     }
       
     case 2: {        
       lcd.clear();
       
 int IntakeTemp;                                                   //Unit: Degrees C
  if (obd.readPID(PID_INTAKE_TEMP, IntakeTemp))       
       lcd.setCursor(0, 0);
       lcd.print("Intake Temp");
       lcd.setCursor(13, 0);
       lcd.print(IntakeTemp);
       
int MAF;                                                          //Unit: g/s
  if (obd.readPID(PID_MAF_FLOW, MAF))       
       lcd.setCursor(0, 1);
       lcd.print("MAF");
       lcd.setCursor(4, 1);
       lcd.print(MAF);

int AFR;                                                          //Unit: Ratio
  if (obd.readPID(PID_AIR_FUEL_EQUIV_RATIO, AFR))
       lcd.setCursor(8, 1);
       lcd.print("AFR");
       lcd.setCursor(12, 1);
       lcd.print(AFR);
       
       break;     }

Yea if we put it in without using case it works, but as soon as it goes into a case it becomes a freeze frame.

if we put it in without using case it works

Please post the complete program that works and the complete one that doesn't

Formatted better part of your code looks like this

          if (obd.readPID(PID_SPEED, Speed))
            lcd.setCursor(0, 0);
          lcd.print("Speed");
          lcd.setCursor(6, 0);
          lcd.print(Speed);
          lcd.setCursor(12, 0);
          lcd.print("km/t");

Which lines of code do you intend to be executed if the test returns true and if it returns false ?

Your code is pretty fine. Only thing is, you only write the screen after you pressed the button. It has nothing to do with the break but all with the fact evything is inside the

if (digitalRead(switchPin) == LOW) {

You have to separate the printing to the screen and the selection of the page. And when updating the screen you only need to update the variables.

Here is the code that worked:

// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int Green = 7;      // select the pin for the LED
int Yellow = 8;  
int Red = 9;

#include <Wire.h>
#include <OBD.h>

COBD obd;

void setup() {
  // set up the number of columns and rows on the LCD
  lcd.begin(16, 2);

// Pin Setup
  pinMode(Green, OUTPUT);
  pinMode(Yellow, OUTPUT);
  pinMode(Red, OUTPUT);
  
 // start communication with OBD-II adapter
  obd.begin();
  // initiate OBD-II connection until success
  while (!obd.init());
  
  // Print a message to the LCD.
  lcd.print("Speed");
  // set the cursor to column 0, line 1
  // line 1 is the second row, since counting begins with 0

  lcd.setCursor(12, 0);
  lcd.print("km/t");
  lcd.setCursor(0, 1);
  lcd.print("Temp");
  lcd.setCursor(8, 1);
  lcd.print("RPM");
}

void loop() {


int rpm;
  // save engine RPM in variable 'value', return true on success
  if (obd.readPID(PID_RPM, rpm)) {
    // light on LED on Arduino board when the RPM exceeds 3000
    digitalWrite(Green, rpm > 3000 ? HIGH : LOW);
    digitalWrite(Yellow, rpm > 4000 ? HIGH : LOW);
    digitalWrite(Red, rpm > 5000 ? HIGH : LOW);
  }
lcd.setCursor(12, 1);
lcd.print(rpm);

   int Speed;
  // save engine RPM in variable 'value', return true on success
  if (obd.readPID(PID_SPEED, Speed)) 
lcd.setCursor(6, 0);
lcd.print(Speed);

  int Water;
  // save engine RPM in variable 'value', return true on success
  if (obd.readPID(PID_COOLANT_TEMP, Water)) 
lcd.setCursor(5, 1);
lcd.print(Water);
}

Here is the full code for our project that does not work:

#include <LiquidCrystal.h>                  //LCD Screen Library and Pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int switchPin = 6;                          // momentary switch (Push Button) on Pin 6, other side connected to ground (Page Turner)
int Display = 0;
int Green = 7;                              // select the pins and names for the LED's
int Yellow = 8;  
int Red = 9;

#include <Wire.h>                           //Library for Data Lines Between OBD-Plug and Arduino in 8-bit
#include <OBD.h>                            //Library for OBD PID Codes

COBD obd;                                   //* for Model A (UART version) (Just write it)
  
void setup()
{
 lcd.begin(16, 2);
 pinMode(switchPin, INPUT);
 digitalWrite(switchPin, HIGH);             // momentary switch (Push Button) turn on pullup resistor
 
 lcd.begin(16, 2);                          // set up the number of columns and rows on the LCD (16x2)

 pinMode(Green, OUTPUT);                    // LED Pin Setup
 pinMode(Yellow, OUTPUT);
 pinMode(Red, OUTPUT);
  
 obd.begin();                               // start communication with OBD-II adapter
 while (!obd.init());                       // initiate OBD-II connection until success
  
 lcd.print("OK Project OBDII");             // Print a Start message to the LCD.
 lcd.setCursor(0,1);                        // set the cursor to column 0, line 1
 lcd.print("Beta Version");                 // line 1 is the second row, since counting begins with 0

}
    
void loop()
{
//    int #;                                                      // save/initiate PID 'value' as new name, return true on success 
//    if (obd.readPID(PID_#, #)) 
  
 if (digitalRead(switchPin) == LOW){  
   delay(700);                                                    // delay to debounce switch, Hold it down for scroll

   Display = Display + 1;
   if(Display > 5){                                               // Number of pages (Display > #pages)
     lcd.clear();
     Display = 1;
   }
   
   switch (Display) {
     case 1: {    
       lcd.clear();
         
int Speed;                                                        //Unit: km/h
  if (obd.readPID(PID_SPEED, Speed)) 
       lcd.setCursor(0, 0);
       lcd.print("Speed");
       lcd.setCursor(6, 0);
       lcd.print(Speed);
       lcd.setCursor(12, 0);
       lcd.print("km/t");

int Water;                                                          //Unit: Degrees C
  if (obd.readPID(PID_COOLANT_TEMP, Water)) 
       lcd.setCursor(0, 1);
       lcd.print("Temp");
       lcd.setCursor(5, 1);
       lcd.print(Water);

int rpm;                                                          //Unit: Ratio
  if (obd.readPID(PID_RPM, rpm)) 

       lcd.setCursor(8, 1);
       lcd.print("RPM");
       lcd.setCursor(12, 1);
       lcd.print(rpm);
       
    {     digitalWrite(Green, rpm > 2500 ? HIGH : LOW);           // light the LED's when RPM exceeds wanted limit
          digitalWrite(Yellow, rpm > 3500 ? HIGH : LOW);
          digitalWrite(Red, rpm > 4000 ? HIGH : LOW);}
       
       break;     }
       
     case 2: {        
       lcd.clear();
       
 int IntakeTemp;                                                   //Unit: Degrees C
  if (obd.readPID(PID_INTAKE_TEMP, IntakeTemp))       
       lcd.setCursor(0, 0);
       lcd.print("Intake Temp");
       lcd.setCursor(13, 0);
       lcd.print(IntakeTemp);
       
int MAF;                                                          //Unit: g/s
  if (obd.readPID(PID_MAF_FLOW, MAF))       
       lcd.setCursor(0, 1);
       lcd.print("MAF");
       lcd.setCursor(4, 1);
       lcd.print(MAF);

int AFR;                                                          //Unit: Ratio
  if (obd.readPID(PID_AIR_FUEL_EQUIV_RATIO, AFR))
       lcd.setCursor(8, 1);
       lcd.print("AFR");
       lcd.setCursor(12, 1);
       lcd.print(AFR);
       
       break;     }
       
      case 3: {        
        lcd.clear();
        
int Runtime;                                                      //Unit: s since Engine start
  if (obd.readPID(PID_RUNTIME, Runtime))          
        lcd.setCursor(0, 0);
        lcd.print("Runtime");
        lcd.setCursor(8, 0);
        lcd.print(Runtime);
        
int FuelLVL;                                                      //Unit: %
  if (obd.readPID(PID_FUEL_LEVEL, FuelLVL)) 
        lcd.setCursor(0, 1);
        lcd.print("Fuel Level");
        lcd.setCursor(11, 1);
        lcd.print(FuelLVL);
        lcd.setCursor(15, 1);
        lcd.print("%");
        
        break;      }
      
         case 4: {
       lcd.clear();
       
int Throttle;                                                     //Unit: %
  if (obd.readPID(PID_THROTTLE, Throttle)) 
       lcd.setCursor(0, 0);
       lcd.print("Throttle");
       lcd.setCursor(10, 0);
       lcd.print(Throttle);
       lcd.setCursor(15, 0);
       lcd.print("%");
 
int Tadv;                                                         //Unit: Degrees before TDC
  if (obd.readPID(PID_TIMING_ADVANCE, Tadv)) 
       lcd.setCursor(0, 1);
       lcd.print("Timing adv");
       lcd.setCursor(13, 1);
       lcd.print(Tadv);
       
       break;     }
     
        case 5: {
       lcd.clear();
       
int Oil;                                                          //Unit: Degrees C
  if (obd.readPID(PID_ENGINE_OIL_TEMP, Oil)) 
       lcd.setCursor(0, 0);
       lcd.print("Oil Temp");
       lcd.setCursor(10, 0);
       lcd.print(Oil);
       
int ECU_V;                                                        //Unit: V
  if (obd.readPID(PID_CONTROL_MODULE_VOLTAGE, ECU_V))    
       lcd.setCursor(0, 1);
       lcd.print("ECU Voltage");
       lcd.setCursor(12, 1);
       lcd.print(ECU_V);
       
       break;     }
 }
}
}

septillion but it does not read every time we press the button, it only reads the first time? :slight_smile:

Only the first time what? Turn it on? Press a button?

I doubt the first because it only prints something OBD Beta and then waits for a button.

And when "it does not work", what does happen? And what do you expect to happen?

Your comment states "scroll thru" ... when button is pushed
You detect the push, wait for 700 ms than run thru the first switch.
You need to hold the button down for scrolling thru the switch.
And 700 ms is too fast anyway.
When you want do more than just (up) scrolling you will find that loop() is not the best tool for the job of any complexity.

Good luck.

Jim

Every time we press a button it takes a screen shot of the exact moment and the data that we have on the page. But only when we switch screens.

We only have one single button.

What i mean by not working is that it is not updating, when we are driving we want the RPM to be constantly changing so it fits what is says in the dash.

The scrolling part is not needed it was just discovered that if we kept the button down it would scroll through the pages.

Ickxz:
Every time we press a button it takes a screen shot of the exact moment and the data that we have on the page. But only when we switch screens.

That's exactly what I said. And I already gave you the solution.

septillion:
You have to separate the printing to the screen and the selection of the page. And when updating the screen you only need to update the variables.

So use a variable to hold which page you are on but only increment that variable after the button press (Hint, add proper debounce instead of the stupid 700ms delay()). All the writing to the screen needs to be outside the button checking.

And two extra bonus points.

  1. Only update the variables on the screen, not the whole screen
  2. Only update the screen like 5 times a second max, not every pass through loop. (Hint, Blink without delay :wink: )

septillion okay i think i understand what you are saying, but since im still very new to this, could you give a simple example of how that could be done?

So i have something to go by :slight_smile:

Split it in three easy parts you just do in loop(). I'm not going to give you all the code, just the concept.

  1. Simply a routine to increase the page index variable. Also, to only change the static content when you change page set a extra flag. And to keep things simple, I would grab Bounce2
button.update()
if(button.fell()){
  pageIndex++;
  pageChanged = true;
  
  //Check to loop around to the first
  if(pageIndex >= NumberOfPages){
    pageIndex == 0;
  }
}
  1. A routine to print all the static stuff after a page change
if(pageChanged){
  lcd.clear();
  //now draw the static text of that page
  //you can use a switch like you did
}
  1. A routine to update the variables on the screen
//update every ScreenUpdateInterval the variables
//or do it direct when new screen selected
if(millis() - lastScreenUpdate > ScreenUpdateInterval || pageChanged){
  pageChanged = false; //reset it
  lastScreenUpdate = millis();
  
  //now clear the variable part of the screen and print the new variable values to the screen
  //just like you did before in the switch
  //You can again use a switch like before to have different actions for different pages
}

THANK YOU this defiantly gave us some ideas and we will go from there, thank you for all your time :slight_smile: