Phantasma Phantasma - 1 month ago 6
C Question

Why interrupt is stopping program instead of jumping back?

i'm working on arduino and i have made two modes in loop(),mode1 in while loop and mode second in while loop they have conditions to be met, i switch between them using button that interrupts routine that is currently executed,changes flags to force program to change to second mode and for some reason instead of breaking out of current while loop (since conditoins are not met anymore )to change to the other it just doesnt respond

or changes from automatic->stops responding

#define ledRed 10
#define buzzerSwitch 9
#define modeSwitch 2
#define buzzer 8

#define ledRed 10
#define buzzerSwitch 9
#define modeSwitch 2
#define buzzer 8
boolean manual;
boolean automatic;
volatile byte buttonState;
int modeSwitchValue;

void setup() {
pinMode(ledGreen, OUTPUT);
digitalWrite(ledGreen, LOW);
pinMode(buzzerSwitch, INPUT_PULLUP);
pinMode(modeSwitch, INPUT_PULLUP);
attachInterrupt(0, changeMode, RISING);
pinMode(buzzer, OUTPUT);
modeSwitchValue = 5;
manual = false;
automatic = false;
Serial.begin(9600);
Serial.println(invitation);
Serial.println("Please choose a mode: Write 'automatic' for an automatic mode or 'manual' or manual code. ");
}
void loop() {

if (Serial.available() > 0) {
receivedData = Serial.readStringUntil('\n');
if (receivedData == "manual" ) {

manual = true;
automatic = false;
modeSwitchValue = 0;
buttonState = HIGH;

}
if ( receivedData == "automatic") {

automatic = true;
manual = false;
modeSwitchValue = 1;
buttonState = LOW;

}

while ((manual == true) && (modeSwitchValue == 0)) {
String s = "Manual mode:";
while (checkPrint(s) == true) {
Serial.println(s);
}
automatic = false;
if (digitalRead(buzzerSwitch) == LOW) {
digitalWrite(ledGreen, HIGH);
digitalWrite(buzzer, HIGH);

} else {

digitalWrite(ledGreen, LOW);
digitalWrite(buzzer, LOW);
}

}

while ((automatic == true) && (modeSwitchValue == 1)) {
String s = "Automatic mode: Please write the message that you would like to display";
while (checkPrint(s) == true) {
Serial.println(s);
}

manual = false;

String message = Serial.readStringUntil('\n');
while (checkPrint(message) == true) {
Serial.print(message);
}
message.toLowerCase();
}




}
}


void changeMode() {
if ( buttonState == HIGH) {
modeSwitchValue = 1;
automatic = true;
manual = false;
buttonState = LOW;

}
if (buttonState == LOW) {

modeSwitchValue = 0;
manual = true;
automatic = false;
buttonState = HIGH;

}
}


I deleted checkPrint() function cause it only ensures msgs are printed once so its not essential to show here i think

I thought that while executing automatic code, i press button and it interrupts,changing mode variable then goes back to same place in program where the interrupt occured. then software notices that while loop condition of automatic mode is not fulfilled anymore so it breaks out to loop() and finds while loop of manual mode to be executed since the conditions are met. am i thinking wrong? or have i missed something?

Answer

You are mixing up assignment "=" and comparison "==" in your changeMode() function. Here is a corrected version of the function.

void changeMode() {
  if ( buttonState == HIGH) {
    modeSwitchValue = 1;
    automatic = true;
    manual = false;
    buttonState = LOW;
  }

  if (buttonState == LOW) {
    modeSwitchValue = 0;
    manual = true;
    automatic = false;
    buttonState = HIGH;
  } 
}

You should also realize that mechanical buttons can have contact bounce. Since you are using an interrupt to detect changes in the button state you might get erratic behavior. Usually, it is better to poll the button state and apply a de-bounce time delay on the order of 20ms.