Help with Millis() in control

Hello. I am new to Arduino programming and I am having troubles with a project I am doing. The project is a pH controller for hydroponics, and the idea that I have is when the difference between the pH that I want and the pH that I have is above a certain number a pump activates (with a relay) for a certain period if time but I can't use a delay. The part of the code is the following:

  dpH = phValue - pHQ;
  if (dPH > 0) {
    if (timer == false){
      currentTime = millis();
      timer = true;      
    }
    pump();
  }
}


void pump()
{
  if (dpH <= 3 && dpH > 2) { 
    digitalWrite(rele, 1);
    if (millis()-currentTime >= 5000) {
      digitalWrite(rele, 0);
      timer = false;
    }
  }
  else if (dpH <= 2 && dpH > 1) { 
    digitalWrite(rele, 1);
    if (millis()-currentTime >= 3000) {
      digitalWrite(rele, 0);
      timer = false;
    }
  }
  else if (dpH <= 1 && dpH > 0) { 
    digitalWrite(rele, 1);
    if (millis()-currentTime >= 2000) {
      digitalWrite(rele, 0);
      timer = false;
    }
  }
  else {
    digitalWrite(rele, 0);
    timer = false;
  }
}

I am not quite sure if it is good to go, because I don't really understand if Millis() starts to measure from the point I call it or since the beginning, or if I can have different Millis(). Thanks in advance for your help.

The value of millis() increments from the second the program beings to run and is whatever value it is at the time the program looks for its value thru the call.

Looking at your code I don't really understand how you are going to differentiate CurrentTime to millis()
hopefully someone else can teach us both about that.

Code fragment looks ok, but better to post the whole thing.

The currentTime thing is ok because it's only set when not already timing.

Could you consider controlling the pump with, say, a state-machine:

void pumpControl( void )
{
    static uint8_t
        statePump = ST_OFF;
    static uint32_t
        tStart,
        tRunTime;
    uint32_t
        tNow = millis();

    switch( state )
    {
        case    ST_OFF:
            dpH = phValue - pHQ;
            if( dpH <= 3 )
            {
                digitalWrite( rele, HIGH );
                tStart = tNow;
                if( dpH <= 1 )
                    tRunTime = 2000ul;
                else if( dpH > 1 && dpH <= 2 )
                    tRunTime = 3000ul;
                else
                    tRunTime = 5000ul;

                state = ST_RUN;
                
            }//if
        break;

        case    ST_ON:
            if( (tNow - tStart) >= tRunTime )
            {
                digitalWrite( rele, LOW );
                state = ST_OFF;
            }//if
            
        break;
        
    }//switch

}//pumpControl

I'm sorry, I'm posting the whole code now.

#include "DFRobot_PH.h"
#include <EEPROM.h>

#define PH_PIN A1
const int relay = 2; 
float voltage, phValue= 20;
int pHQ = 7; 
int dpH = 0; 
unsigned long currentTime = 0;
boolean timer = false;
DFRobot_PH ph;

void setup()
{
  Serial.begin(115200);
  ph.begin();
  pinMode(rele, OUTPUT);
  initialTime= millis();
}

void loop()
{
  static unsigned long timepoint = millis();
  if (millis() - timepoint > 1000U) {           
    timepoint = millis();
    voltage = analogRead(PH_PIN) / 1024.0 * 5000;
    phValue = -2.1429 * ph.readPH(voltage, temperature) + 15.71;
    Serial.print("pH:");
    Serial.println(phValue, 2);
  }
  dpH = phValue - pHQ;
  if (dPH > 0) {
    if (timer == false){
      currentTime = millis();
      timer = true;      
    }
    pump();
  }
}


void pump()
{
  if (dpH <= 3 && dpH > 2) { 
    digitalWrite(rele, 1);
    if (millis()-currentTime >= 5000) {
      digitalWrite(rele, 0);
      timer = false;
    }
  }
  else if (dpH <= 2 && dpH > 1) { 
    digitalWrite(rele, 1);
    if (millis()-currentTime >= 3000) {
      digitalWrite(rele, 0);
      timer = false;
    }
  }
  else if (dpH <= 1 && dpH > 0) { 
    digitalWrite(rele, 1);
    if (millis()-currentTime >= 2000) {
      digitalWrite(rele, 0);
      timer = false;
    }
  }
  else {
    digitalWrite(rele, 0);
    timer = false;
  }
}

I found the first part of the loop on the internet (how to read signals from the pH sensor). And with the state-machine, I also knew I could use it but I don't really know how to specify the values (for example, the states). Thank you very much for your help.

why did you use uint8 in one place but uint32 in the other?

What do you mean? Here?

    static uint8_t
        statePump = ST_OFF;
    static uint32_t
        tStart,
        tRunTime;
    uint32_t
        tNow = millis();
.
.
.

The variable state Pump only needs to hold a very small value (basically 0 (off) or 1 (on).) This could be done with a a single bit but a byte is handy.

The other values -- those that are used in millis() timing need to be 32-bits wide because the values returned by millis() are 32-bit unsigned values.

yes that is exactly what i was wondering thank you so much.

In this case, the pump can turn on and at some point before 5 seconds dpH goes out of range, the pump does not turn off.

It is important that time checks are made in millis code.
To that effect, a pH test might set variables to trigger a function outside of the test code itself.

Time conditions are only one kind of event. Pin states and values in variables are other trigger events for conditional tasks in main loop code. Engineers have been doing it since the 70's that I know of.

if ( pumpTimer == 0 ) {  // to pH test only when the pump is not running
// you may or may not want that. You must decide, take your time.
....
  if (dpH <= 3 && dpH > 2) 
  { 
    pumpTimer = 5000;  // an int, does double-duty
    digitalWrite(rele, 1);
    timerStart = millis();  // causes the one pump function to run in turn
  }
  else if (......

void runPumpOnTimer()  // this function Must run every time that loop() runs.
{
  if ( pumpTimer > 0 )  // you turn it on by telling it how long to run
  {
    if ( millis() - timerStart >= pumpTimer ) {
      digitalWrite(rele, 0);
      pumpTimer = 0;         // this makes the pump run a 1-shot event
    }
  }
}

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