Change variable without leaving a case

Hello there,

I am programming a self driving "robot". The robot has two wheels each of them connected to a motor. I vary the robot's speed with PWM and I make the robot turn by turning one wheel forward and the other one backward.

There are 3 modes: 1: Stop, 2: self drive, 3. drive manually (with the buttons of the remote)

The robot is controlled by an IR remote (IR receiver connected to the arduino).

In "auto mode", I can change the speed while driving. But I can't do so while driving in manual mode. The variable for the speed (spd) changes to the new value but it's not written in the "working" case (switch case). Even if I drive backward and forward again it doesn't change the speed. --> So I have to change to another mode (auto or off) and then change back to manual mode for changing the speed.

Now I'm wondering why it works in the auto mode (green color) but not in the manual mode (red color).
Here's my code:

// Right Forward: 9
// Right Backward: 10
// Left Forward: 6
// Left Backward : 5

// Whisker Right: 3
// Whisker Left: 2

// IR Receiver: 11

// dir 1: Forward
// dir 2: Backward
// dir 3: Left
// dir 4: Right

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

int RF = 9;
int RB = 10;
int LF = 6;
int LB = 5;

int WR = 3;
int WL = 2;

int spd = 50;
int dir = 0;

int mode = 0;

void setup()
{
  pinMode (3, INPUT);
  pinMode (2, INPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop()
{
  if (irrecv.decode(&results)) {                      // Prints in the received IR-Codes
    Serial.println(results.value, HEX);
    irrecv.resume();
  }
  delay(100);

  switch (results.value)                              // Switch case to define which mode to run: off, auto or manual
  {
    case 0x800F040C:                                 // Off mode
      mode = 0;
      break;

    case 0x800F845B:                                // Manual mode
      mode = 1;
      break;

    case 0x800F045C:                               // Auto mode
      dir = 0;
      mode = 2;
      break;
  }

  switch (results.value)                          // Switch case to change the variable (spd) for the speed
  {
    case 0x800F0401:
      spd = 50;                                  // PWM 50: Low speed
      break;

    case 0x800F8402:              
      spd = 150;                                // PWM 150: Medium speed
      break;

    case 0x800F8403:
      spd = 255;                                // PWM 255: Max speed
      break;
  }


  switch (mode)                                 // switch case to switch the mode
  {
    case 0:                                     // mode off: wheels dont' move

      dir = 0;

      analogWrite (RF, 0);
      analogWrite (RB, 0);
      analogWrite (LF, 0);
      analogWrite (LB, 0);
      break;





    case 1:                                                                   // mode auto

      if ((digitalRead (WR) == HIGH) && (digitalRead (WL) == HIGH))          // checking whiskers to turn if the robot drives towards a wall
      {
        dir = 1;                                                              // no whisker activated: drive straight on
        delay (5);
      }
      if ((digitalRead (WR) == LOW) && (digitalRead (WL) == LOW))           // both whiskers activated: turn approx. 180 degrees
      {
        dir = 2;
        delay (5);
      }
      if ((digitalRead (WR) == LOW) && (digitalRead (WL) == HIGH))          // whisker right activated: turn left
      {
        dir = 3;
        delay (5);
      }
      if ((digitalRead (WR) == HIGH) && (digitalRead (WL) == LOW))          // whisker left activated: turn right
      {
        dir = 4;
        delay (5);
      }


      switch (dir)                                                          // switch case to change direction due to the state of the whiskers
      {
        case 0:                                                           // stopp
          analogWrite (RF, 0);
          analogWrite (RB, 0);
          analogWrite (LF, 0);
          analogWrite (LB, 0);
          break;

        case 1:                                                           // straight on
          analogWrite (RF, spd);
          analogWrite (RB, 0);
          analogWrite (LF, spd);
          analogWrite (LB, 0);
          break;

        case 2:                                                          // backward
          analogWrite (RF, 0);
          analogWrite (RB, spd);
          analogWrite (LF, 0);
          analogWrite (LB, spd);
          delay (1000);
          analogWrite (RF, 0);
          analogWrite (RB, spd);
          analogWrite (LF, spd);
          analogWrite (LB, 0);
          delay (300);
          break;

        case 3:                                                       // turn left
          analogWrite (RF, spd);
          analogWrite (RB, 0);
          analogWrite (LF, 0);
          analogWrite (LB, spd);
          delay (200);
          break;

        case 4:                                                   // turn right
          analogWrite (RF, 0);
          analogWrite (RB, spd);
          analogWrite (LF, spd);
          analogWrite (LB, 0);
          delay (200);
          break;
      }
      break;





    case 2:                                                           // mode manual: here's the problem with the variable "spd" which doesn't change while driving

      dir = 0;

      switch (results.value)                                         // switch case for changing the direction due to the IR-Signal received from the remote
      {
        case 0x800F841E:                                            // forward
          analogWrite (RF, spd);
          analogWrite (RB, 0);
          analogWrite (LF, spd);
          analogWrite (LB, 0);
          break;

        case 0x800F041F:                                          // backward
          analogWrite (RF, 0);
          analogWrite (RB, spd);
          analogWrite (LF, 0);
          analogWrite (LB, spd);
          break;

        case 0x800F0420:                                          // turn left
          analogWrite (RF, spd);
          analogWrite (RB, 0);
          analogWrite (LF, 0);
          analogWrite (LB, spd);
          break;

        case 0x800F0421:                                        // turn right
          analogWrite (RF, 0);
          analogWrite (RB, spd);
          analogWrite (LF, spd);
          analogWrite (LB, 0);
          break;
      }
      break;
  }
}

Thank you in advance!

First, it would be a lot easier to read your code if you'd make some useful comments. For example: how about something like:

#define GOFORWARD   0x800F040C

// more code...

  switch (results.value)
  {
    case GOFORWARD:             // This causes it to...whatever it does...

Next, what's the purpose of the bracketed HTML expression:

    switch (dir)
    {
      [color=limegreen][color=green][/color]case 0:
          // more code...
      [/color]

Does that compile?

Before posting your code next time, use Ctrl-T in the IDE to reformat your code to a standard style. It will make it easier for us to read.

I tried to do so. Hope it's better to read now

The HTML expressions (didn't know what this is before) were created when I tried to color a part of the text of my code. But I guess this just works outside the "code box". I wanted to mark the excerpts containing the "problem".

stefan_bollinger8226:
I tried to do so. Hope it's better to read now

As a general rule, it's not a good idea to go back to the original post and edit the code. Instead, post the new version of the code. The reason is: 1) it shows the evolution of the code, 2) it gives context to the posts readers make between the two versions of the code. The comments help, but I'd still rather see #define's, const, or enum for the hex constants. It makes reading the code more "in-line".

Ok, I'm sorry.
This will take some time since I don't know what you're talking about (#define, enum etc.). I will google it and try to adjust the code accordingly.

No apology is necessary. I think you'll find readers here are very helpful as long as they see the poster trying to make progress on their own.

just another thought...

Variable names are free. I'm sure you know what RB, WF and those others are, (and we can figure it out), but using longer names doesn't make the hex any larger, while making it a lot easier to read,

e.g.
RW could be RIGHT_WHISKER
RB might become RIGHT_BACK or RIGHT_REAR

so commands become..

analogWrite (RIGHT_REAR, speed);

if ((digitalRead(RIGHT_WHISKER==LOW) && (digitalRead(LEFT_WHISKER==LOW)) {

Oops! Try this...

analogWrite (RIGHT_REAR, speed);

if (digitalRead(RIGHT_WHISKER)==LOW && digitalRead(LEFT_WHISKER)==LOW) {

And then it would be much more readable to put this into a function. The high level code that's making decisions on which direction to travel should not concern itself with the details of how the sensors work.

boolean whiskerIsTouching(int whiskerPin) {
  return digitalRead(whiskerPin) == LOW;
}

...

if (whiskerIsTouching(RIGHT_WHISKER) && whiskerIsTouching(LEFT_WHISKER)) {

It might look silly writing a 3-line function for something that didn't even take up 1 line to begin with, but you will be amazed how it helps to make the decision-making code understandable.

Since it's my first time making an own program for a micro controller, my program is really messy. So your tips are really helpful, thank you :slight_smile: