1

I have used attachInterrupt() to reset my program to the beginning. It actually interrupts while running the 3 states as shown below inside of the if statement but when I press the actual button it does not exit, it goes to the function and continuing to the next state. It only works (means exiting/resetting) after all three states have executed completely.

if(buttoncount<2){
  originalstate();
  alertstate();
  evacuationstate();

I would like to make a button to stop the program while running in the middle and start again.

Code:

// Declaring pins

// Input pins
const int sensor1button_pin = 6;
const int sensor2button_pin = 3;
const int sensor3button_pin = 4;
const int sensor4button_pin = 5;
const int sensor5button_pin = 2;
const int sensor6button_pin = 15;
const int sensor7button_pin = 15;

// Output pins
const int led1_pin = 8;
const int led2_pin = 9;
const int led3_pin = 10;
const int led4_pin = 11;
const int buzzerpin = 15;

// Initialy buzzer at false mode
boolean flag1;
boolean flag2;
int flag3 ;


// for leds
int ledState1 = LOW;   // Original
int ledState2 = LOW;   // Alert
int ledState3 = LOW;   // Evacuate
int ledState4 = LOW;   // Isolate

// Buttons
int button1_state = LOW;
int button2_state = LOW;
int button3_state = LOW;
int button4_state = LOW;
int button6_state = LOW;
int button7_state = LOW;
int button5_state = LOW;

// Other variables
int buttoncount = 0;
int reset_switch=0;

void setup() {
  // INPUT pins
  pinMode(sensor1button_pin, INPUT);
  pinMode(sensor2button_pin, INPUT);
  pinMode(sensor3button_pin, INPUT);
  pinMode(sensor4button_pin, INPUT);

  pinMode(sensor5button_pin, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(sensor5button_pin), clearreset, CHANGE); 

  pinMode(sensor6button_pin, INPUT);
  pinMode(sensor7button_pin, INPUT);

  // OUTPUT pins
  pinMode(buzzerpin, OUTPUT);
  pinMode(led1_pin, OUTPUT);
  pinMode(led2_pin, OUTPUT);
  pinMode(led3_pin, OUTPUT);
  pinMode(led4_pin, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  button1_state = digitalRead (sensor1button_pin);
  button2_state = digitalRead (sensor2button_pin);
  button3_state = digitalRead (sensor3button_pin);
  button4_state = digitalRead (sensor4button_pin);
  button5_state = digitalRead (sensor5button_pin);
  button6_state = digitalRead (sensor6button_pin);
  button7_state = digitalRead (sensor7button_pin);

  Serial.println(digitalRead (sensor5button_pin));

  if( button1_state == HIGH || button2_state == HIGH || button3_state == HIGH || button4_state == HIGH) {
    delay(280);
    buttoncount = buttoncount + 1;
  }

  if (button1_state == HIGH || button2_state == HIGH || button3_state == HIGH || button4_state == HIGH) {
    if(buttoncount<2){
      originalstate();
      alertstate();
      evacuationstate();
    }
  } 
}

// LED lighting arrangements
void originalstate() {
  digitalWrite(led1_pin, HIGH);
  digitalWrite(led2_pin, LOW);
  digitalWrite(led3_pin, LOW);
  digitalWrite(led4_pin, LOW);
  delay(1500);
}

void alertstate() {
  digitalWrite(led1_pin, LOW);
  digitalWrite(led2_pin, HIGH);
  digitalWrite(led3_pin, LOW);
  digitalWrite(led4_pin, LOW);
  delay(1500);
}

void evacuationstate() {
  digitalWrite(led1_pin, LOW);
  digitalWrite(led2_pin, LOW);
  digitalWrite(led3_pin, HIGH);
  digitalWrite(led4_pin, LOW);
  delay(1500);
}

void isolatestate() {
  digitalWrite(led1_pin, LOW);
  digitalWrite(led2_pin, LOW);
  digitalWrite(led3_pin, LOW);
  digitalWrite(led4_pin, HIGH);
}

// Clear or reset back to the begin

void clearreset() { 
 button1_state = LOW;
 button2_state = LOW;
 button3_state = LOW;
 button4_state = LOW;
 button5_state = LOW;
 button6_state = LOW;
 button7_state = LOW;

 digitalWrite(led1_pin, LOW);
 digitalWrite(led2_pin, LOW);
 digitalWrite(led3_pin, LOW);

 buttoncount = 0;        
 exit;
}
  • 3
    The arduino has a reset pin, pull it to ground with switch,and it will reset from the beginning. – Chad G May 24 '18 at 15:50
  • i tried your one but it completely reset the arduino , but that's fine for the reset button .any way ,i can interrupt the program while running and change to any other function of the program . such as when we press the reset button it goes to reset, if we press a push button it goes to some any other function. – Waranga Ratnayake May 24 '18 at 16:02
  • set a flag variable in the interrupt service function ... check the flag at the beginning of each state function and skip digitalWrite() and delay() commands if the flag is set – jsotola May 24 '18 at 16:14
  • you could also use a state variable and call the state functions depending on its value .... use the interrupt to set the state variable to a specific value – jsotola May 24 '18 at 16:16
  • you have two identical if statements one after another .... merge the contents into one – jsotola May 24 '18 at 16:18
2

You should enable verbose compilation in the IDE. You will then have a chance to see this compiler warning:

warning: statement is a reference, not call, to function ‘exit’
  exit;
      ^
warning: statement has no effect

Naming a function without calling it is a way to get a pointer to the function. It's equivalent to &exit. But since you do nothing with that pointer, the statement has no effect, and that's exactly what the compiler is warning you about.

You presumably want to call the exit() function, like in:

exit(0);

Edit: That being said, exit() is probably not what you want. This function just stops your program by putting it in an infinite loop. If you want it to restart from scratch, you can first declare

extern "C" void __init();

then, instead of exit(0); call __init();. This will send your program to the beginning of the initialization code from the C runtime, which is responsible of resetting the stack and initializing the memory (.data and .bss sections). Note that this is not equivalent to a hardware reset because:

  • doing this does not run the bootloader
  • more importantly, it doesn't reset the IO registers of the peripherals to their default reset state.
1

You need non-blocking code in combination with a finite state machine: 1. Non-blocking code: You should not use delay(), since it is just busy waiting. Instead use the millis() function to measure the time distance between the last execution of the code part and the current time. If it has reached a certain level (like 1500ms), execute the code and save the current time in a timestamp as a reference for the next execution. Refer to the BlinkWithoutDelay example of the Arduino IDE. There are also many tutorials for that on the internet, so I will not explain this further here. 2. Finite state machine: Here your loop() function contains of a switch statement with a (mostly numerical) state variable as parameter. Every case contains only the code for its special case. To get from one state to another you would just change the state variable to the corresponding value. You can also do this in an ISR (if you set the state variable as volatile). If you non-blocking code as described above, the loop() function is executed very fast, so that the change of the state variable inside the ISR takes effect almost immediately (delay will not be sensable by a human). Something like this:

volatile int state=0;

void isr_function(){
    state++;
    if(state>1) state=0;
}

void loop(){
    switch(state){
        case 0: // state 0
            do_something();
            break;
        case 1: // state 1
            do_another_thing();
            break;
    }
}

Note: Depending in your target you may want to add code for button debouncing, so that one button press is really sensed as one press, not more. This is relevant most times you have non-blocking code. Debouncing has been described many times in the internet, so just Google it

0

... .any way, I can interrupt the program while running and change to any other function of the program. such as when we press the reset button it goes to reset, if we press a push button it goes to some any other function.

Interrupt will not help you achieve your requirement. You want to 'reset the state' of your running sketch. But after the interrupt the MCU returns in the code where it was before interrupt and continues.

You should implement the 'reset of the state' in your algorithm. In a loop of a non-blocking sketch you can check the button and if it is pressed, then 'reset the state' of the sketch.

  • Did you read my answer? __init() completely resets the state of the program. There is no “after the interrupt”: since __init() does not return, the following reti (return from interrupt) instruction will never be executed. And there is no “state where it was before interrupt”: that state was on the stack, and the stack is reset by __init(). – Edgar Bonet May 25 '18 at 12:47
  • @EdgarBonet, I did read your answer and it is correct. I answer other point of view, not what he coded, but what he wants to achieve (second comment). He doesn't want to reset the program, only the 'state of the program'. – Juraj May 25 '18 at 12:53
  • Then you should clarify your answer, say that you are proposing a different approach (the OP specifically asked to “stop the program [...] and start again”), adjust the wording accordingly (“must” → “should”), tell if/how the proposed approach is better, and maybe explain how resetting the “state of the program” (whatever you mean by that) is different from resetting the program itself. – Edgar Bonet May 25 '18 at 13:43

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.