Water pump operation with millis()

Hello, I'm pretty new in the Arduino world, so i need help with some programming. The Arduino controls 3 things: a servo with a potentiometer; a relay that controls a 220v water heater with a temperature sensor; and another relay that controls a water pump activated with an infrared proximity sensor. The code works, the problem it's with the delays used in the pump cycle, that interferes with the servo operation creating a ton of lag. I've tried using millis() instead, but my knowledge is very limited and I couldn't manage to make it work. It would be very useful some guidance.

#include <OneWire.h> 
#include <DallasTemperature.h>
#include <Servo.h> 

#define Pin 3 // pin sensor
OneWire ourWire(Pin); 
DallasTemperature sensors(&ourWire);
float celsius()
{
  int dato;
  float c;
  dato=sensors.getTempCByIndex(0);
  c=(dato);
  return(c);
}
Servo yerba; //servo
int potenciometro = 0;
int valor_potenciometro;

const int ProxSensor=6; //pin infrared sensor

void setup()
{
 sensors.begin();
 pinMode (8,OUTPUT);  // pin water heater relay 

 yerba.attach(2);  // pin servo

 pinMode(7, OUTPUT); // pin pump relay
 pinMode(ProxSensor,INPUT); 
}
void loop(){
  valor_potenciometro = analogRead(potenciometro);
  valor_potenciometro = map(valor_potenciometro, 0, 1023, 0, 120); 
  yerba.write(valor_potenciometro);
    
  sensors.requestTemperatures();
  if (celsius() > 35.00) 
 {
  digitalWrite(8,HIGH);  // relay on, water heater off (water heater in NC)
 }
  else
  digitalWrite(8,LOW);  // relay off, water heater on
  float Celsius = celsius();

  if(digitalRead(ProxSensor)==LOW)      //if sensor LOW (obstacle)
  {
   delay(2000);           // wait time for pump on
   digitalWrite(7, HIGH);
   delay(3000);            // pump working time
   digitalWrite(7, LOW);   
   delay(10000);          // wait time after pump operation
  }
  else
  {
   digitalWrite(7, LOW);    
  }            
}

Thanks in advance.

Starting point, work out all the possible states the device can be in…
e.g. idle, opening, pumping, blinking etc.

Make sure you figure out ALL the possibilities.

With that, you now have ‘states’ for a state machine.

Even if they overlap, or change order, you can use millis() and switch()-case statements to navigate through the various states - based on switch inputs, or intervals.

Sometimes you might need multiple millis() timers to keep one event running, while you go to do something else.

Use millis() for timing.
This code uses esp_timer_get_time() is similar to using millis().


void fDoMoistureDetector( void * parameter )
{
  //wait for a mqtt connection
  while ( !MQTTclient.connected() )
  {
    vTaskDelay( 250 );
  }
  int      TimeToPublish = 5000000; //5000000uS
  int      TimeForADreading = 100 * 1000; // 100mS
  uint64_t TimePastPublish = esp_timer_get_time(); // used by publish
  uint64_t TimeADreading   = esp_timer_get_time();
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 10; //delay for 10mS
  float    RemainingMoisture = 100.0f; //prevents pump turn on during start up
  bool     pumpOn = false;
  uint64_t PumpOnTime = esp_timer_get_time();
  int      PumpRunTime = 11000000;
  uint64_t PumpOffWait = esp_timer_get_time();
  uint64_t PumpOffWaitFor = 60000000; //one minute
  float    lowMoisture = 23.0f;
  float    highMoisture = 40.0f;
  for (;;)
  {
    //read AD values every 100mS.
    if ( (esp_timer_get_time() - TimeADreading) >= TimeForADreading )
    {
      xEventGroupSetBits( eg, evtADCreading0 );
      TimeADreading = esp_timer_get_time();
    }
    xQueueReceive(xQ_RM, &RemainingMoisture, 0 ); //receive queue stuff no waiting
    //read gpio 0 is water level good. Yes: OK to run pump : no pump off.   remaining moisture good, denergize water pump otherwise energize water pump.
    if ( RemainingMoisture >= highMoisture )
    {
      WaterPump0_off();
    }
    if ( !pumpOn )
    {
      log_i( "not pump on ");
      if ( gpio_get_level( GPIO_NUM_0 ) )
      {
        if ( RemainingMoisture <= lowMoisture )
        {
          //has one minute passed since last pump energize, if so then allow motor to run
          if ( (esp_timer_get_time() - PumpOffWait) >= PumpOffWaitFor )
          {
            WaterPump0_on();
            log_i( "pump on " );
            pumpOn = !pumpOn;
            PumpOnTime = esp_timer_get_time();
          }
        }
        //xSemaphoreGive( sema_RemainingMoisture );
      } else {
        log_i( "water level bad " );
        WaterPump0_off();
        PumpOffWait = esp_timer_get_time();
      }
    } else {
      /*
         pump goes on runs for X seconds then turn off, then wait PumpOffWaitTime before being allowed to energize again
      */
      if ( (esp_timer_get_time() - PumpOnTime) >= PumpRunTime )
      {
        log_i( "pump off " );
        WaterPump0_off(); // after 5 seconds turn pump off
        pumpOn = !pumpOn;
        PumpOffWait = esp_timer_get_time();
      }
    }
    // publish to MQTT every 5000000uS
    if ( (esp_timer_get_time() - TimePastPublish) >= TimeToPublish )
    {
      xQueueOverwrite( xQ_RemainingMoistureMQTT, (void *) &RemainingMoisture );// data for mqtt publish
      TimePastPublish = esp_timer_get_time(); // get next publish time
    }
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
  }
  vTaskDelete( NULL );
}// end fDoMoistureDetector1()
////

Thank you very much, I'll try both ways.

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