Using mills / statemachine, skipped loops?

edit: problem found and fixed by Robin2

Changed: previousRelayPinMillis += RelayPinOFF;
To: previousRelayPinMillis = currentMillis;

Trying to use mills instead of delay.
I have the below working to some extent.
When the start button is pressed it exits out of the start loop into the prefill loop.
However, it seem that the first 10-20 loops (out of 100) are skipped?
I have the serial printing how many loops are remaining, it will print from 100 to 80ish in one hit, then start the loop like normal.

Any ideas?

#include <DFRobot_LCD.h>

//Constants to set pin numbers
const int StartButtonLed = 3; //PWM Pin
const int StartButtonPin = 4;
const int PauseButtonLed = 6; //PWM Pin
const int PauseButtonPin = 7;
const int RelayPin = 8;

//Constants for drip functions
const int PreSoakCountGoal = 100; // Number of drips during PreSoak, Aim for 200ML
const int DripCycleCountGoal = 100; // // Number of drips during DripCycle, Aim for 800ML

//Variables will change
int StartButtonLedState = 0;
int StartButtonPinState = 0;
int StartButtonPinLastState = 0;
int PauseButtonLedState = 0;
int PauseButtonPinState = 0;
int RelayPinState = 0;
int StartState = 1;
int PreSoakState = 0;
int PreSoakCount = 0;
int DripCycleState = 0;
int DripCycleCount = 0;

int PulseStartButtonLedState = 0;

int RelayPinON = 500; // number of millisecs that Relay is ON
int RelayPinOFF = 250; // number of millisecs that Relay is OFF
unsigned long previousRelayPinMillis = 0;
unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

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

  pinMode (StartButtonLed, OUTPUT);
  pinMode (StartButtonPin, INPUT);
  digitalWrite(StartButtonPin, HIGH);

  pinMode (PauseButtonLed, OUTPUT);
  pinMode (PauseButtonPin, INPUT);
  pinMode (RelayPin, OUTPUT);

}

void loop() {

  currentMillis = millis(); // capture the current time

  Start();

  PreSoak();

  //DripCycle();
}

//Functions

void Start() {
  if (StartState == 1) {
    digitalWrite(StartButtonLed, HIGH);
    Serial.println("Press Start to begin");
    // handle button
    boolean StartButton_pressed = !digitalRead(StartButtonPin); // pin low -> pressed

    if (StartButton_pressed == HIGH) {
      digitalWrite(StartButtonLed, LOW);
      StartState = 0;
      PreSoakState = 1;
    }
    delay(250); // prevent bounce?
  }
}

//PreSoak
void PreSoak() { 
  //delay(250); // prevent bounce?
  if (PreSoakState == 1 && PreSoakCount < PreSoakCountGoal ) {
    // Serial.println("Starting PreSoak");
    // PulseStartButtonLed (); seems to slow down the loop? need to consider the timing it takes to pulse the led?
    if (RelayPinState == LOW) { //if the Relay is OFF

      if ((unsigned long) currentMillis - previousRelayPinMillis >= RelayPinOFF) {
        RelayPinState = HIGH;
        digitalWrite(RelayPin, RelayPinState);
        previousRelayPinMillis += RelayPinOFF;

      }
    }
    else {  // if the Relay is ON)

      if ((unsigned long) currentMillis - previousRelayPinMillis >= RelayPinON) {
        RelayPinState = LOW;
        digitalWrite(RelayPin, RelayPinState);
        previousRelayPinMillis += RelayPinON;
        PreSoakCount++;
        Serial.println(PreSoakCountGoal - PreSoakCount);
      }
    }
  }
}

//DripCycle
void DripCycle() { 
  if (DripCycleState == 1 && DripCycleCount < DripCycleCountGoal ) {
    // Serial.println("Starting DripCycle");
    // PulseStartButtonLed (); seems to slow down the loop? need to consider the timing it takes to pulse the led?
    if (RelayPinState == LOW) { //if the Relay is OFF

      if ((unsigned long) currentMillis - previousRelayPinMillis >= RelayPinOFF) {
        RelayPinState = HIGH;
        digitalWrite(RelayPin, RelayPinState);
        previousRelayPinMillis += RelayPinOFF;

      }
    }
    else {  // if the Relay is ON)

      if ((unsigned long) currentMillis - previousRelayPinMillis >= RelayPinON) {
        RelayPinState = LOW;
        digitalWrite(RelayPin, RelayPinState);
        previousRelayPinMillis += RelayPinON;
        DripCycleCount++;
        Serial.println(DripCycleCountGoal - DripCycleCount);
      }
    }
  }
}

// Pulse StartButtonLed
void PulseStartButtonLed () {
  if (PulseStartButtonLedState == 1) {
    float in, out;
    for (in = 0; in < 6.283; in = in + 0.0005)
    {
      out = sin(in) * 127.5 + 127.5;
      analogWrite(StartButtonLed, out);
    }
  }
}

ColdDrip032019.ino (3.99 KB)

That is not a complete sketch so I don't have any ideas other than to post all the code.

Have a look at the Controleo3 from Whizoo. All their code is open.

This is a solder oven, right?

blh64:
That is not a complete sketch so I don't have any ideas other than to post all the code.

Have attached the sketch if you would like to take a look.
It is still work in progress.

MorganS:
Have a look at the Controleo3 from Whizoo. All their code is open.

This is a solder oven, right?

Thanks, but different project, maybe I can get some ideas from it?

dom_christo:
Have attached the sketch if you would like to take a look.

Inline would have been a better choice.

I assume the second block of code in your Original Post is the complete program? It is much less confusing if you don't update older Posts (other than to correct typos). Just put new info in a new Post so the discussion follows logically with no need to back-track.

Anyway ...
This sort of thing can cause a problem

if ((unsigned long) currentMillis - previousRelayPinMillis >= RelayPinOFF) {


        previousRelayPinMillis += RelayPinOFF;

      }

if there was an appreciable time between the program starting and the function PreSoak() being called. It may take several iterations for the addition of RelayPinOFF to get previousRelayPinMillis past the current value of millis().

There are two options. Either set previousRelayPinMillis = millis() just before PreSoak() is called if doing so would be appropriate OR change previousRelayPinMillis += RelayPinOFF; to previousRelayPinMIliis = currentMIllis;

...R

Robin2:
It is much less confusing if you don't update older Posts

Looks like that was a moderator edit.

Robin2:
I assume the second block of code in your Original Post is the complete program? It is much less confusing if you don't update older Posts (other than to correct typos). Just put new info in a new Post so the discussion follows logically with no need to back-track.

Anyway ...
This sort of thing can cause a problem

if ((unsigned long) currentMillis - previousRelayPinMillis >= RelayPinOFF) {

previousRelayPinMillis += RelayPinOFF;

}



if there was an appreciable time between the program starting and the function PreSoak() being called. It may take several iterations for the addition of RelayPinOFF to get previousRelayPinMillis past the current value of millis().

There are two options. Either set previousRelayPinMillis = millis() just before PreSoak() is called if doing so would be appropriate OR change previousRelayPinMillis += RelayPinOFF; to previousRelayPinMIliis = currentMIllis;

...R

Thank you for this.
After thinking about it for a while I figured out Why it was happening as you pointed out.
But unsure how to tackle it. Will give it a go.

Cheers.

Robin2:
I assume the second block of code in your Original Post is the complete program?

It is. I put it inline as a convenience.

dom_christo:
But unsure how to tackle it. Will give it a go.

I gave you two solutions - both based on my own personal experience.

…R

Robin2:
I gave you two solutions - both based on my own personal experience.

...R

Thank you, that worked.