Go Down

Topic: No if's or while's in a switch case? (Read 2207 times) previous topic - next topic

Tumbleweed

For people who actually know how to code this will seem simple, but no matter what I try I can not get an if statement, while loop, or for loop to work inside of a switch case statement.
Do I need to use a bunch of if statements instead, or put switch cases inside fewer ifs and whiles?
I am trying to build an Arduino based leveling system for my 5th wheel based on the LevelEasy commercial project, but with some improvements when finished. I built one with mercury switches, SRCs, and relays that works well but requires more user interaction than i like.
I figure I have about 300 hours trying to program it and just can't get it.The mechanical and electrical parts all check out, I have o-scopes, function generators, and years of hobby experience for that, just can't get this thing to check a switch or variable when it is in a switch case, and then change actions accordingly.
I thought a switch case was just a neater way of having a bunch of if statements, but I can't find an example of one with any other control statements inside it. Is this not possible?
Thanks

a sample function with problem

Code: [Select]

void memSet()
{

  lcd_key = read_LCD_buttons();  // read the buttons

    switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
  case btnHITCH:

    {   
      hitchVHigh = average;       //Get the upper height to set hitchDifference
    }

    break;


  case btnLEVEL:               
    { 
      EEPROM.write((average / 4),1);      // save level value to eeprom
    }
    break;


  case btnTRAVEL:
    {
      hitchVLow = average;                        //get lower hitched value
      hitchDifference = hitchVHigh - hitchVLow;   //calculate hitch offset
      EEPROM.write(hitchDifference,12);           //write offset to eeprom 

    }
    break;


   
  }


}


Einstein once said you don't really understand anything until you can explain it to your Grandmother

Tumbleweed

And another, the first one won't write to eeprom, this one ignores the pin or variable values.
Code: [Select]


    lcd_key = read_LCD_buttons();  // read the buttons

      switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
    case btnHITCH:

      {   
        if (average < unHooked)
        {
          lcd.setCursor(0,0); 
          lcd.print("   HITCH   ");
          digitalWrite(upoutpin, HIGH);
        }
      }

      break;


    case btnUP:
      {

        lcd.setCursor(0,0);
        lcd.print(" MANUAL RAISE ");   
        digitalWrite(upoutpin, HIGH);        //raise front of trailer manually

      }
      break;

    case btnDOWN:
      {
        if (digitalRead(legsw == HIGH))
        {
          lcd.setCursor(0,0);
          lcd.print("MANUAL LOWER    ");
          digitalWrite(downoutpin, HIGH);
        }
      }
      break;



    case btnLEVEL:               // function here to save level value and/or level trailer
      { 

        if (resetEeprom == LOW)            // check for reset sw
        { 
          EEPROM.write (average,1);       //store the level value in eeprom
        }   
        else
        {

          if (digitalRead(legsw == HIGH && average != (levelVal *4 )))
          {
            if(average > (levelVal *4))
            {
              digitalWrite (downoutpin, HIGH );         
              lcd.setCursor(0,0);
              lcd.print("   LEVELING   ");
            }
            else
            {
              digitalWrite(upoutpin, HIGH);
              lcd.setCursor(0,0);
              lcd.print("   LEVELING   ");
            }
          }
        }
        break;
      }

    case btnTRAVEL:
      {
               
          if (digitalRead(legsw == HIGH))
          {
            digitalWrite(downoutpin, HIGH);   
            lcd.setCursor(0,0); 
            lcd.print("RAISING LEGS   ");    //Need limit sw to turn off
          }
       
        break;

      }
    case btnNONE:
      {

        lcd.setCursor(0,0); 
        lcd.print("     NONE    ");
        digitalWrite(upoutpin, LOW);
        digitalWrite(downoutpin, LOW);
      }
      break;
    }

    // delay before next reading:
    //delay(100);
  }

}
Einstein once said you don't really understand anything until you can explain it to your Grandmother

Morris Dovey

These statements work as well as ever inside switch statements. If your code results don't match your expectations, then the problem must lie in either the code or the expectations. :)

I suggest adding some Serial.print() calls to locate problems. I would start with outputting the value of lcd_key to verify that it's what you think it should be...
There's always a better way!

Osgeld

post your entire code, I see nothing outstanding in the examples provided at first glance (attach it as a text file if need be)
http://arduino.cc/forum/index.php?action=unread;boards=2,3,4,5,67,6,7,8,9,10,11,66,12,13,15,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,86,87,89,1;ALL

CrossRoads

#4
Apr 24, 2012, 06:54 am Last Edit: Apr 24, 2012, 06:58 am by CrossRoads Reason: 1
What is the value of lcd_key after it is called?
lcd_key = read_LCD_buttons();  

Does it equal btnHITCH, btnLEVEL, etc, or does lcd_key = 1,2,3 etc?

Some print statements as Morris suggested will help:

 lcd_key = read_LCD_buttons();  // read the buttons
 
Serial.print (lcd_key); // what'd you get back?
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Nick Gammon


I thought a switch case was just a neater way of having a bunch of if statements, but I can't find an example of one with any other control statements inside it. Is this not possible?


Absolutely it is possible. Post code that demonstrates the problem. Not a snippet.

Stripping your example back to compile, like this:

Code: [Select]
void memSet()
{
int lcd_key = 1;


    switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
  case 1:

    {   

    }

    break;


  case 2:               
    { 

    }
    break;


  case 3:
    {


    }
    break;


   
  }


}

void setup () {}
void loop () {}


I get no errors.

Quote
I can not get an if statement, while loop, or for loop to work inside of a switch case statement.


Your example did not have a while, if or for in it, so I don't know what it was supposed to prove.

Perhaps also post the error message?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon


Do I need to use a bunch of if statements instead, or put switch cases inside fewer ifs and whiles?


Or are you saying it compiled but didn't actually work? Well it would be clearer to say so, and demonstrate conclusively in what way it didn't work.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Tumbleweed

OK, removed some comments, short enough now
will follow with more details
Code: [Select]

/*

ADXL3xx

Reads an  MMs7361 accelerometer and communicates the
acceleration to the computer.  Using a MMS7361 analog breakout instead
http://www.arduino.cc/en/Tutorial/ADXL3xx

The circuit:
analog 0: input for the shield buttons
analog 1: power pin to wake accelerometer
analog 2: x-axis
analog 3: y-axis
analog 4: z-axis
digital 2: to transistor controlling 12v auto relay
digital 3: to transistor controlling 12v auto relay
digital 11: leg limit switch
digital 10: pwm output for lcd led
*/
#include <LiquidCrystal.h>
#include <EEPROM.h>

// select the pins used on the LCD panel (RS,E,D4,D5,D6,D7)  (D10 is backlight control)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);        // pinout for DFRobot lcd

// these constants describe the pins. They won't change:

const int upoutpin = 2;             //  up relay power
const int downoutpin = 3;            // down relay power (D4-9: LCD)
const int numReadings = 10;          //number of pin readings to average
const int dimLed = 10;         // Led brightness control
const int legsw = 11;             //
const int resetEeprom = 12;
const int slpin = 15;                // pin to wake or power-save accelerometer

// set up averaging parameters
int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int inputPin = A2;              // input for x axis
int lcd_key     = 0;            //setup switch for buttons
int adc_key_in  = 0;

#define btnHITCH     0
#define btnUP        1
#define btnDOWN      2
#define btnLEVEL     3
#define btnTRAVEL    4
#define btnNONE      6

int x,y,z;
float vx;
int levelVal = 0;                         // store level position
int hitchVLow;                 // average value when hitched
int hitchVHigh;                 // average value when raised
int hitchDifference;              // store this hitchVHigh - hitchVLow
int unHooked;                      //unhitched hieght


// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);      // read the value from the sensor
  // my buttons when read are centered at these valies: 0, 110, 300, 475, 600 using 3.3 aref with 1K resistor
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  if (adc_key_in < 50)   return btnHITCH; 
  if (adc_key_in < 180)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 545)  return btnLEVEL;
  if (adc_key_in < 800)  return btnTRAVEL;       // Check values when using AREF pin at 3.3v

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


void setup() {
  // initialize the serial communications:
  lcd.begin(16, 2);              // start the library
  lcd.setCursor(0,0);
  // analogReference(EXTERNAL);                             // set reference to 3.3v - use 3.3v power out
  pinMode(slpin, OUTPUT);                                // ready pin wake up accelerometer
  pinMode(upoutpin, OUTPUT);                              // ready up relay power pin           
  pinMode(downoutpin, OUTPUT);                            // ready down relay power pin
  pinMode (legsw, INPUT);                          // ready saftey sw
  pinMode (dimLed, OUTPUT);                      // ready led brite control
  pinMode (resetEeprom, INPUT);                  // ready pin 12
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;



  digitalWrite(resetEeprom, HIGH);                      // set pullup resistorit
  digitalWrite(slpin, HIGH);                              // wake accelerometer
  digitalWrite(legsw, HIGH);                           // set pullup resistor
  analogWrite (dimLed, 150);                           // dim the led to save current

  levelVal = EEPROM.read(1);                         //Get stored level value
  hitchDifference = EEPROM.read(12);                 //Get stored hitch offset
}


void memSet()
{

  lcd_key = read_LCD_buttons();  // read the buttons

    switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
  case btnHITCH:

    {   
      hitchVHigh = average;       //Get the upper height to set hitchDifference
    }

    break;


  case btnLEVEL:               
    { 
      EEPROM.write((average / 4),1);      // save level value to eeprom
    }
    break;


  case btnTRAVEL:
    {
      hitchVLow = average;                        //get lower hitched value
      hitchDifference = hitchVHigh - hitchVLow;   //calculate hitch offset
      EEPROM.write(hitchDifference,12);           //write offset to eeprom 

    }
    break;   
  }
}
void loop()
{

  if (resetEeprom == LOW)
  {
    memSet();
  }
  else
  {

    // subtract the last reading:
    total = total - readings[index];         
    // read from the sensor: 
    readings[index] = analogRead(inputPin);
    // add the reading to the total:
    total= total + readings[index];       
    // advance to the next position in the array: 
    index = index + 1;                   

    // if we're at the end of the array...
    if (index >= numReadings)             
      // ...wrap around to the beginning:
      index = 0;                           

    // calculate the average:
    average = total / numReadings;         

    // Convert ADC values to voltages
    // The formula for voltage conversion is v = (ADCREAD*VREF/1023)-ZGV, where ZGV is "Zero-G voltage" (voltage at 0G)
    // ZGV is found in the spec sheet and happens to be 1.62 or 1/2 VCC in our case.  Warning: you need to make the variable signed!
    // The formula for G conversion is g = v/SENSITIVITY.  The sensitvity is also found in the spec sheet and happens to be 800 mV/g here

    // Remember to make your units consistent! (g = v[V]*1000 / SEN [mV] )
    vx = (average/5.68)-levelVal;
    // gx = vx*10/8;
    // vy = (y*3.3/1023)-1.62;
    // gy = vy*10/8;
    //  vz = (z*3.3/1023)-1.62;
    //  gz = vz*10/8;

    lcd.setCursor(0,1);
    lcd.print("X = ");
    lcd.print(vx); 




    lcd_key = read_LCD_buttons();  // read the buttons

      switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
    case btnHITCH:

      {   
        if (average < unHooked)
        {
          lcd.setCursor(0,0); 
          lcd.print("   HITCH   ");
          digitalWrite(upoutpin, HIGH);
        }
      }

      break;


    case btnUP:
      {

        lcd.setCursor(0,0);
        lcd.print(" MANUAL RAISE ");   
        digitalWrite(upoutpin, HIGH);        //raise front of trailer manually

      }
      break;


    case btnDOWN:
      {
        if (digitalRead(legsw == HIGH))
        {
          lcd.setCursor(0,0);
          lcd.print("MANUAL LOWER    ");
          digitalWrite(downoutpin, HIGH);
        }
      }
      break;



    case btnLEVEL:               // function here to save level value and/or level trailer
      { 

        if (resetEeprom == LOW)            // check for reset sw
        { 
          EEPROM.write (average,1);       //store the level value in eeprom
        }   
        else
        {

          if (digitalRead(legsw == HIGH && average != (levelVal *4 )))
          {
            if(average > (levelVal *4))
            {
              digitalWrite (downoutpin, HIGH );         
              lcd.setCursor(0,0);
              lcd.print("   LEVELING   ");
            }
            else
            {
              digitalWrite(upoutpin, HIGH);
              lcd.setCursor(0,0);
              lcd.print("   LEVELING   ");
            }
          }
        }
        break;
      }

    case btnTRAVEL:
      {
               
          if (digitalRead(legsw == HIGH))      // limit sw to turn off
          {
            digitalWrite(downoutpin, HIGH);   
            lcd.setCursor(0,0); 
            lcd.print("RAISING LEGS   ");   
          }
       
        break;

      }
    case btnNONE:
      {

        lcd.setCursor(0,0); 
        lcd.print("     NONE    ");
        digitalWrite(upoutpin, LOW);
        digitalWrite(downoutpin, LOW);
      }
      break;
    }

    // delay before next reading:
    //delay(100);
  }

}
Einstein once said you don't really understand anything until you can explain it to your Grandmother

Tumbleweed

Thanks for the replies,
Yes it does compile. The switch case that in in the main loop function will move the linear actuator (I have actually built a small mock-up of the mechanical functions including limit switches, accelerometer, relays and actuators), but ignores the limit switches or any control statements put in to read the accelerometer .  The accelerometer puts out a ten reading average to the lcd fine.

The problem with the external memset() funtion is it doesn't write to the eeprom like it is supposed to.

I know it will be simple when you tell me, that's why I've waited so long, trying to find my mistake myself.
Is there a way to put this code into a regular C IDE with a proper debugger? Stepping in  while it executes sure would be nice.
Thanks again
Einstein once said you don't really understand anything until you can explain it to your Grandmother

AWOL

#9
Apr 24, 2012, 01:48 pm Last Edit: Apr 24, 2012, 01:49 pm by AWOL Reason: 1
Code: [Select]
if (digitalRead(legsw == HIGH))
BZZZZT!
Code: [Select]
if (digitalRead(legsw == HIGH && average != (levelVal *4 )))
BZZZZT!
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Nick Gammon

Well spotted AWOL.

I was concentrating on why the forum hung, my name disappeared, and I was being insulted by idiots. But you stayed on focus. :)
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Tumbleweed

Thanks for the help,
obviously the syntax is wrong, where can I find intructions/examples to fix it?
Einstein once said you don't really understand anything until you can explain it to your Grandmother

Nick Gammon

As an example:

Code: [Select]
if (digitalRead(legsw == HIGH))


should be:


Code: [Select]
if (digitalRead(legsw) == HIGH)


Subtle but important.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

AWOL

No, the syntax is correct, otherwise the compiler would have complained.
It's the semantics that are wrong.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Tumbleweed

Thanks again,
I see what is wrong with the second example you gave too.
Sooooo embarasing, kind of like when this old southern boy goes in a nice restaurant and tries to pronounce the menu.
Einstein once said you don't really understand anything until you can explain it to your Grandmother

Go Up