Go Down

Topic: Switch / Case with multiple variables? (Read 5156 times) previous topic - next topic

ffmurray

Ive been playing with switch / case and was wondering if there is a way to use multiple variables
something like

switch (a, b c)
{
    case 1, 2, 3:
    //do something
    return;
}

i know that code wont compile, but is there a proper syntax for something like that or is there a different tool?

majenko

You cannot do that with case.  You will have to use if / else if etc.

ffmurray

too bad there isnt something like switch / case for multiple variables, that would be slick

majenko


AWOL

If you tell us what it is you're trying to do, we could maybe suggest a solution.
"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.

ffmurray

im trying to program a wall avoiding robot,  it has a ping)) sensor on a servo that gets distances from the left right and center then decides what to do.  if it sees something on the left side it will turn right even if it should back up or something because this comes first in the code.  I would like to write something that considers all the input before deciding but dont know what tool to use or how to format it with if, else if statements

here is my current main loop, i think most of the function names are pretty self explanitory
Code: [Select]

void loop()
{
  directionalPing();
  if(pingLeft <= 6)
    {
      turnRight(600);
      return;
    }
  if(pingRight <= 6)
    {
      turnLeft(600);
      return;
    }
  if(pingForward <= 6)
    {
      reverse(200);
      turnLeft(600);
      return;
    }
  if(pingForward > 6)
    {
      forward(500);
      reverse(50);
      return;
    }
}

robtillaart

#6
Jun 09, 2012, 08:37 am Last Edit: Jun 09, 2012, 08:45 am by robtillaart Reason: 1
Quote
Ive been playing with switch / case and was wondering if there is a way to use multiple variables
something like

switch (a, b c)
{
   case 1, 2, 3:
   //do something
   return;
}

i know that code wont compile, but is there a proper syntax for something like that or is there a different tool?


1) you can nest switches

switch (a, b c)
{
   case 1:
   switch(b)
   {
      case 2:
etc

will result is a forest of code.

2) combine abc to one state (bit stuffing)

depending on the range of the values a,b,c you can pack these three vars in one .
suppose a = 0-3 (needs 2 bits)  and b = 0-31 (5 bits) and c = 0-8, (3 bits)
then you can make

int val = a + b << 2 + c << 7   // val = [0000 00CC CBBB BBAA]  bit pattern

and do  the same for all relevant values.
As this is quite error prone you can "macrofy" this, see the sample sketch below (IDE 0.22)

Code: [Select]

//
//    FILE: MultiSwitch.pde
//  AUTHOR: Rob Tillaart
//    DATE: 09-06-2012
//
// PUPROSE: macrofying a multiple switch
//

#define SWITCH(a,b,c) switch(a + b<<2 + c<<7)
#define CASE(a,b,c) case(a + b<<2 + c<<7)

void setup()
{
 Serial.begin(9600);
 Serial.println("start...");
}

void loop()
{
 int a=2, b=3, c=4;
 int x = 5;

 SWITCH(a,b,c)
 {
   CASE(1,2,3):
   x=4;
   break;
   CASE(2,3,4):
   x=3;
   break;
 default:
   x=6;
   break;
 }
 Serial.println(x);
 delay(500);

 a=1, b=2, c=3;

 SWITCH(a,b,c)
 {
   CASE(1,2,3):
   x=4;
   break;
   CASE(2,3,4):
   x=3;
   break;
 default:
   x=6;
   break;
 }
 Serial.println(x);
 delay(500);
 
 a++;
 
 SWITCH(a,b,c)
 {
   CASE(1,2,3):
   x=4;
   break;
   CASE(2,3,4):
   x=3;
   break;
 default:
   x=6;
   break;
 }
 Serial.println(x);
 delay(500);
}


notes:
- all warnings about using macros apply,
- there are limitations how long the bitpattern can be => use a long for var a to maximise the trick.
- multiple multicase switches need additional macros

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart


append.

instead of a macro one could think of using a function, but that doesn't work as the case is expecting a const value compile time. However one could do with just one macro mimicing the function. (coffee really clears up the mind ;)

So here is the code with a normal switch and only one macro
Code: [Select]

//
//    FILE: MultiSwitch.pde
//  AUTHOR: Rob Tillaart
//    DATE: 09-06-2012
//
// PUPROSE: macrofying a multiple switch
//

#define H(a,b,c) (a + b<<2 + c<<7)

void setup()
{
  Serial.begin(9600);
  Serial.println("start...");
}

void loop()
{
  int a=2, b=3, c=4;
  int x = 5;

  switch(H(a,b,c))
  {
    case(H(1,2,3)):
    x=4;
    break;
    case(H(2,3,4)):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

  a=1, b=2, c=3;

  switch(H(a,b,c))
  {
    case(H(1,2,3)):
    x=4;
    break;
    case(H(2,3,4)):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

 
  a++;
 
  switch(H(a,b,c))
  {
    case(H(1,2,3)):
    x=4;
    break;
    case(H(2,3,4)):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

}




Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

ffmurray

Thank you robtillaart,  Im working on using that technique in my code now. 

wildbill

Quote
I would like to write something that considers all the input before deciding but dont know what tool to use or how to format it with if, else if statements


I know I pointed you down this road, but what's the requirement here? Once you have all the various ping measures, what's your algorithm for deciding how to move?

ffmurray

I don't quite know how to go about developing an algorithm for the movement (im still pretty new at programming anything).  I would like to start with something like if pingLeft pingRight and pingForward all revieve <6 then it backs up until it registers a longer distance on one of the sides and then turns that way.

but on a more general programming question:
what are various ways people use to imagine and or visualize different algorithms?

ffmurray

#11
Jun 10, 2012, 07:03 am Last Edit: Jun 10, 2012, 07:05 am by ffmurray Reason: 1
so this is kinda what i had in mind for the possible decisions - indicates a reading greater than 12"  + indicates a reading of either 6 or between 6 and 12 depending on situation  but im still not quite sure how to implement it into code that checks all 3 reading before making a decision


1) L-  F-  R+  |  x<6: hard turn left
                  |  6> x >12 gentle turn left


2) L- F+ R-    |  reverse measure again turn towards greatest distance


3) L+ F- R=   |  y<6: hard turn right
                  |  6> y >12 gentle turn right


4) L- F+ R+   |  hard turn left


5) L+ F+ R-   |  hard turn right


6) L+ F+ R+  |  reverse, check L & R turn towards greater distance


7) L+ F- R+   |  if distance between objects is greater than width of robot continue forward
                  |  if distance between objects is smaller than robot reverse and turn towards
                  |  greatest reading




EDIT:  does anyone know of somewhere i could go on them tharr interwebs to learn about such a thing? (somewhere or something free)

PeterH

What you're trying to do would make sense if you were trying to create a compound finite state machine - although there are better ways to do it.

But it seems to me that is not what you need here. As I see it, you have a couple of algorithms to decide what action to take, and there is some precedence between them. If there is a wall in front then back up; otherwise if there is an obstruction to the left then steer right, and so on.

In that case I'd suggest using simple if/else style logic to decide what action to take and then have a separate chunk of code that carries it out. If there are lots of actions you might find it convenient to define them as enumerated values and then use a switch statement to execute the chosen action.
I only provide help via the forum - please do not contact me for private consultancy.

ffmurray

Quote
What you're trying to do would make sense if you were trying to create a compound finite state machine - although there are better ways to do it.

what sort of better ways?  I dont really care so much about building the robot, but learning to program in general, the tools of problem solving used to write code.

hubajs


when I recieve UDP command, I use switch in following way to join several possibilities to one result:

Code: [Select]

    if(packetBuffer[0] == 'R' || packetBuffer[0] == 'r') switch_value = 0; //reset
    if(packetBuffer[0] == 'W' || packetBuffer[0] == 'w') switch_value = 1; //speed up
    if(packetBuffer[0] == 'S' || packetBuffer[0] == 's') switch_value = 2; //speed down

    switch (switch_value) {
    case 0:
      servoPos = 90;           // tell servo to go to position servoPos
      servoMove(servoPos);
      led_blink();
      break;
    case 1:
      if( servoPos >= 10 && servoPos <= 165) {
      servoPos = servoPos+5;           // tell servo to go to position servoPos
      servoMove(servoPos);
      }
      led_blink();
      break;
    case 2:
      if( servoPos >= 15 && servoPos <= 165) {
      servoPos = servoPos-5;           // tell servo to go to position servoPos
      servoMove(servoPos);
      }
      led_blink();
      break;
    default:
      // if nothing else matches, do the default
      // default is optional

Go Up