Currently, I have two loops in my Arduino code.
Certain cases take me from loop 1 to loop 2
I also have an ISR
When my ISR condition is met the code is executed and part of the ISR code is supposed to go to loop 1. Which it does but...
Then I close the ISR accordingly, but the service routine goes back to loop 2.
Any ideas why?
I've been surfing the web for the past couple hours and haven't caught a wave..
Thanks all.
//Physical variables
int eStop = 3; // the number of the input pin
int eStopLED = 9; // the number of the output pin
int dispenseButton = 6; // the number of the input pin
int dispenseLED = 8; // the number of the output pin
// have 789 for colors and 3456 for input only 3 ND 6 NEEDS TO BE USED
int eStopZone = HIGH; // the current eStopZone of the output pin
int eStopScan; // the current eStopScan from the input pin
int eStopPrior = LOW; // the eStopPrior eStopScan from the input pin
int dispenseZone = HIGH; // the current eStopZone of the output pin
int dispenseScan; // the current eStopScan from the input pin
int dispensePrior = LOW; // the eStopPrior eStopScan from the input pin
//Other Variables
volatile int vControl = 0;
int eVar;
int i; //Normal counting integer
// will quickly become a bigger number than can be stored in an int.
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
void control(void);
void emergency(void);
//another coid for char ring
void setup()
{
pinMode(eStop, INPUT);
pinMode(eStopLED, OUTPUT);
pinMode(dispenseButton, INPUT);
pinMode(dispenseLED, OUTPUT);
eVar = 0;
Serial.begin(9600); //Start Serial
attachInterrupt(digitalPinToInterrupt(eStop), emergency, CHANGE);
}
void loop()
{
eStopScan = digitalRead(eStop);
dispenseScan = digitalRead(dispenseButton);
//Serial.println(eStopScan);
/*if (eStopScan == HIGH && eStopPrior == LOW && millis() - time > debounce) { //eStop control conditions
switch (eVar) {
case 0:
vControl = 0;
control();
break;
case 1:
vControl = 1;
control();
break;
}
time = millis();
}
*/
if (dispenseScan == HIGH && dispensePrior == LOW && millis() - time > debounce) { //dispense control conditions
Serial.println("in this loop");
switch (eVar) {
case 0:
vControl = 2;
control();
break;
case 1:
vControl = 3;
control();
break;
}
time = millis();
}
eStopPrior = eStopScan;
dispensePrior = dispenseScan;
}
void control () {
switch (vControl) {
case 0: //estop case put in another variable for showing last estop state
eStopZone = HIGH;
dispenseZone = LOW;
digitalWrite(dispenseLED, dispenseZone);
digitalWrite(eStopLED, eStopZone);
eStopScan = LOW;
dispenseScan = LOW;
Serial.println("Case 0");
//eVar = 1;
break;
case 1:
for (int i = 0; i <= 2; i++) {
eStopZone = LOW;
digitalWrite(eStopLED, eStopZone);
delay(345);
eStopZone = HIGH;
digitalWrite(eStopLED, eStopZone);
delay(345);
Serial.println("Case 1");
//Serial.println(i);
}
break;
case 2:
dispenseZone = HIGH;
eStopZone = HIGH;
digitalWrite(eStopLED, eStopZone);
digitalWrite(dispenseLED, dispenseZone);
Serial.println("here 1");
delay(1000);
Serial.println("here?");
eStopZone = LOW;
digitalWrite(eStopLED, eStopZone);
Serial.println("Case 2");
break;
case 3:
dispenseZone = HIGH;
eStopZone = LOW;
digitalWrite(eStopLED, eStopZone);
digitalWrite(dispenseLED, dispenseZone);
eVar = 0;
Serial.println("Case 3");
// make led go green
break;
}
time = millis();
loop();
}
void emergency () {
Serial.println("interrupt");
vControl = 0;
control();
}
Com window from debugging
in this loop
here 1
here?
Case 2
in this loop
here 1
here?
Case 2
in this loop
here 1
interrupt
interrupt
interrupt
here?
Case 2
-
4Please show us the sketch you're using.VE7JRO– VE7JRO2020年01月09日 03:06:24 +00:00Commented Jan 9, 2020 at 3:06
-
please explain what you understand about an interrupt and about ISRjsotola– jsotola2020年01月09日 03:42:31 +00:00Commented Jan 9, 2020 at 3:42
-
It is difficult to understand, what you actually mean. Please include your code and a detailed description about what you expected the code to do and what it actually does.chrisl– chrisl2020年01月09日 07:57:50 +00:00Commented Jan 9, 2020 at 7:57
-
My understanding is that the ISR will get completed and then go back to the state where it left off. However, I thought since im saying to go back into the loop where my variable is now changed it would nullify the previous case..96jeremy– 96jeremy2020年01月09日 11:37:55 +00:00Commented Jan 9, 2020 at 11:37
2 Answers 2
Your explanation of what you expect to happen is not very clear but I'll take a stab at your question.
First thing - Interrupt Service Routines (ISR) need to be short (execution time, not necessarily code length). Do the minimum necessary to save whatever status or data caused the interrupt and exit. Let the background (your main sketch) handle any further processing resulting from the interrupt.
That means the ISR has to leave some indication - a boolean flag, f/ex - that it did something, and your background has to check that frequently, act on it when it changes, and reset it for the next interrupt.
It looks like your ISR is calling into your background code, which effectively becomes part of the ISR, runs at interrupt level, prevents further interrupts while it is doing so, and (possibly) returns to your background code at a place or in a state that is no longer relevant by then.
Think about organizing your code so that the background does whatever ongoing, routine tasks you need it to be doing, but checking frequently for whether an interrupt has occurred yet. When one has, do whatever needs to done to handle it, reset the "interrupt has occurred" flag, and return to your background task(s).
I cannot see what actually goes wrong, but you're calling way too much stuff in your ISR. You're changing non-volatile variables with the control()
call in your ISR, leading to undefined behaviour: You don't know when the ISR is being called, especially not whether it is called before or after the non-volatile variables have been transferred from memory to the registers or back in the routine started from loop()
. Also: Never output anything from an ISR nor from code you call from that ISR. Serial communication is slooow (compared to what the processor could be doing in that time frame).
I'd say: The only thing your ISR should do is to add 1 to a volatile variable, then end. In your loop()
, check whether that volatile variable is greater than 0, then reset the volatile variable back to 0 and run what you've got in your current ISR. To react to the interrupt in a timely manner, this also means that you should not use delay()
anywhere in your code. This would put your code back into defined behaviour, at least.