digital read/write not working within switch/case serial loop

Hi,
I am trying to get a digitalRead/Write statement to switch the mode within my Switch/Case loop.

I want to be able to switch the mode to (mode = 5) when the button attached to 'StopPin' is pressed.
Preferably only whilst (mode = 6) is running.

I know the wiring to the button/Test LED is right as I have tested it with the bit of code greyed out -

// buttonState = digitalRead(StopPin);
// if (buttonState == HIGH) {digitalWrite(TestPin, HIGH);}

so I know the switch works fine. My problem is as soon as I move this to within the IF variables in the code
it stops working. I have tried to get it to light up the Test LED and switch the mode with no luck.

I am assuming it is something to do with the fact it is working alongside the serial input (which all works great)
but I cannot see why. I have tried moving the read/write to different parts of the loop but cant seem to get it
to do anything. Can anyone see why?

Thanks in advance

const int ShakePin = 4;
const int FeedPin = 5;
const int StopPin = 8;
const int TestPin = 13;
byte mode;
int buttonState = 0;


void setup()
{
  pinMode(ShakePin, OUTPUT);  //Shaker Relay Pin 
  digitalWrite(ShakePin, LOW);  // 
 
  pinMode(FeedPin, OUTPUT);  // Feeder Relay Pin
  digitalWrite(FeedPin, LOW);  // 
 
  pinMode(StopPin, INPUT);  // Cutout Switch
  digitalWrite(StopPin, LOW);  // 
  
  pinMode(TestPin, OUTPUT);  // pin 12 shakermotor as OUTPUT
  digitalWrite(TestPin, LOW);  // pin 12 shakermotor as OUTPUT
  
  Serial.begin(115200);       // start serial communication at 115200bps

}
 
void loop() {
//    buttonState = digitalRead(StopPin);    
//    if (buttonState == HIGH) {digitalWrite(TestPin, HIGH);} 
  
  if( Serial.available() >= 2){
    
    buttonState = digitalRead(StopPin); //Is the stop pin high
   
    int key = Serial.read();
    int val = Serial.read();
    
    
    if ( mode == 0 && key == 4 && val == 1){ mode = 1;}
    if ( mode == 0 && key == 5 && val == 1){ mode = 2;}
    if ( mode == 0 && key == 13 && val == 1){ mode = 3;}
    if (buttonState == HIGH) {mode = 5;}   // If Pin is high light the stopPin
 
 //   if ( mode == 6 && buttonState == HIGH){ mode = 5;}
 //   if (buttonState == HIGH) {digitalWrite(TestPin, HIGH);}   // If Pin is high light the TestLED
    
    switch (mode){
    
case 0:  // do nothing and wait
break;

case 1:  // Shake
    digitalWrite (ShakePin, HIGH);
    delay (5000);
    digitalWrite (ShakePin, LOW); 
    mode = 5; 
break;


    
case 2:  // Feed
    digitalWrite (FeedPin, HIGH);
    delay (3000);
    digitalWrite (FeedPin, LOW);
    delay (1000);
    mode = 6;
break;

case 3:   //LED Test
     
     digitalWrite (TestPin,HIGH);
     delay (3000);
     digitalWrite (TestPin,LOW);
     mode = 5;
break;

case 5:  // Reset all variables and go to wait mode
     key = 0;
     val = 0;
     mode = 0;
break;

case 6:  // Run Motor until Interupt from StopPin
     digitalWrite (FeedPin, HIGH);
break;

     
  }
  }
}
    if ( mode == 0 && key == 4 && val == 1){ mode = 1;}
    if ( mode == 0 && key == 5 && val == 1){ mode = 2;}
    if ( mode == 0 && key == 13 && val == 1){ mode = 3;}

Nested ifs would make this clearer.

    if ( mode == 0 && val == 1)
    {
       if (key == 4)
          { mode = 1;}
       if (key == 5)
          { mode = 2;}
       if (key == 13)
          { mode = 3;}
    }
My problem is as soon as I move this to within the IF variables in the code
it stops working.

You can't move stuff into the IF variables. Into the if statement block, yes. But, you need to show WHERE you moved that to.

I am assuming it is something to do with the fact it is working alongside the serial input (which all works great)
but I cannot see why.

I can't see any basis for that assumption.

Put each { and } on a new line, and use Tools + Auto Format to properly indent your code. That may make your problem apparent. If not, post the code you are having problems with, without commented out code.

ok, reformatted - anyway, here is the problem -

when the (buttonState == HIGH) it does not switch the case to (mode = 7), turning the pin to low and returning the mode to 0.

I have an LED attached to the FeedPin at the moment. When I trigger [key 5] the LED lights up for three seconds, off for a second then
back on, which indicates that it is succesfully running mode-2 then switching to mode-6 with no problems, however the LED does not turn off when I press the switch attached to the StopPin, which indicates to me that it is not switching to Mode-7.

(changed slightly from original posted code)

void loop() {


  if( Serial.available() >= 2){

    buttonState = digitalRead(StopPin); //Is the stop pin high

    int key = Serial.read();
    int val = Serial.read();


if ( mode == 0 && val == 1)
    {
       if (key == 4)
          { mode = 1;}
       if (key == 5)
          { mode = 2;}
       if (key == 13)
          { mode = 3;}
       if (buttonState == HIGH) 
          { mode = 7;}
    }

    switch (mode){

    case 0:  // do nothing and wait
      break;

    case 1:  // Shake
      digitalWrite (ShakePin, HIGH);
      delay (5000);
      digitalWrite (ShakePin, LOW); 
      mode = 5; 
      break;



    case 2:  // Feed
      digitalWrite (FeedPin, HIGH);
      delay (3000);
      digitalWrite (FeedPin, LOW);
      delay (1000);
      mode = 6;
      break;

    case 3:   //LED Test

      digitalWrite (TestPin,HIGH);
      delay (3000);
      digitalWrite (TestPin,LOW);
      mode = 5;
      break;

    case 5:  // Reset all variables and go to wait mode
      key = 0;
      val = 0;
      mode = 0;
      break;

    case 6:  // Run Motor until Interupt from StopPin
      digitalWrite (FeedPin, HIGH);
      break;
      
    case 7:  // Reset all variables and go to wait mode
      digitalWrite (FeedPin, LOW);
      key = 0;
      val = 0;
      mode = 0;
      break;


    }
  }
}

Are you sending it serial data while StopPin is HIGH? You have a requirement that there be two bytes (0 and 1) of incoming serial data while StopPin is HIGH in order to change modes.

Hi,
no there is only serial data when I press a button on the andorid app that is communicating with the serial port, I see the problem now as it can only read the button state when the serial data is being sent, due to it being within the serials IF statement.

Any idea how I can implement reading the pin state and changing the mode whilst also monitoring the serial input?

Any idea how I can implement reading the pin state and changing the mode whilst also monitoring the serial input?

Do them independently. Read the switch state. Then, read the serial data, if any.

Thanks, Can I change the mode within another IF statement from outside the IF statement? I need to be able to interupt {mode = 6} with
the switch, making the program stop? I thought that is what I had done already, unsuccesfully

Can I change the mode within another IF statement from outside the IF statement?

You keep using the definitive article - the IF statement. There is more than one if statement. You need to clarify what if statement you are referring to.

Most likely, the answer is yes.

I need to be able to interupt {mode = 6} with
the switch, making the program stop?

You don't want to interrupt mode 6. That implies letting it resume after the interruption. You want to terminate mode 6. Anytime you are in mode 6, you can read the switch state, and change to a different mode if the state is to your liking.

Anytime you are in mode 6, you can read the switch state, and change to a different mode if the state is to your liking.

I have tried adding the following to within the (mode = 6) code:

 case 6:  // Run Motor until StopPin pressed
      digitalWrite (FeedPin, HIGH);
      buttonState = digitalRead(StopPin);
      if (buttonState == HIGH) { mode = 7;}
      break;
      
    case 7:  // Reset all variables and go to wait mode
      digitalWrite (TestPin,HIGH);
      digitalWrite (FeedPin, LOW);
      key = 0;
      val = 0;
      mode = 0;
      break;


    }
  }
}

The TestPin does not go HIGH and the FeedPin does not go LOW when the StopPin switch is pressed whilst mode = 6 is running.

I am trying to find out where in my code I need to monitor the StopPin to allow me to interrupt (sorry, change mode) whilst mode
6 is running. It currently does not. Can anyone suggest where I need to monitor the switch to allow the mode to be changed

I have tried adding the following to within the (mode = 6) code:

Which looks correct.

The TestPin does not go HIGH and the FeedPin does not go LOW when the StopPin switch is pressed whilst mode = 6 is running.

You need to add a Serial.print() statement to loop, to print out the value in mode.

You need to add a Serial.print() statement to loop, to print out the value in mode.

Thanks, can you explain to me where in the loop and what this would achieve?

If it is just to monitor the state of the button I can't actually view the serial port output as the app does not support it. Or is this to output the button state to the serial port to allow it to be read by the program?

I know the switch works because If I hold it whilst the key is pressed the mode does change (as indicated by the test LED lighting up after 3 seconds)

Sorry but I am trying to understand why this would work rather than 'it works'

Thanks

The way I understand it my code is operating as the following at the moment:

If Serial bytes received, read bytes and change mode based on the byte value. Only read the button value if serial data is being received.

What I need it to do is:

If serial bytes received, read bytes and change mode based on the byte value. when mode 6 is running, monitor StopPin and if value goes high change mode to 7.

I am having trouble finding exactly where in my code I need to put the monitor to allow me to switch the mode without simultaneously receiving data from the serial port.

Thanks, can you explain to me where in the loop and what this would achieve?

Just before the switch(mode) statement would be good. You'd KNOW what state the code is in, instead of guessing/hoping/wondering.

If it is just to monitor the state of the button I can't actually view the serial port output as the app does not support it.

What app doesn't support "it"?

Or is this to output the button state to the serial port to allow it to be read by the program?

It is to output to the serial port the mode (not the state of a switch). Read by what program? What do you have on the PC end of the serial port?

Sorry, more information. I am using a Bluetooth module attached to the arduino. I am using an android app which when you set up a touchbutton and press it, it sends two bytes of information (key,val) over bluetooth to the serial port. This is all working great and triggers the right pins when the right touch button is pressed.

Because the app does not have a serial monitor I cannot see what is going on, the only way I know is by using LEd's on the pins to monitor the mode changes. Using the PC serial monitor as well as the BT module does not work as I think the BT module is the serial input/output port. (I am a beginner so I am still working all this out)

I know that there is no problem with monitoring the switch input because It does switch the mode if I am already making the StopPin HIGH when the mode starts (if I hold down the StopPin button whilst pressing the button on the app).

I know this is because I have the mode changes within the IF serial.available statement and changes can only be made at the same time as serial information is being recieved. I cannot work out a way to have the StopPin change the mode, within the Switch/case block whilst Mode 6 is already running, without having to recieve serial data at the same time.

Sorry if this is confusing as hell

Ok,
solved this, thanks for your help PaulS but I think part of my problem was explaining my problem. After many an hour head scratching
I have solved it.

My problem was having the switch/case inside the if (serial.available(){ so monitoring of the input could only happen whilst it was receiving serial data.

I moved it outside of the IF statement so that all the above did was write the values to key and val and it worked a charm

void loop() {

if( Serial.available() >= 2){
key = Serial.read();
val = Serial.read();
}

if (key == 4 && val == 1){ mode = 1;}
if (key == 5 && val == 1){ mode = 2;}
if (key == 13 && val == 1){ mode = 3;}

switch (mode){

Thanks again for help