Is it possible to pauze arduino program

Hello everybody,

I was wondering if I can "Pauze" my arduino code. I have 4 relays that needed be turned on and off. Every relay is connected to 4 different roller shutters. And when a rollershutter is working , it needs to be stopped when pressing a button. I have now a button connected with a I2C bus, when it gives a 1 the relays start when it gives a 0, I want them to stop instantly.
I was looking for a while loop or something with millis but I cant figure it out.
Can you guys help me?

Testopstelling_Motor_Slave.ino (1,6 KB)

Please post your code in a message, not an attachment, using code tags. Actually, you were advised to do that multiple times in the last thread you started.

No.

But what you can do is ignore a certain section of the code using an if statement, that looks at the time between when you want to start your code again and when you stoped it.

Lots and lots of examples if you search for "state machine", we get this question almost every day on this forum.

// SLAVE

#include <Wire.h>                   
#define SLAVE_ADDR 9                // Slave I2C address

#define Relay1 2                  
#define Relay2 3                     
#define Relay3 4                   
#define Relay4 5                  
int Lampon;                         //Receiving Values from Master

void setup() {
Wire.begin(SLAVE_ADDR);             //Initialize I2C as slave
Wire.onReceive(receiveEvent);       //Receivefunction from Master to Slave
Serial.begin(9600);
Serial.println("I2C Slave demonstration");
pinMode(Relay1,      OUTPUT);  
pinMode(Relay2,      OUTPUT);
pinMode(Relay3,      OUTPUT);
pinMode(Relay4,      OUTPUT);
}

void receiveEvent(){                    
 Lampon  = Wire.read();                
 Serial.println(Lampon);}
                                                                      
void loop(){
  if (Lampon ==0){                  //Turn all the relays off (Active-LOW relays)
    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2, HIGH);
    digitalWrite(Relay3, HIGH);
    digitalWrite(Relay4, HIGH);
  }
  
  if (Lampon ==1){                
  delay(100);
  digitalWrite(Relay1, LOW); //Relay on
  delay(3000);
  digitalWrite(Relay1, HIGH);//Relay off

  delay(100);  
  digitalWrite(Relay2, LOW); //Relay on
  delay(6000);
  digitalWrite(Relay2, HIGH);//Relay off
   
  delay(100);
  digitalWrite(Relay3, LOW); //Relay on
  delay(4000);
  digitalWrite(Relay3, HIGH);//Relay off

  delay(100);
  digitalWrite(Relay4, LOW); //Relay on
  delay(2000);
  digitalWrite(Relay4, HIGH);//Relay off
 }
}

Sorry, im kind of new in this

Thanks for complying. There is a help thread at the top of this forum for things like that.

I think your question is really, "can I interrupt an Arduino program" not "pause" it. Because nothing can happen while the 'delay()' function is running. If that is wrong, then please explain what you mean by "pausing" it.

There is also a section about that in the help threads I mentioned.

If you want it to respond instantly you normally need an interrupt.

You can get to respond "almost instantly" if you get rid of the delay(), by using one or more millis() timers, and making your loop run as fast as possible.

...Without an interrupt your program can respond to a switch during a delay() or while it's doing anything else and you have to wait for the loop to come-around and read the switch.

But, you said, with a button. Button pushing is usually orders of magnitude slower than the program can poll a switch in the loop() function. So please, don't think you need a hardware interrupt and its interrupt handler, to interface the switch.

The process isn't beginner friendly, and usually confounds people even more than the polling method.

You have no hope of reading the button with all those delays. An interrupt is not the solution. You need to learn about state machines and millis() polling.
First make those adjustments, then adding a button state and polling will be a trivial task.
How much time to you have left to work on this before it's due?

If receiveEvent() gets called from an interrupt you can make a fakeDelay() function that checks for the value of Lampon.

// Return 'true' if Lampon goes to 0 during the delay
bool fakeDelay(unsigned long milliseconds)
{
  unsigned long startTime = millis();
  while (millis() - startTime < milliseconds)
  {
    if (Lampon == 0)
      return true;
  }
  return false;
}

Then you can replace each of the delay(n); calls with:

if (fakeDelay(n)) return;

That will short-circuit the delays and go back to the beginning of loop() if Lampon changes to 0.

NOTE: Wire.read() returns a byte so Lampon should be a byte, not an int.

You have a sequence of switching relays on/off.
This is something that can be programmed with a state-machine and non-blocking timing

explaining non-blocking timing:

explaining the basic principle of a state-machine

you could keep

void loop(){
  if (Lampon ==0){                  //Turn all the relays off (Active-LOW relays)
    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2, HIGH);
    digitalWrite(Relay3, HIGH);
    digitalWrite(Relay4, HIGH);
  }

and then add the relay-timed on/off-switching with the state-machine

void loop(){
  if (Lampon ==0){                  //Turn all the relays off (Active-LOW relays)
    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2, HIGH);
    digitalWrite(Relay3, HIGH);
    digitalWrite(Relay4, HIGH);
  }
if (Lampon ==1){
  relayOn_OFF_StateMachine();
}

the state-machine works this way: jump_in / jump_out
and as time passes by if a certain amount of time has passed by execute the next action
like

digitalWrite(Relay1, LOW); //Relay on

or

digitalWrite(Relay1, HIGH);//Relay off

basically this way

if ( TimePeriodIsOver(myTimer,100) {
  digitalWrite(Relay1, LOW); //Relay on
}
if ( TimePeriodIsOver(myTimer,3000) {
  digitalWrite(Relay1, HIGH); //Relay off
}

etc.

best regards Stefan

Hi StefanL38,

Ive tried interruptpin but that is not an solution, because it cant stop the delays. I have read your articles and I am not sure how I can stop the "delays" immediately with your suggestion? can you help me?

..Jelle

You can refer to this: how to use button to start/stop program

That seems a complicated way to hook up a button, although that's probably just my ignorance showing. But I'm keen to know a) why you have done it that way and b) how it's all connected, for my edification.

I use an i2c bus to have a connection with multiple arduinos and relays. It is for a school project and on my internship, I need to make a panel where I can control the lights and shutter doors of my intern company building (sorry for the bad English.)

Ok, but what does it actually mean to "have now a button connected with a I2C bus". I can't picture how it hangs together. Is the button an actual i2c device?

I think he means that his Arduino is an I2C slave device and is connected to another Arduino which is acting as an I2C master. The master is sending data to his slave, maybe derived from a push button.

However, we have never seen the code for other end, the I2C master so we don't know if this is right and it is this end that is generating the problems.

Basically the code has not been very well thought out, as it needs to implement a state machine with no delays in it, as others have pointed out adnausiam.

Until he gets round to thinking like that the whole project is doomed to fail. As illustrated by the very bad title of the thread.

The answer is that you can't stop a delay, once called it has to finish.
The secret is to remove all delays and write the code as a state machine.

The trouble is that @jelle_koomen does not want to start and stop a program. He just thought he did when he first posed the problem.

This is a state diagram. Each state has a number associated with it represented by a variable called state or what ever you like. When a state is entered it does the actions indicated in the box. The transition from one state to another occurs on an action, these are indicated by a line from one state to another. Next to these lines is what action causes the transition from one state to the other.

Your state is particularly simple, you transition from one state to the next on only two actions. The first being the time you have been in that state and the second is the Lampon variable becoming 0.
Your loop function consists of taking the state variable value and going to the state indicated by it. This can be done by using a case / switch structure. Before you do that you should if the state variable has changed since last time. If it has then update an unsigned long variable called startTime to the value of millis. You use this in each state to see if it is time to change states. If in a state you detect the Lampon variable is equal to 0 (or false) then you change the state number back to zero.
Note that it doesn't matter if you enter any one state a number of times because only on the first entry to that state actually changes the relay values to something new, after that it keeps writing the same value to the relays and so does nothing.

what about going to sleep - that would pause the code for a while?

Well it would pause the code until it got woken up again by some sort of interrupt which is not relevant.

My comment of NO was before he posted any code, and you ignore the caveat I put in the rest of my answer.

However, we have established that the OP does not actually want to pause the code at all, it was a result of not thinking correctly what he wanted / needed to do to make his project work.

yeah - was more a general comment that sleeping the Arduino would pause a code, not arguing with your answer.

1 Like