Delay() appears to no longer operate in ms

Hi everyone, apologies if this has already been covered but i have searched and have only found the oposite problem.

my code is using the DS3231 rtc to keep time, obviously :), and i am using this to trigger relays at specific times; this portion of the code is functioning very well.

I decided i would like a manual way of triggering a relay sequence with a button and i opted for the hardware interrupt approach described here:

it does function as intended in all ways except, my "void ISR" contains delay() commands which are strangely no longer behaving in the units of milliseconds!

for example, i have delay(3000000) leading to a real life delay of ~18 seconds, where it clearly ought to be 3000 seconds or 50 minutes, so 166.666 faster.

I can fudge my way around this, by simply correcting by a factor of 166.7, but i would prefer to understand what i have done to cause this.

This is my first post, i have been tinkering with arduino in my late night free-time when the kids are sleeping, sorry if it feels like a waste of bits reading it but i'd love someone to explain what is happening here to me.

Many thanks!

apologies, it wont let me upload the .ino as i am a new user so here is the code:

//based on viral science code//

#include <DS3231.h>


int Pump_Relay = 8;
int Relay2 = 3;
int Relay3 = 4;
int Relay4 = 5;
int Relay5 = 6;
int Relay6 = 7;

DS3231  rtc(SDA, SCL);
Time t;

//need to make Pump_OnHour, relay 1 OnHour etc etc.
const int PumpOnHour = 19; //SET TIME TO ON Pump (24 HOUR FORMAT)
const int PumpOnMin = 37;
const int PumpOffHour = 22; //SET TIME TO OFF Pump
const int PumpOffMin = 28;

const int Relay1_OnHour = 19; //SET TIME TO ON Relay1 (24 HOUR FORMAT)
const int Relay1_OnMin = 37;
const int Relay1_OffHour = 22; //SET TIME TO OFF Relay1
const int Relay1_OffMin = 28;

const int Relay2_OnHour = 19; //SET TIME TO ON Relay2 (24 HOUR FORMAT)
const int Relay2_OnMin = 38;
const int Relay2_OffHour = 22; //SET TIME TO OFF Relay2
const int Relay2_OffMin = 28;

const int Relay3_OnHour = 19; //SET TIME TO ON Relay3 (24 HOUR FORMAT)
const int Relay3_OnMin = 39;
const int Relay3_OffHour = 22; //SET TIME TO OFF Relay3
const int Relay3_OffMin = 28;

const int Relay4_OnHour = 19; //SET TIME TO ON Relay4 (24 HOUR FORMAT)
const int Relay4_OnMin = 40;
const int Relay4_OffHour = 22; //SET TIME TO OFF Relay4
const int Relay4_OffMin = 28;

const int Relay5_OnHour = 20; //SET TIME TO ON Relay5 (24 HOUR FORMAT)
const int Relay5_OnMin = 19;
const int Relay5_OffHour = 22; //SET TIME TO OFF Relay5
const int Relay5_OffMin = 28;

const int Relay6_OnHour = 20; //SET TIME TO ON Relay6 (24 HOUR FORMAT)
const int Relay6_OnMin = 19;
const int Relay6_OffHour = 22; //SET TIME TO OFF Relay6
const int Relay6_OffMin = 28;
int buttonPin = 2;

volatile int switchState;

void buttonInterrupt() {
  switchState = digitalRead(buttonPin);

  if (switchState == HIGH) {
    digitalWrite(Pump_Relay,HIGH);

    delay(3000000); // this results in 18 s of delay in reality!

    digitalWrite(Relay2,HIGH);

    delay(3000000); // this results in 18 s of delay in reality!

    digitalWrite(Relay2,LOW);
    digitalWrite(Relay3,HIGH);

    delay(3000000); // this results in 18 s of delay in reality!

    digitalWrite(Relay3,LOW);
    digitalWrite(Relay4,HIGH);

    delay(3000000); // this results in 18 s of delay in reality!

    digitalWrite(Relay4,LOW);
    digitalWrite(Relay5,HIGH);

    delay(3000000); // this results in 18 s of delay in reality!

    digitalWrite(Relay5,LOW);
    digitalWrite(Relay6,HIGH);

    delay(3000000); // this results in 18 s of delay in reality!

    digitalWrite(Relay5,LOW);
    digitalWrite(Pump_Relay,LOW);

delay(3000000); // this results in 18 s of delay in reality!
    
  }
  }

void setup() {
  Serial.begin(9600);
  rtc.begin();

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(Pump_Relay, OUTPUT);
  digitalWrite(Pump_Relay, LOW);

  pinMode(Relay2, OUTPUT);
  digitalWrite(Relay2, LOW);

  pinMode(Relay3, OUTPUT);
  digitalWrite(Relay3, LOW);

  pinMode(Relay4, OUTPUT);
  digitalWrite(Relay4, LOW);

  pinMode(Relay5, OUTPUT);
  digitalWrite(Relay5, LOW);

  pinMode(Relay6, OUTPUT);
  digitalWrite(Relay6, LOW);
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonInterrupt, CHANGE);

}

void loop() {
  //switchState = digitalRead(2);
  t = rtc.getTime();
  Serial.print(t.hour);
  Serial.print(" hour(s), ");
  Serial.print(t.min);
  Serial.print(" minute(s)");
  Serial.println(" ");
  delay (1000);
  
  if(t.hour == PumpOnHour && t.min == PumpOnMin){
    digitalWrite(Pump_Relay,HIGH);
    Serial.println("PUMP ON");
    }
    
    else if(t.hour == PumpOffHour && t.min == PumpOffMin){
      digitalWrite(Pump_Relay,LOW);
      Serial.println("PUMP OFF");
    }

    if(t.hour == Relay2_OnHour && t.min == Relay2_OnMin){
    digitalWrite(Relay2,HIGH);
    Serial.println("Relay2 ON");
    }
    
    else if(t.hour == Relay2_OnHour && t.min == Relay2_OnMin){
      digitalWrite(Relay2,LOW);
      //Serial.println("Relay1 OFF");
    }

    if(t.hour == Relay3_OnHour && t.min == Relay3_OnMin){
    digitalWrite(Relay3,HIGH);
    Serial.println("Relay3 ON");
    }
    
    else if(t.hour == Relay3_OnHour && t.min == Relay3_OnMin){
      digitalWrite(Relay3,LOW);
      //Serial.println("Relay3 OFF");
    }

    
    if(t.hour == Relay4_OnHour && t.min == Relay4_OnMin){
    digitalWrite(Relay4,HIGH);
    Serial.println("Relay4 ON");
    }
    
    else if(t.hour == Relay4_OnHour && t.min == Relay4_OnMin){
      digitalWrite(Relay4,LOW);
      //Serial.println("Relay3 OFF");

      
    if(t.hour == Relay5_OnHour && t.min == Relay5_OnMin){
    digitalWrite(Relay5,LOW);
    Serial.println("Relay5 ON");
    }
    
    else if(t.hour == Relay5_OnHour && t.min == Relay5_OnMin){
      digitalWrite(Relay5,HIGH);
      //Serial.println("Relay3 OFF");

      
    if(t.hour == Relay6_OnHour && t.min == Relay6_OnMin){
    digitalWrite(Relay6,LOW);
    Serial.println("Relay6 ON");
    }
    
    else if(t.hour == Relay6_OnHour && t.min == Relay6_OnMin){
      digitalWrite(Relay6,HIGH);
      //Serial.println("Relay3 OFF");
    }
    }
    }

}





Interrupts are off inside ISRs. delay() depends on interrupts to run.

Please post all your code.

Use the IDE tool Copy for Forum and paste it here in your next post.

a7

1 Like

I hope this is what you meant alto777, i'm new here and not good at diving this thing!

thank you for engaging and helping me out.


//based on viral science code//

#include <DS3231.h>


int Pump_Relay = 8;
int Relay2 = 3;
int Relay3 = 4;
int Relay4 = 5;
int Relay5 = 6;
int Relay6 = 7;

DS3231  rtc(SDA, SCL);
Time t;

//need to make Pump_OnHour, relay 1 OnHour etc etc.
const int PumpOnHour = 19; //SET TIME TO ON Pump (24 HOUR FORMAT)
const int PumpOnMin = 37;
const int PumpOffHour = 22; //SET TIME TO OFF Pump
const int PumpOffMin = 28;

const int Relay1_OnHour = 19; //SET TIME TO ON Relay1 (24 HOUR FORMAT)
const int Relay1_OnMin = 37;
const int Relay1_OffHour = 22; //SET TIME TO OFF Relay1
const int Relay1_OffMin = 28;

const int Relay2_OnHour = 19; //SET TIME TO ON Relay2 (24 HOUR FORMAT)
const int Relay2_OnMin = 38;
const int Relay2_OffHour = 22; //SET TIME TO OFF Relay2
const int Relay2_OffMin = 28;

const int Relay3_OnHour = 19; //SET TIME TO ON Relay3 (24 HOUR FORMAT)
const int Relay3_OnMin = 39;
const int Relay3_OffHour = 22; //SET TIME TO OFF Relay3
const int Relay3_OffMin = 28;

const int Relay4_OnHour = 19; //SET TIME TO ON Relay4 (24 HOUR FORMAT)
const int Relay4_OnMin = 40;
const int Relay4_OffHour = 22; //SET TIME TO OFF Relay4
const int Relay4_OffMin = 28;

const int Relay5_OnHour = 20; //SET TIME TO ON Relay5 (24 HOUR FORMAT)
const int Relay5_OnMin = 19;
const int Relay5_OffHour = 22; //SET TIME TO OFF Relay5
const int Relay5_OffMin = 28;

const int Relay6_OnHour = 20; //SET TIME TO ON Relay6 (24 HOUR FORMAT)
const int Relay6_OnMin = 19;
const int Relay6_OffHour = 22; //SET TIME TO OFF Relay6
const int Relay6_OffMin = 28;
int buttonPin = 2;

volatile int switchState;

void buttonInterrupt() {
  switchState = digitalRead(buttonPin);

  if (switchState == HIGH) {
    digitalWrite(Pump_Relay,HIGH);

    delay(3000000);

    digitalWrite(Relay2,HIGH);

    delay(3000000);

    digitalWrite(Relay2,LOW);
    digitalWrite(Relay3,HIGH);

    delay(3000000);

    digitalWrite(Relay3,LOW);
    digitalWrite(Relay4,HIGH);

    delay(3000000);

    digitalWrite(Relay4,LOW);
    digitalWrite(Relay5,HIGH);

    delay(3000000);

    digitalWrite(Relay5,LOW);
    digitalWrite(Relay6,HIGH);

    delay(3000000);

    digitalWrite(Relay5,LOW);
    digitalWrite(Pump_Relay,LOW);

delay(3000000);
    
  }
  }

void setup() {
  Serial.begin(9600);
  rtc.begin();

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(Pump_Relay, OUTPUT);
  digitalWrite(Pump_Relay, LOW);

  pinMode(Relay2, OUTPUT);
  digitalWrite(Relay2, LOW);

  pinMode(Relay3, OUTPUT);
  digitalWrite(Relay3, LOW);

  pinMode(Relay4, OUTPUT);
  digitalWrite(Relay4, LOW);

  pinMode(Relay5, OUTPUT);
  digitalWrite(Relay5, LOW);

  pinMode(Relay6, OUTPUT);
  digitalWrite(Relay6, LOW);
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonInterrupt, CHANGE);

}

void loop() {
  //switchState = digitalRead(2);
  t = rtc.getTime();
  Serial.print(t.hour);
  Serial.print(" hour(s), ");
  Serial.print(t.min);
  Serial.print(" minute(s)");
  Serial.println(" ");
  delay (1000);
  
  if(t.hour == PumpOnHour && t.min == PumpOnMin){
    digitalWrite(Pump_Relay,HIGH);
    Serial.println("PUMP ON");
    }
    
    else if(t.hour == PumpOffHour && t.min == PumpOffMin){
      digitalWrite(Pump_Relay,LOW);
      Serial.println("PUMP OFF");
    }

    if(t.hour == Relay2_OnHour && t.min == Relay2_OnMin){
    digitalWrite(Relay2,HIGH);
    Serial.println("Relay2 ON");
    }
    
    else if(t.hour == Relay2_OnHour && t.min == Relay2_OnMin){
      digitalWrite(Relay2,LOW);
      //Serial.println("Relay1 OFF");
    }

    if(t.hour == Relay3_OnHour && t.min == Relay3_OnMin){
    digitalWrite(Relay3,HIGH);
    Serial.println("Relay3 ON");
    }
    
    else if(t.hour == Relay3_OnHour && t.min == Relay3_OnMin){
      digitalWrite(Relay3,LOW);
      //Serial.println("Relay3 OFF");
    }

    
    if(t.hour == Relay4_OnHour && t.min == Relay4_OnMin){
    digitalWrite(Relay4,HIGH);
    Serial.println("Relay4 ON");
    }
    
    else if(t.hour == Relay4_OnHour && t.min == Relay4_OnMin){
      digitalWrite(Relay4,LOW);
      //Serial.println("Relay3 OFF");

      
    if(t.hour == Relay5_OnHour && t.min == Relay5_OnMin){
    digitalWrite(Relay5,LOW);
    Serial.println("Relay5 ON");
    }
    
    else if(t.hour == Relay5_OnHour && t.min == Relay5_OnMin){
      digitalWrite(Relay5,HIGH);
      //Serial.println("Relay3 OFF");

      
    if(t.hour == Relay6_OnHour && t.min == Relay6_OnMin){
    digitalWrite(Relay6,LOW);
    Serial.println("Relay6 ON");
    }
    
    else if(t.hour == Relay6_OnHour && t.min == Relay6_OnMin){
      digitalWrite(Relay6,HIGH);
      //Serial.println("Relay3 OFF");
    }
    }
    }

}



type or paste code here

@scrapking, I've fixed your post so it's more readable.

Note that we prefer it if you post your code in a post; we don't have to download it first and users with a cell phone can also view it.

1 Like

Thanks, sorry about that being hard to read.. i had a look in FAQ for a guide on things like this but didn't spot anything so just took a crack at it.

any ideas why the delay is out by a factor of 166.7?

You must not use delay() in an ISR ( as @alto777 already pointed out). They don't work when called within an ISR. ISRs should be short and are needed if very fast reaction to an event is mandatory. They are inappropiate for the use with buttons.
Simply read your button within loop() and react accordingly.

1 Like

Ah ok, i misunderstood what @alto777 had meant.

I shall experiment with it outside an ISR and in the loop, but i had thought it would result in an unresponsive button.

Thanks for the post!

Use a millis() based approach instead of delay().

You got the code posting thing down, so.

Even if the delays worked in the interrupt, when you did invoke that code, your program would go,off for 18 million milliseconds and all that would be happening would be the relays turning on and off in the sequence you wrote.

18 thousand seconds. Check my calculation, but that's five hours where the rest of your code does. Not. Execute.

So you need to do two things at once, probably.

I am in transit, later I'll look for and you can look for Arduino relay RTC programs. Add Arduino to any search and see what ppl have accomplished. Get inspiration or borrow or steal codeā€¦

A relay sequencer with an RTC has been done many times.

Meanwhile, check these out google-wise:

Arduino blink without delay

and

 Arduino two things at once 

to see the general idea of delay()-free programming. Also forget about interrupts for the moment. They have their place, just not here, and the complexity they add is to be weighed. Def not for beginners.

I use interrupts very rarely, to a first approximation never, except when it is all done for me when I use a library and don't even know myself that's what's making it work.

Oh, welcome to the forum!

a7

@scrapking I see you have massively edited your first post. In the future, please do not do that as it can make nonsense of the following posts.

New info, new post. Change the code? Post it again in its entirety. And so forth.

a7

have you seen the doc ?

Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs, only one can run at a time, other interrupts will be executed after the current one finishes in an order that depends on the priority they have. millis() relies on interrupts to count, so it will never increment inside an ISR. Since delay() requires interrupts to work, it will not work if called inside an ISR. micros() works initially but will start behaving erratically after 1-2 ms. delayMicroseconds() does not use any counter, so it will work as normal.

I would use a button library and a state machine approach (Here is a small introduction to the topic: Yet another Finite State Machine introduction)

1 Like

Thanks I shall check into those.

the reason the delay was set so high was that was me forcing it to work in 10's of seconds interval, but this was before you all enlightened me about the mistake i had made using delay() in ISR.

to be clear, i'm after a delay around 20-30 seconds long, to be optimised with empirical testing, and not something in the magnitude of minutes, let alone thousands of them :slight_smile:

I am now tinkering on using an ISR to switch pin X to high so input pin Y can read it and trigger my if() statement.

that way i estimate the button will be responsive, but have whatever the delay in finishing the loop to hit my IF() statement is, which is fine.

thanks for the engagement, i have learned a lot already :melting_face:

I believe that edit was made by @sterretje helping me fix the formatting?

apologies if i did do something without realising

Very creative.

You can do better, however. Typically an ISR is used to set a flag, and the mainline code sees that the flag has been set, does whatever that means, then clears the flag.

What's a flag? You can use a boolean variable

volatile bool myFlag;

Set it true in the ISR

    myFlag = true;

See it true in your code

    if (myFlag) {
    
// launch the missiles. Feed the dog. Whatever.

      myFlag = false;  // so you don't do it until the flag is set again by the ISR
    }

I repeat, interrupts can be fun and useful. I encourage you to leave them aside for the moment, they do not need to be part of this solution.

a7

1 Like

@alto777, I can not really call moving three backticks a massive edit :rofl:

Indeed. Your normal text (and the youtube video) was also inside the code tags which made it more difficult to read. I've just moved your opening code tag from the beginning of the post to the beginning of the code.

No, not a massive edit, but massive changes because. When I saw the post, it was without the ticks and as such a pile of text from which I dug out and answered what I thought would help.

Instead of seeing how to fix the post.

@scrapking has gone well beyond the typical first time posters, for which s/he should be praised if not at least not criticized. Sry.

But seeing the chick with the interrupts video, Imthought that must be new. By coincidence I just recently watched that. I don't remember it like I don't remember most of what happened >> 24 hours ago. Evidently she made no mention of some key details around using interruptsā€¦

a7

2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.