Several tasks using millis function

Hello,

I am a beginner in writing code in Arduino, so I will be glad to see your help with my project. In short, I don't know exactly how to program millis function so it would work.
Short description of what I would like my program to do:

I am using 1x 24VAC relay and 2x 2 Relay modules. With 2x 2 Relay modules I control the connections to 24VAC relay. At first, the 24V relay is in off state and I would like to measure its coil resistance at that time. Before relay turns on, I would like to disconnect the connections from coil to arduino with Module relays, turn relay on and then check if +5V is passed through the poles of 24V relay. 24V Relay is off for 300ms and then on for 300ms, in a loop.

What relays do:

  • Relay 2 turns on to provide connection between A1 of 24V relay (first side of coil) and +5V of Arduino
  • Relay 4 turns on to provide connection between A2 of 24V relay (second side of coil) and Analog A0 of Arduino
  • Relay 1 turns on to provide connection between A1 of 24V relay (first side of coil) and one connection of 24AC
  • Relay 3 turns on to provide connection between A1 of 24V relay (second side of coil) and one connection of 24AC

I would like my code to run like this:

  • 000ms: Program start
  • 100ms: Turn relay 2 and 4 on
  • 150ms: Measure resistance of 24V Relay's coil
  • 200ms: Turn relay 2 and 4 off
  • 300ms: Turn relay 1 and 3 on
  • 450ms: Check if poles of 24V Relay are all on
  • 600ms: Turn relay 1 and 3 off
  • 600ms: Restart the program

My code so far:

// inputs and outputs

#define relay1 8
#define relay2 9
#define relay3 10
#define relay4 11
#define Switch1Pole1 47
#define Switch1Pole2 49
#define Switch1Pole3 51
#define Switch1Pole4 53

int readResistance = 0;

// constants

const unsigned long interval1 = 100;
const unsigned long interval2 = 150;
const unsigned long interval3 = 200;
const unsigned long interval4 = 300;
const unsigned long interval5 = 450;
const unsigned long interval6 = 550;
const unsigned long interval7 = 600;

// variables

unsigned long TimeBefore1 = 0;
unsigned long TimeBefore2 = 0;
unsigned long TimeBefore3 = 0;
unsigned long TimeBefore4 = 0;
unsigned long TimeBefore5 = 0;
unsigned long TimeBefore6 = 0;
int pinstate1 = 0;
int pinstate2 = 0;
int pinstate3 = 0;
int pinstate4 = 0;
unsigned int counter1 = 0;
unsigned int counter2 = 0;
unsigned int counter3 = 0;
unsigned int counter4 = 0;

int analogPin = 0;
int raw = 0;
int Vin = 5;
float Vout = 0;
float R1 = 900;
float R2 = 0;
float buffer = 0;

//program 

void setup() {
  pinMode(relay1, OUTPUT); 
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  digitalWrite(relay1, HIGH);
  digitalWrite(relay2, HIGH);
  digitalWrite(relay3, HIGH);
  digitalWrite(relay4, HIGH);
  pinMode(Switch1Pole1, INPUT_PULLUP);
  pinMode(Switch1Pole2, INPUT_PULLUP);
  pinMode(Switch1Pole3, INPUT_PULLUP);
  pinMode(Switch1Pole4, INPUT_PULLUP);
  Serial.begin(115200);
  }

void loop() {

  unsigned long TimeNow = millis();

  
  if (TimeNow - TimeBefore1 >= interval1) {
    TimeBefore1 = TimeNow+500;
    digitalWrite(relay2, LOW);
    digitalWrite(relay4, LOW);
 
    
    }
  
  if (TimeNow - TimeBefore2 >= interval2) {
    TimeBefore2 = TimeNow+450;
    raw = analogRead(analogPin);
    if(raw){
      buffer = raw * Vin;
      Vout = (buffer)/1024.0;
      buffer = (Vin/Vout) - 1;
      R2= R1 * buffer;
      Serial.print("Vout: ");
      Serial.println(Vout);
      Serial.print("R2: ");
      Serial.println(R2);
    }
    
  }
  
  if (TimeNow - TimeBefore3 >= interval3) {
     TimeBefore3 = TimeNow+400;
    digitalWrite(relay2, HIGH);
    digitalWrite(relay4, HIGH);
    }
    
  if (TimeNow - TimeBefore4 >= interval4) {
    TimeBefore4 = TimeNow+300;
    digitalWrite(relay1, LOW);
    digitalWrite(relay3, LOW);

    
    }
   
  if (TimeNow - TimeBefore5 >= interval5) {
    TimeBefore5 = TimeNow+150; 
    if (digitalRead(Switch1Pole1) == HIGH) {
      pinstate1 = 1;
      counter1  = counter1 + 1;
      }
    else  {
      pinstate1 = 0;
      }
    Serial.print("Pinstate: ");
    Serial.println(pinstate1);
    Serial.print("Counter: ");
    Serial.println(counter1);
    }
  
  if (TimeNow - TimeBefore6 >= interval7) {
    TimeBefore6 = TimeNow;
    digitalWrite(relay1, HIGH);
    digitalWrite(relay3, HIGH);
    }
  
  }

Yes. What is Your question, Your trouble?

ProgramStart = millis
If millis-programStart is > 100 And < 150 turn relay 2 and 4 on etc. You seem to be in that track anyway

Use blink without delay tutorial to convert logic to code. What problem are you having with it

I have no idea what you are up to with those relays but sounds odd and exciting.

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

Robin2:
The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

I have seen all these tutorials, tried them and still my program doesn't work.

The problem with my code is that I would like to do something at a specific time... If I write a program for a relay to turn on and off every 300ms, everything works fine. But when I add measuring in between, the program doesn't execute in the right order...
The problem must be somewhere in the millis() function. Do you maybe have any programs written with millis() where something happens at 100ms, another thing at 200ms, third thing at 600ms and then loops the program to repeat? I do not wish for the first thing to loop every 100ms and the second at every 200ms... I want the program to loop every 600ms and in that 600ms do different tasks.

Here is my code transformed into tutorial "Several things at a Time". My program gets totally messed up as tasks do not work in order.

// inputs and outputs

#define rele1 8
#define rele2 9
#define rele3 10
#define rele4 11
#define Switch1Pole1 47
#define Switch1Pole2 49
#define Switch1Pole3 51
#define Switch1Pole4 53

int readResistance = 0;

// constants

const unsigned long interval1 = 100;
const unsigned long interval2 = 150;
const unsigned long interval3 = 200;
const unsigned long interval4 = 300;
const unsigned long interval5 = 450;
const unsigned long interval6 = 550;
const unsigned long interval7 = 600;

// variables

unsigned long TimeBefore1 = 0;
unsigned long TimeBefore2 = 0;
unsigned long TimeBefore3 = 0;
unsigned long TimeBefore4 = 0;
unsigned long TimeBefore5 = 0;
unsigned long TimeBefore6 = 0;
int pinstate1 = 0;
int pinstate2 = 0;
int pinstate3 = 0;
int pinstate4 = 0;
unsigned int counter1 = 0;
unsigned int counter2 = 0;
unsigned int counter3 = 0;
unsigned int counter4 = 0;

int analogPin = 0;
int raw = 0;
int Vin = 5;
float Vout = 0;
float R1 = 900;
float R2 = 0;
float buffer = 0;

//program

void setup() {
  pinMode(rele1, OUTPUT);
  pinMode(rele2, OUTPUT);
  pinMode(rele3, OUTPUT);
  pinMode(rele4, OUTPUT);
  digitalWrite(rele1, HIGH);
  digitalWrite(rele2, HIGH);
  digitalWrite(rele3, HIGH);
  digitalWrite(rele4, HIGH);
  pinMode(Switch1Pole1, INPUT_PULLUP);
  pinMode(Switch1Pole2, INPUT_PULLUP);
  pinMode(Switch1Pole3, INPUT_PULLUP);
  pinMode(Switch1Pole4, INPUT_PULLUP);
  unsigned long TimeNow = millis();
  Serial.begin(115200);
}

void loop() {




  if (millis() - TimeBefore1 >= interval1) {

    digitalWrite(rele2, LOW);
    digitalWrite(rele4, LOW);
    TimeBefore1 += interval1;

  }

  if (millis() - TimeBefore2 >= interval2) {

    raw = analogRead(analogPin);
    if (raw) {
      buffer = raw * Vin;
      Vout = (buffer) / 1024.0;
      buffer = (Vin / Vout) - 1;
      R2 = R1 * buffer;
      Serial.print("Vout: ");
      Serial.println(Vout);
      Serial.print("R2: ");
      Serial.println(R2);
      TimeBefore2 += interval2;
    }

  }

  if (millis() - TimeBefore3 >= interval3) {

    digitalWrite(rele2, HIGH);
    digitalWrite(rele4, HIGH);
    TimeBefore3 += interval3;

  }

  if (millis() - TimeBefore4 >= interval4) {

    digitalWrite(rele1, LOW);
    digitalWrite(rele3, LOW);
    TimeBefore4 += interval4;

  }

  if (millis() - TimeBefore5 >= interval5) {

    if (digitalRead(Switch1Pole1) == HIGH) {
      pinstate1 = 1;
      counter1  = counter1 + 1;
    }
    else  {
      pinstate1 = 0;
    }
    Serial.print("Pinstate: ");
    Serial.println(pinstate1);
    Serial.print("Counter: ");
    Serial.println(counter1);
     TimeBefore5 += interval5;
  }

  if (millis() - TimeBefore6 >= interval7) {

    digitalWrite(rele1, HIGH);
    digitalWrite(rele3, HIGH);
    
     TimeBefore6 += interval7;

  }

}

Serial output says that with updated code, program reads resistance couple of times when 24V relay is off, with my old code it is just the opposite, the program counts more times.
Serial output with this updated version of the program:

Vout: 2.2.03
Pinstate: 1
Counter: 1
Vout: 0.00
R2: 920700.00
Vout: 0.01
R2: 306300.00
Vout: 2.29
R2: 1065.03
out: 2.29
R2: 1065.03
Pinstate: 1
Counter: 2
Vout: 0.00
R2: 920700.00
Vout: 0.01
R2: 306300.00
Vout: 2.29
R2: 1065.03
Vout: 2.29
R2: 1065.03
Vout: 0.03
R2: 152700.00
Pinstate: 1
Counter: 3
Vout: 0.01
R2: 459900.00
Vout: 2.29
R2: 1069.23
Vout: 2.29
R2: 1065.03
Pinstate: 1
Counter: 4
Vout: 0.47
R2: 8700.00
Vout: 2.29
R2: 1069.23
Vout: 2.29
R2: 1069.23
Vout: 2.29
R2: 1065.03

This is the Serial output with my version of the program:

Pinstate: 1
Counter: 1
Pinstate: 1
Counter: 2
Pinstate: 1
Counter: 3
Vout: 2.29
R2: 1065.03
Pinstate: 1
Counter: 4
Pinstate: 1
Counter: 5
Pinstate: 1
Counter: 6
Vout: 2.29
R2: 1065.03

You can use the counter variant of BWD
BWD is Blink Without Delay

Since you use 50ms
Use BWD to increment a counter every 50 ms

Globals
Unsigned long then
Int duration, counter
Duration = 50
These get declared before startup()

If startSwith toggled on
If (millis() - then ) >= duration
{
Counter++
Then = millis()
}

If counter == 2 // 100 ms
Digital write relay 2& 4

If counter == 3 // 150ms
Open/close relays 2 4 as needed
Measure

And so on.....
Every increment you Open or close what was closed or open
Then open or close the new thing.

This is Not actual code. I am thumb txting on my phone. Power is out for a few days.

If counter == 20. Stop counting.
Counter = 0 // reset

The idea is that you increment counter every 50ms and do something.

We assume your coil voltage reading bit works. Using a voltage divider and such.

In that makes sense then great
If you want clarification i can do that at work in a few hours

Looks like you posted while I was txting

Seems you have a start on a path

I adapted the description in your Original Post like this
I would like my code to run like this:

000ms: Program start
    100ms: Turn relay 2 and 4 on
        150ms: Measure resistance of 24V Relay's coil
    200ms: Turn relay 2 and 4 off
    300ms: Turn relay 1 and 3 on
        450ms: Check if poles of 24V Relay are all on
    600ms: Turn relay 1 and 3 off
600ms: repeat

and I think the following pseudo code should implement it. Note that all the timing is referenced to the original start time. When the sequence completes the start time is updated to allow the whole thing to repeat.

if (millis() - startTime >= 100) {
    if (rel24on == false) {
        relays 2 and 4 on
        rel24on = true;
}

if (millis() - startTime >= 150) {
    if (resMeasured == false) {
        measure resistance
        resMeasured = true
    }
}

if (millis() - startTime >= 200) {
    if (rel24on == true) {
        relays 2 and 4 off
        rel24on = false
    }
}

[....]

if (millis() -startTime >= 600) {
   if (rel13on == true) {
        relays 1 and 3 off
    }
      // reset values for next iteration
   startTime = millis()
   rel24on = false;
   rel13on = false;
   resMeasured = false;
}

...R

EDIT ... I have updated the code slightly

All you need to keep in mind with millis is how the arduino processes code. This is the useful benefit to millis over delay but it can also catch you out. The arduino works through your code from top to bottom starting with setup only once then loop over and over. You have to be careful with variables used to store your startTime using millis as every time the code loops it can reset it. You can get over this by putting a variable in setup so that it is activated once and then reset it in your last if statement because all conditions will then have been met.

You simply need to take your good description of what you want to achieve and start converting it to code logic then actual code. e.g

I would like my code to run like this:
000ms: Program start recorded once in a variable
every time through loop check time against this variable
if time >100ms: Turn relay 2 and 4 on
remember to put an upper bound of time so that it does not turn these on every time through loop e.g <150 or as above use booleans
if time >150ms <200ms: Measure resistance of 24V Relay's coil
etc 200ms: Turn relay 2 and 4 off
etc 300ms: Turn relay 1 and 3 on
etc 450ms: Check if poles of 24V Relay are all on
etc 600ms: Turn relay 1 and 3 off
if time > 600ms: Restart the program by resetting the startTime variable

You have done well so far. You know what you want to do. Now you just need to adjust to how a microcontroller sees things. here is a trick: make 3 columns on paper. In column 1 put your human description of what you want, column 2 code logic like above, column 3 actual code for each part. e.g

000ms program start // record program start only once in variable // in setup- programStart = millis();
100ms turn relay 2 and 4 on// if time > 100ms turn relays on// if ((millis()-programStart etc

The reason i like the counter variation

If startSwith toggled on
If (millis() - then ) >= duration
{
Counter++
Then = millis()
}

Is that is the totality of timing in software.

Count becomes a digital interger value.

The multiple if() statements only look to see what the count is

I will note that this only works for timing durations that share a common value