Problem with looping inside a switch case

Hello, this is my first ever post here. So i have made a small autonomous car and what i'm trying to do now is to control it by switch case. The problem is when i use switch case 'a', the code runs once and stops. I need the code to keep looping until for example i choose switch case 's' to stop the car. I have tried everything and searched everywhere but couldn't find a solution. Can anybody please help me solve this problem ?

void loop() {
  int y;
  int n = map(y, -28, 152, 0, 180);

  if (Serial.available() > 0) {
    int inByte = Serial.read();
  

  switch (inByte) {
    case 'f':
      goForward();
      Serial.println("going forward");
      break;

    case 'b':
      goBackward();
      Serial.println("going in reverse");
      break;

    case 'l':
      y = -28;
      servo.write(n);
      Serial.println("Wheels turn 90 degrees to the left");
      break;

    case 'r':
      y = 152;
      servo.write(n);
      Serial.println("Wheels turn 90 degrees to the right");
      break;

    case 's':
      Stop();
      break;

    case '1':
      sensor();
      break;

    case 'a':

      Serial.println("Starting Autonomous Driving");


      sensor();
      if (distance > 20) {
        servo.write(62);
        goForward();
      }

      else if (distance < 20) {
        Stop();

        if (y < 62) {
          Serial.print("angle 2 is ");
          Serial.print(y);
          Serial.print(" degrees, ");
          servo.write(y);
        }

      }

  }
}

I have tried everything

Obviously not. If you put EVERY{ on a line BY ITSELF, and put EVERY } on a line BY ITSELF, and used Tools + Auto Format, it would be perfectly obvious what the problem is.

Using the value that you get from the serial port should be independent from getting a value from the serial port.

I need the code to keep looping until for example i choose switch case 's' to stop the car.

No you don't - NEVER DO THIS KIND OF THING!

Mark

PaulS:
Obviously not. If you put EVERY{ on a line BY ITSELF, and put EVERY } on a line BY ITSELF, and used Tools + Auto Format, it would be perfectly obvious what the problem is.

Using the value that you get from the serial port should be independent from getting a value from the serial port.

can you please explain ? how will this solve anything

how will this solve anything

Look at this pseudo code:

if there is serial data
{
   read the serial data
   use the serial data
}

Compare that to:

if there is serial data
{
   read the serial data
}
use the serial data

It should be perfectly obvious that separating the using of the data from the reading of the data is necessary.

PaulS:

if there is serial data

{
  read the serial data
}
use the serial data



It should be perfectly obvious that separating the using of the data from the reading of the data is necessary.

Thanks for clarifying. I already tried that before but the serial monitor became unresponsive to my keyboard inputs :confused:

jradisam:
Thanks for clarifying. I already tried that before but the serial monitor became unresponsive to my keyboard inputs :confused:

That's because you had blocking code in that "solution"

AWOL:
That's because you had blocking code in that "solution"

Excuse my ignorance. This is my first ever project using arduino and my first ever experience with a programming language. Please, i would appreciate some detailed explanation about the blocking code and how to fix it so that i could learn something and fix my project.

I already tried that before but the serial monitor became unresponsive to my keyboard inputs :confused:

Post that code.

If your program looks like this:

void loop()
{
   static char inData = ' ';
   if(Serial.available() > 0)
   {
      inData = Serial.read();
   }

   switch(inData)
   {
      case 'a':
        doDomethingThatTakesTenMinutes();
        break;
      case 'b':
        doSomethingThatTakesTwentyMinutes();
        break;
      default:
        doSomethingThatTakesFiveMinutes();
   }
}

then it should be pretty obvious that it will take at least 5 minutes to respond to the next serial value.

If your code looks like:

void loop()
{
   static char inData = ' ';
   if(Serial.available() > 0)
   {
      inData = Serial.read();
   }

   switch(inData)
   {
      case 'a':
        doDomethingThatTakesTenMicroseconds();
        break;
      case 'b':
        doSomethingThatTakesTwentyMicroseconds();
        break;
      default:
        doSomethingThatTakesFiveMicroseconds();
   }
}

then it should be pretty obvious that it will take at least 5 microseconds to respond to the next serial value.

However long it takes the shortest doSomething() function to do something is how quickly you can respond to serial input.

So, none of your doSomething() functions should take more than a few milliseconds, of you want a responsive system. That means no for loops, no delay()s, and especially no for loops with embedded delay()s.

The loop() function loops. Let it handle ALL the looping.

PaulS:
Post that code.

However long it takes the shortest doSomething() function to do something is how quickly you can respond to serial input.

So, none of your doSomething() functions should take more than a few milliseconds, of you want a responsive system. That means no for loops, no delay()s, and especially no for loops with embedded delay()s.

The loop() function loops. Let it handle ALL the looping.

I completely understand what you're saying. However i can't get this ting to work. It's been driving me crazy for a week. I tried this shorter just to test it and still no response

#include <Servo.h>
Servo servo;

void setup()
{
  Serial.begin(9600);
  servo.attach(52);
}


void loop()
{

  static char inByte = ' ';

  if (Serial.available() > 0)
  {
    int inByte = Serial.read();
  }

  switch (inByte) 
  {
    case 'a':
      servo.write(90);
      break;
    case 'b':
      servo.write(0);
      break;
    case 'c':
      servo.write(180);
      break;
    default:
      servo.write(120);
  }
}

You've got two variables with the same name, one with very limited scope.

Don't do that.

  static char inByte = ' ';

  if (Serial.available() > 0)
  {
    int inByte = Serial.read();
  }

It is dumb to use a type in the name of a variable when the type in the name is not the type of the variable.

It is equally dumb to have two variables with the same name but different types.

It is just as dumb to have a local variable that goes out of scope before you can do anything with it.

static char inByte = ' ';

  if (Serial.available() > 0)
  {
    int inByte = Serial.read();
  }

When you declare inByte as an integer variable within the if statement, you are creating a 2nd variable named inByte, separate from the original inByte declared as a char. This 2nd variable is only usable within the { } of the if statement, and ceases to exist once you leave that. The original char typed inByte is a completely separate variable and will not be altered.

You will often see someone asking about an error where a variable is "out of scope", the scope of a variable is the section of the program within which a variable is defined, usually in a section bounded by a set of brackets { } . If you had only declared inByte once, where you did the Serial.read within the if statement, all of your references to inByte outside of the if statement would have been out of scope, because inByte would no longer exist once you leave the section it was defined in.

As for the other comments you have gotten, if I were going to call the variable inByte, I would have defined it as a byte. For a char, inChar would be a more suitable name. In the end it doesn't make much difference to the code, because the compiler is doing the needed type conversions in the Serial.read and switch statement, but you will see a difference in a Serial.print, where a byte will print as a number, and a char as an ascii character, so having the name implying a different type than it actually is can lead to confusion.