Switch case default condition running when it should not and multiple times.

Hello,

I have 2 DC motors connected to a motor driver and an MPU-6050 sensor connected to an Arduino UNO R3. The purpose of my sketch is to enable control of each or both motors and reading the sensor data via the Serial Monitor using a command line interface. I am using Switch/Case statements but the default case is running even when it should not. And on top of that, it runs more than once when a value is entered which does not match any of the case values.

Here is my complete code:

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include <I2Cdev.h>
#include <MPU6050.h>

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include <Wire.h>
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high

int16_t ax, ay, az;
int16_t gx, gy, gz;

char val;
int speed = 60; // set the starting speed

// Motor Connections A 
int enA = 10;
int in1 = 8;
int in2 = 12;

// Motor Connections B 
int enB = 9;
int in3 = 7;
int in4 = 6;

void setup () {

  // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(9600);

    // initialize device
    Serial.println("Initialising MPU-6050...");
    accelgyro.initialize();

    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful." : "MPU6050 connection failed.");

  while (!Serial) {
    ; // wait for serial port to connect.
  }
  Serial.println("Serial port connected.");
  
  // list of commands
  Serial.println("----------------------------------");
  Serial.println("The following commands are available:");
  Serial.println("1 - Forward Motor A only."); 
  Serial.println("2 - Forward both motors A and B.");
  Serial.println("3 - Forward motor B only.");
  Serial.println("4 - Stop motor A only.");
  Serial.println("5 - Stop both motors A and B.");
  Serial.println("A - Set PWM to 100.");
  Serial.println("E - Set PWM to 255.");
  Serial.println("G - Read Gyroscope values.");
  Serial.println("L - Read Accelerometer values.");
  Serial.println("----------------------------------");
  
  pinMode (enA, OUTPUT);
  pinMode (enB, OUTPUT);
  pinMode (in1, OUTPUT);
  pinMode (in2, OUTPUT);
  pinMode (in3, OUTPUT);
  pinMode (in4, OUTPUT);
  analogWrite (enA, speed);
  analogWrite (enB, speed);
}

void loop () { 
  
  // read raw accel/gyro measurements from device
  accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
 if (Serial.available()) {
  
  val = Serial.read();
   
    switch(val)
    {
      case '1': 
        Serial.println("Input: '1'. Forward motor A.");
        digitalWrite (in1, HIGH);
        digitalWrite (in2, LOW);
        break;       
      
      case '2': 
        Serial.println("Input: '2'. Forward motor A and B.");
        digitalWrite (in1, HIGH);
        digitalWrite (in2, LOW);
        digitalWrite (in3, HIGH);
        digitalWrite (in4, LOW);
        break;
      
      case '5': 
        Serial.println("Input: '5'. Stop motors A and B.");
        digitalWrite (in1, LOW);
        digitalWrite (in2, LOW);
        digitalWrite (in3, LOW);
        digitalWrite (in4, LOW);
        break;
      
      case 'A': 
        Serial.println("Input: 'A'. Set PWM to 100.");
        speed = 100;
        break;
      
      case 'X': 
        Serial.println("Input: 'X'. Turn motor A only.");
        analogWrite (enA, 60);
        analogWrite (enB, 60);
        digitalWrite (in1, HIGH);
        digitalWrite (in2, LOW);
        digitalWrite (in3, LOW);
        digitalWrite (in4, LOW); 
        delay (800);
        break;
      
      case 'G':
        Serial.print("Input: 'G'. Gyro-X: ");
        Serial.print(gx);
        Serial.print(", ");
        Serial.print("Gyro-Y: ");
        Serial.print(gy);
        Serial.print(", ");
        Serial.print("Gyro-Z: ");
        Serial.print(gz);
        Serial.println(".");
        break;
      
      case 'L': 
        Serial.print("Input: 'L'. Acc-X: ");
        Serial.print(ax);
        Serial.print(", ");
        Serial.print("Acc-Y: ");
        Serial.print(ay);
        Serial.print(", ");
        Serial.print("Acc-Z: ");
        Serial.print(az);
        Serial.println(".");
        break;
      
      default:
        Serial.println("Invalid command.");
        break;
    }
    
  analogWrite (enA, speed);
  analogWrite (enB, speed);

  }
}

Here is the problem when i enter a valid case value in the Serial Monitor. The correct motor is actually activated though.

Input: '1'. Forward motor A.
Invalid command.
Invalid command.

Here is the output when i enter an invalid case value.

Invalid command.
Invalid command.
Invalid command.

The default case is executed twice when a valid case value is entered and thrice when an invalid case value is entered in the Serial Monitor. These should not happen but i can’t figure out why. Also, is it necessary to have a break statement at the end of the default case statements?

line ending characters. \r \n
what is your line ending setting in Serial Monitor?

Juraj:
line ending characters. \r \n
what is your line ending setting in Serial Monitor?

Arduino IDE 1.8.9. Both NL & CR. 9600 baud.

So when you enter a command, what is sent for the board to read?

When i enter '1' (without quotes) and press the Send button, this is what is shown in the Serial Monitor:

Input: '1'. Forward motor A.
Invalid command.
Invalid command.

Everything below the first line, "Input: '1'. Forward motor A." should not be there.

Juraj:
line ending characters. \r \n
what is your line ending setting in Serial Monitor?

what did I write?

When you send '1' from the serial monitor with the CR and LF enabled in the line endings of serial monitor what is actually sent is 1,CR,LF. '1' is valid, CR and LF are not valid. Turn off line endings in serial monitor or write code that will ignore the line endings in your input.

Juraj:
what did I write?

Oh, i missed the hint. :stuck_out_tongue:

groundFungus:
When you send '1' from the serial monitor with the CR and LF enabled in the line endings of serial monitor what is actually sent is 1,CR,LF. '1' is valid, CR and LF are not valid. Turn off line endings in serial monitor or write code that will ignore the line endings in your input.

I set it to "No line ending" and it's fixed! Thanks. :slight_smile: