Search code examples
serializationarduinoswitch-statementled

Faulty Arduino Logic?


I am making a simple Led program that will be turned into a library for my project. I have created four methods that will allow you to A) Setup as many Led pins as you want and make them as Outputs. B) Flash the Led lights at a customized time. C) Turn On Leds. D) Turn Off Leds. Everything is working if i just run the methods in the void loop(). For example:

Void loop(){

flashLed(pinNum, 2000);
turnOf(pinNum);
turnOn(pinNum);
}

If i run the above code it works fine, however it keeps looping as its obviously in a loop. So i decided to start the serial com by using Serial.begin(9600) in the setup(), and then testing for the serial com and used a switch case statement in order to appropriately implement these methods. What am i doing wrong here? i get no errors at all. When i type into the serial monitor nothing happens, i believe my logic is fine but that is why i am here. When anything is typed into the serial monitor, the code runs the default in the switch case statement and that is all. I have tried using while, if to no avail. Also tested the inverse of serial which would be !serial.available() Here is my code:

//Define the pin numbers
byte pinNum[] = {4, 3, 2};


void setup() {
  //Setup the ledPins
  ledSetup(pinNum);
  Serial.begin(9600);  
}

void loop() {

  while(Serial.available() > 0){
    //Read the incoming byte
    byte ledStatus = Serial.read();
    switch (ledStatus){
      case 0: 
      turnOff(pinNum);
      Serial.println("The Leds Have Been Turned Off");
      break;
      case 1:
      turnOn(pinNum);
      Serial.println("The Leds Have Been Turned On");
      break;
      case 2:
      flashLed(pinNum, 1000); //This will make the Led blink for half a second
      Serial.println("The Leds Will Begin Flashing");
      break;
      default:
      flashLed(pinNum, 1000); //This will make the Led blink for half a second
      break;
    }
  }
}

//Method to declare the pins as output
void ledSetup(byte ledPins[]){
  for (int i = 0; i <= sizeof(ledPins); i++){
    pinMode(ledPins[i], OUTPUT);
  }
}

//Method to blink the Led light/lights
void flashLed(byte ledBlink[], int duration){
  //Time is divided by two because it takes 2 seconds 
  //to run the sketch 
for (int i = 0; i <= sizeof(ledBlink); i++){
  digitalWrite(ledBlink[i], HIGH);
  delay(duration/2);
  digitalWrite(ledBlink[i], LOW);
  delay(duration/2);
}
}

//Method to turn Leds off
void turnOff(byte ledOff[]){
  for(int i = 0; i <= sizeof(ledOff); i++){
    digitalWrite(ledOff[i], LOW);
}
}

//Method to turn Leds On
void turnOn(byte turnOn[]){
for (int i = 0; i <= sizeof(turnOn); i ++){
  digitalWrite(turnOn[i], HIGH);

}
}

Solution

  • The serial monitor sends symbols encoded in the ASCII format.

    e.g. when you enter 0, Serial.read() returns 48, which is the ASCII code for digit 0. Since the value 48 is not listed in the following cases, the default branch is taken:

          case 0: ...
          case 1: ...
          case 2: ...
          default: ...
    

    There are many solutions to your problem.

    1. change case conditions to match what you are sending:

          case '0': ...
          case '1': ...
          case '2': ...
    

    2. replace Serial.read() with Serial.parseInt():

        int ledStatus = Serial.parseInt();
    

    This will actually work with more general inputs, e.g. 123, but it will return 0 if there is anything different from a digit in the input buffer.

    3. wrap Serial.read() within atoi():

        byte ledStatus = atoi(Serial.read());
    

    This is somewhat more limited than both of previous options, since now you can only have 10 cases in your switch.