0

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
  • 4
    Please show us the sketch you're using. – VE7JRO Jan 9 at 3:06
  • please explain what you understand about an interrupt and about ISR – jsotola Jan 9 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 Jan 9 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 Jan 9 at 11:37
1

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).

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.