Problem with onChange function and millis delays in switch

Hi as you can see I'm not an expierienced programmer,
I'm trying to control a series of relays with varying delays, for which I am using millis and a switch routine, It works perfectly as a small programm in the Arduino IDE but when I transfer it to the full programm in Cloud editor it hangs or rather only executes the first switch case. Can somebody help!
PS.- the screen comments are only temporary so that I can see if its running properly

void onShowerChange(){
    if(shower==1){  
      run_Shower();    
      //shower = 0;
    }
}

void run_Shower() {
  unsigned long previousSTime;
  unsigned long startSTime; 
  unsigned long currentSTime = millis();
  int Count = 0;
  unsigned long Run = 1; 
    
    if ((currentSTime - previousSTime) >= Run) {  
          Count++;
            switch(Count){
                case 1:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  if(filter_Active){
                    lcd.print("Filter ON"); 
                  }else{
                    lcd.print("Filter OFF");
                    }
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo ON ");
                  lcd.setCursor(0, 3);
                  lcd.print("Case 1");            
                  /*
                  digitalWrite(Relay4, LOW); //Filter Off
                  digitalWrite(Relay6, HIGH); //3 Way Trafo On
                  */
                  Run = WAIT_1Sec;
                  break;

                case 2:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("3Way Valve ON->Pump");
                  lcd.setCursor(0, 3);
                  lcd.print("Case  2"); 
                  /*
                  digitalWrite(Relay10, HIGH); //3 Way over to shower pump (Posibly) LOW???
                  */
                  //Run = WAIT_1Min;
                  Run = WAIT_1Sec;
                  break;

                case 3:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("Filter Back ON");
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump ON");                  
                  lcd.setCursor(0, 3);
                  lcd.print("Case   3");  
                  /*
                  digitalWrite(Relay4, HIGH); //Filter ON
                  digitalWrite(Relay8, HIGH); //Shower Pump ON
                  */
                  //Run = WAIT_5Min;
                  Run = WAIT_1Sec;
                  break;

                case 4:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("Filter OFF");
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump OFF");                                             
                  lcd.setCursor(0, 2);
                  lcd.print("3Way back <- Filter");
                  lcd.setCursor(0, 3);
                  lcd.print("Case    4"); 
                  /*
                  digitalWrite(Relay4, LOW); //Filter Off                  
                  digitalWrite(Relay8, LOW); //Shower Pump Off
                  digitalWrite(Relay10, LOW); //3 Way over to filter (Posibly) HIGH???
                  */
                  //Run = WAIT_1Min;
                  Run = WAIT_1Sec;
                  break;

                case 5:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("Filter Back ON");
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo OFF");  
                  lcd.setCursor(0, 3);
                  lcd.print("Case     5");        
                  /*
                  digitalWrite(Relay4, HIGH); //Filter ON                  
                  digitalWrite(Relay6, LOW); //3 Way Trafo Off
                  */
                  Run = WAIT_1Sec;
                  break;    

                default:   
                  if(Count = 5){
                   // shower = 0; 
                    break;
                  }/*else{
                  Count = 0;
                  Run = 1; 
                  }*/
            }
            previousSTime = currentSTime;  
          }
}

Hi @ardopool ,

generally for sound support posting the complete code is required ...

What's obvious in the partial code you posted is that the local variables

  unsigned long previousSTime;
  unsigned long startSTime; 
  unsigned long currentSTime = millis();
  int Count = 0;
  unsigned long Run = 1; 

will lose their content everytime after run_Shower() has been executed.

So with any new call of the function Count will be set to Zero and incremented to 1 just before the switch statement. All other cases will never be performed.

If you want the variables Count, previousSTime and startSTime to "survive" for the next function call you must declare them outside the function as global variables OR declare them inside the function as "static int" or "static unsigned long". You should also initialize all variables before usage to be sure about their content.

There may be more issues but that cannot be checked without the complete code ...

Good luck!
ec2021

Hi ec32021,
Many thanks for your input.
I've tried your changes the best that I can achieve now is to step through the switch case by case by switching the cloud switch on and off??????
Here is the complet code as you requested. I have commented out the other routines in the loop so as not to confuse.
Greatfully Nick:-)


/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled 2"
  https://create.arduino.cc/cloud/things/0fb7db16-7499-4f12-8d3b-033a81cb8d3b 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String message;
  float controller_Humid;
  float controller_Temp;
  float humidDHT2;
  float inlet_Pressure;
  float pH_sensor;
  float sensor_01;
  float sensor_02;
  float sensor_03;
  float sensor_04;
  float tempDHT2;
  CloudSchedule poolScheduleEvening;
  CloudSchedule poolScheduleMorning;
  bool filter_Active;
  bool filter_Override;
  bool humid_Warning;
  bool pool_deck;
  bool shower;
  bool sW1_PoolDeck;
  bool sW2_LowerDeck;
  bool sW3_TikiBar;
  bool sW4_Pool;
  bool uV_Reactor;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"
#include <Arduino.h>
#include "EthernetENC.h"
#include "DHT.h"
#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD
#include <OneWire.h>              //for DS18b20
#include <DallasTemperature.h>     //for DS18b20         
#include <Streaming.h>

#define DHTPin1 4
#define DHTPin2 3
#define DHTTYPE1 DHT22
#define DHTTYPE2 DHT22


LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);

DHT dht1(DHTPin1, DHTTYPE1);
DHT dht2(DHTPin2, DHTTYPE2);

// Sensor at pin 2 for DS18B20
OneWire bus(2);
DallasTemperature sensors(&bus);         //**************************

// Addresses of DS18B20s
DeviceAddress sensor_1 = { 0x28, 0xFF, 0x64, 0x1D, 0xF1, 0xC9, 0x48, 0x47 }; //Inlet:
DeviceAddress sensor_2 = { 0x28, 0xFF, 0x64, 0x1D, 0xF1, 0xF7, 0xC1, 0xA6 }; //Skimer:
DeviceAddress sensor_3 = { 0x28, 0xFF, 0x0A, 0x01, 0xA3, 0x17, 0x04, 0x8B }; //Pool Floor:
DeviceAddress sensor_4 = { 0x28, 0xFF, 0xC7, 0x1B, 0xA2, 0x17, 0x05, 0x93 }; //Filter Room:

/* As installed for the pool
Ambi = 0x28, 0x05, 0x17, 0xa2, 0x1b, 0xa7, 0xff
Filter = 0x28, 0x05, 0x17, 0xa2, 0x45, 0xbb, 0xff
Floor = 0x28, 0x01, 0x20, 0x58, 0xfe, 0x5e, 0x4a
Inlet = 0x28, 0x01, 0x20, 0x58, 0xf8, 0x4a, 0x6c
Skim = 0x28, 0x01, 0x20, 0x5b, 0xc3, 0x99, 0x9b
*/
///************Pressure**********////
int pressureInput = A3; //select the analog input pin for the pressure transducer
float V, Pin;
float P_total  = 0;

///**************PH***************///
float calibration_value = 16.61;
int phval = 0; 
unsigned long int avgval; 
int buffer_arr[10],temp;
float ph_act = 0.0;

///***************Shower Variables*******************************///
const long WAIT_1Sec = 1000; //1Sec
const long WAIT_1Min = 60000; //1Min
const long WAIT_5Min = 300000; //5Mins

static unsigned long previousSTime = 0;
static unsigned long startSTime = 0; 
unsigned long currentSTime;// = millis();
static int Count = 0;
unsigned long Run = 1; 

/*
unsigned long now;
unsigned long then = 0;
unsigned long intervals[5] = {0, 2000, 4000, 6000, 2000};
int current_interval_index = 0;
*/




int page_counter=1 ;       //To move beetwen pages
//Variables for auto scroll
unsigned long previousPagetime = 0;
unsigned long interval = 10000; //Desired wait time 10 seconds

int temp_interval = 2000; //interval between two temperature check
int temp_time_mark; //store the millis of the last temperature check

//**********************counter for loop execution*******************
const long eventTime_HumTemp = 1000; //in ms
const long eventTime_SensTemp = 1000; //in ms
const long eventTime_Press = 1000; //in ms
const long eventTime_Ph = 1000; //in ms

unsigned long previousTime_HTemp = 0;
unsigned long previousTime_Temp = 0;
unsigned long previousTime_Press = 0;
unsigned long previousTime_Ph = 0;


// Arduino Digital I/O pin numbers for UNO R3
enum {Relay1=13, Relay2=5, Relay4=6, Relay6=7, Relay8=8, Relay10=9, Relay12=10,
       Relay14=11, Relay16=12};   //*****Setting A4 & A5 looses the screen!!!!!!!!! obviously clashes with i2c connections

int relays[] = {Relay1,Relay2,Relay4,Relay6,Relay8,Relay10,Relay12,Relay14,Relay16};
// Number of relays in the array
enum { maxRelayCount = sizeof relays / sizeof relays[0] };
enum { RELAY_OFF = HIGH}; 


void dosensors(){          
  if ( millis() - temp_time_mark >= temp_interval) {
    sensors.requestTemperatures(); // Send the command to get temperatures
  }
    sensors.requestTemperatures();  
    float temp_Inlet = round(sensors.getTempC(sensor_1) * 10.0) / 10;
    float temp_Skim = round(sensors.getTempC(sensor_2) * 10.0) / 10;
    float temp_Floor = round(sensors.getTempC(sensor_3) * 10.0) / 10;
    float temp_Filter = round(sensors.getTempC(sensor_4) * 10.0) / 10;
    sensor_01 = temp_Inlet;
    sensor_02 = temp_Skim;
    sensor_03 = temp_Floor;
    sensor_04 = temp_Filter;
    delay(1000); 
}

void HumTemp(){ 
    humidDHT2 = dht1.readHumidity(); //Ambient
    tempDHT2 = dht1.readTemperature();
    controller_Humid = dht2.readHumidity(); //Controller
    controller_Temp = dht2.readTemperature();
    delay(1000);
}

void getPressure(){  
  const float  OffSet = 0.51 ;
    Pin = analogRead(0);
    V = Pin * 5.00 / 1024;     //Sensor output voltage
    inlet_Pressure = (((V - OffSet) * 250) * 0.1450377377);             //Calculate water pressure in psi
    inlet_Pressure = fabs(inlet_Pressure);
}

void getPH(){ 
   for(int i=0;i<10;i++) 
   { 
   buffer_arr[i]=analogRead(A1);
   delay(30);
   }
   for(int i=0;i<9;i++)
   {
   for(int j=i+1;j<10;j++)
   {
   if(buffer_arr[i]>buffer_arr[j])
   {
   temp=buffer_arr[i];
   buffer_arr[i]=buffer_arr[j];
   buffer_arr[j]=temp;
   }
   }
   }
   avgval=0;
   for(int i=2;i<8;i++)
   avgval+=buffer_arr[i];
   float volt=(float)avgval*5.0/1024/6;
   ph_act = -5.70 * volt + calibration_value;
   pH_sensor = ph_act;
   delay(100);
}

/* for multi tasking display*/
void display_Sensors(){
    float temp_Inlet = round(sensors.getTempC(sensor_1) * 10.0) / 10;
    float temp_Skim = round(sensors.getTempC(sensor_2) * 10.0) / 10;
    float temp_Floor = round(sensors.getTempC(sensor_3) * 10.0) / 10;
    float temp_Filter = round(sensors.getTempC(sensor_4) * 10.0) / 10;
    lcd.setCursor(0, 0);
    lcd.print("Inlet: ");
    lcd.setCursor(13, 0);
    lcd.print(temp_Inlet,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 1);
    lcd.print("Skimmer: ");
    lcd.setCursor(13, 1);
    lcd.print(temp_Skim,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 2);
    lcd.print("Floor: ");
    lcd.setCursor(13, 2);
    lcd.print(temp_Floor,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 3);
    lcd.print("Filter Room: ");
    lcd.setCursor(13, 3);
    lcd.print(temp_Filter,1);
    lcd.print((char)223); lcd.print("C"); 
}

void display_Humid(){
  lcd.setCursor(0, 0);
  lcd.print("Ambient Temp: ");
  lcd.print(tempDHT2,1);
  lcd.print(char(223));
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Ambient Hum.: ");
  lcd.print(humidDHT2,1);
  lcd.print("%");

  lcd.setCursor(0, 2);
  lcd.print("Control Temp: ");
  lcd.print(controller_Temp,1);
  lcd.print(char(223));
  lcd.print("C");

  lcd.setCursor(0, 3);
  lcd.print("Control Hum.: ");
  lcd.print(controller_Humid,1);
  lcd.print("%");
}

void display_Pressure(){
  //lcd.setCursor(0, 0);
  //lcd.print("Voltage:");
  //lcd.print(V, 3);
  //lcd.print("V");
  lcd.setCursor(5, 0);
  lcd.print("Pressure: ");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
  lcd.setCursor(6, 2);
  lcd.print(inlet_Pressure , 1);
  lcd.setCursor(9, 2);
  lcd.print(" Psi");
  lcd.setCursor(0, 3);
  lcd.print("--------------------");
}

void display_PH(){
  lcd.setCursor(6, 0);
  lcd.print("PH Val:");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
  lcd.setCursor(7, 2);
  lcd.print(pH_sensor);
  lcd.setCursor(0, 3);
  lcd.print("--------------------");
}

void setup() {
    // Defined in thingProperties.h
  initProperties();
  // Initialize serial and wait for port to open:
  
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  Serial.begin(9600);
  sensors.begin();
  dht1.begin();
  dht2.begin();
  delay(1000); 
  lcd.init();
  lcd.backlight(); 
  shower = false;

  //Set pins to OFF & declare pins as OUTPUTS
  for(int i = 0; i < maxRelayCount; ++i) {
    pinMode(relays[i], OUTPUT);
    digitalWrite(relays[i], RELAY_OFF);
  }
 // Check that all relays are inactive at Reset
   delay(1000);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}
           
void loop() {
  ArduinoCloud.update();

  unsigned long currentTime = millis();
  //currentSTime = millis();
  //now = millis();
/*
  if (currentTime - previousTime_HTemp >= eventTime_HumTemp) {
    HumTemp();
    Serial.print(controller_Temp,1);
    Serial.print(controller_Humid,1);
    Serial.print(tempDHT2,1);
    Serial.print(humidDHT2,1);
    previousTime_HTemp = currentTime;
  }

  if (currentTime - previousTime_Temp >= eventTime_SensTemp) {
    dosensors();
    Serial.print(sensor_01,0);
    Serial.print(sensor_02,0);
    Serial.print(sensor_03,0);
    Serial.print(sensor_04,0);
    previousTime_Temp = currentTime;
  }

  if (currentTime - previousTime_Press >= eventTime_Press) {
    getPressure();
    Serial.print(inlet_Pressure,2);
    previousTime_Press = currentTime;
  }

  if (currentTime - previousTime_Ph >= eventTime_Ph) {
    getPH();
    Serial.print(pH_sensor,1);
    previousTime_Ph = currentTime;
  }

  switch (page_counter) {
    case 1:{     //page 1
      display_Sensors();
    }
    break;
    case 2: { //page 2 
     display_Humid(); 
    }
    break;
    case 3: {   //page 3 
      display_Pressure();
    }
    break;
    case 4: {   //page 4
      display_PH();
    }
    break;
  }

//-----------Auto scroll function---------------//
     unsigned long currentPagetime = millis();            
     
     if (currentPagetime - previousPagetime > interval) {  
     previousPagetime = currentPagetime;                   
     lcd.clear();                                      
     if (page_counter < 4){                            
     page_counter = page_counter +1;                   
     }
     else{
      page_counter=1;                                  
     }
    } 
    
  if (poolScheduleMorning.isActive() || poolScheduleEvening.isActive()) {
    uV_Reactor = true;
    filter_Active = true;
  }else {
    uV_Reactor = false;
    filter_Active = false;
  }
 */
  ArduinoCloud.update();
   // }

}


/* ******************Not Require ****************************/

/*
  Since Message is READ_WRITE variable, onMessageChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onMessageChange()  {
  // Add your code here to act upon Message change
}

/* ******************Not Require ****************************/
/*
  Since PoolDeck is READ_WRITE variable, onPoolDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolDeckChange()  {
  // Add your code here to act upon PoolDeck change
}

/* ******************Not Require ****************************/
/*
  Since FilterOverride is READ_WRITE variable, onFilterOverrideChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onFilterOverrideChange()  {
  // Add your code here to act upon FilterOverride change
}

/* ******************Not Require ****************************/
/*
  Since PoolSchedule is READ_WRITE variable, onPoolScheduleChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleChange()  {
  // Add your code here to act upon PoolSchedule change
  
/*
  Since PoolScheduleMorning is READ_WRITE variable, onPoolScheduleMorningChange() is
  executed every time a new value is received from IoT Cloud.

void onPoolScheduleMorningChange()  {
  // Add your code here to act upon PoolScheduleMorning change
}*/  
  
  
}
/*******************************************************************************/

/*
  Since SW1PoolDeck is READ_WRITE variable, onSW1PoolDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW1PoolDeckChange()  {
  // Add your code here to act upon SW1PoolDeck change
    if (sW1_PoolDeck == 1) {
      digitalWrite(Relay12, HIGH);
    } 
    else {
      digitalWrite(Relay12, LOW);
    }
}

/*
  Since SW2LowerDeck is READ_WRITE variable, onSW2LowerDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW2LowerDeckChange()  {
  // Add your code here to act upon SW2LowerDeck change
      if (sW2_LowerDeck == 1) {
      digitalWrite(Relay14, HIGH);
    } 
    else {
      digitalWrite(Relay14, LOW);
    }
}

/*
  Since SW3TikiBar is READ_WRITE variable, onSW3TikiBarChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW3TikiBarChange()  {
  // Add your code here to act upon SW3TikiBar change
    if (sW3_TikiBar == 1) {
      digitalWrite(Relay16, HIGH);
    } 
    else {
      digitalWrite(Relay16, LOW);
    }
}

/*
  Since SW4Pool is READ_WRITE variable, onSW4PoolChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW4PoolChange()  {
  // Add your code here to act upon SW4Pool change
  if (sW4_Pool == 1) {
      digitalWrite(Relay1, HIGH);
    } 
    else {
      digitalWrite(Relay1, LOW);
    }
}


/*
  Since Shower is READ_WRITE variable, onShowerChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onShowerChange(){
    if(shower==1){  
      run_Shower();    
    }
}

void run_Shower() {
  currentSTime = millis();
    if ((currentSTime - previousSTime) >= Run) {  
          Count++;
            switch(Count){
                case 1:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  if(filter_Active){
                    lcd.print("Filter active turn Off"); 
                  }else{
                    lcd.print("Filter not active");
                    }
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo ON ");
                  lcd.setCursor(0, 3);
                  lcd.print("Case 1");            
                  /*
                  digitalWrite(Relay4, LOW); //Filter Off
                  digitalWrite(Relay6, HIGH); //3 Way Trafo On
                  */
                  Run = WAIT_1Sec;
                  break;

                case 2:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("3Way Valve ON->Pump");
                  lcd.setCursor(0, 3);
                  lcd.print("Case  2"); 
                  /*
                  digitalWrite(Relay10, HIGH); //3 Way over to shower pump (Posibly) LOW???
                  */
                  //Run = WAIT_1Min;
                  Run = WAIT_1Sec;
                  break;

                case 3:
                  lcd.clear();
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter back ON"); 
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump ON");                  
                  lcd.setCursor(0, 3);
                  lcd.print("Case   3");  
                  /*
                  digitalWrite(Relay4, HIGH); //Filter ON
                  digitalWrite(Relay8, HIGH); //Shower Pump ON
                  */
                  //Run = WAIT_5Min;
                  Run = WAIT_1Sec;
                  break;

                case 4:
                  lcd.clear();
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter Off"); 
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump OFF");                                             
                  lcd.setCursor(0, 2);
                  lcd.print("3Way back <- Filter");
                  lcd.setCursor(0, 3);
                  lcd.print("Case    4"); 
                  /*
                  digitalWrite(Relay4, LOW); //Filter Off                  
                  digitalWrite(Relay8, LOW); //Shower Pump Off
                  digitalWrite(Relay10, LOW); //3 Way over to filter (Posibly) HIGH???
                  */
                  //Run = WAIT_1Min;
                  Run = WAIT_1Sec;
                  break;

                case 5:
                  lcd.clear();
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter back ON"); 
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo OFF");  
                  lcd.setCursor(0, 3);
                  lcd.print("Case     5");        
                  /*
                  digitalWrite(Relay4, HIGH); //Filter ON                  
                  digitalWrite(Relay6, LOW); //3 Way Trafo Off
                  */
                  Run = WAIT_1Sec;
                  break;    

                default:   
                  if(Count = 5){
                    shower = 0; //Turn cloud switch back to OFF
                    Count = 0;
                    Run = 0;
                    //break;
                  }
            }
            //previousSTime = currentSTime;  
          }
}


/*
  Since PoolScheduleMorning is READ_WRITE variable, onPoolScheduleMorningChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleMorningChange(){
  // Add your code here to act upon PoolScheduleMorning change
  if (poolScheduleMorning.isActive()) {
    digitalWrite(Relay4, HIGH);
    digitalWrite(Relay2, HIGH);
    } else {
      digitalWrite(Relay4, LOW);
      digitalWrite(Relay2, LOW);
    }
}

/*
  Since PoolScheduleEvening is READ_WRITE variable, onPoolScheduleEveningChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleEveningChange() {
  // Add your code here to act upon PoolScheduleEvening change
  if (poolScheduleEvening.isActive()) {
    digitalWrite(Relay4, HIGH);
    digitalWrite(Relay2, HIGH);
    } else {
      digitalWrite(Relay4, LOW);
      digitalWrite(Relay2, LOW);
    }
  }










Hi @ardopool.

This is what your code is expected to do. As the comment says:

The ArduinoCloud.update() function will call the onShowerChange function if the value of the shower Cloud Variable has been changed from the Arduino Cloud dashboard. That is the only time it will call the onShowerChange function.

Maybe you have the impression that the onShowerChange function will also be called automatically after the value of the shower variable is changed internally by the sketch program? This is not so.

Hi ptillisch,
Thankyou, thankyou, thankyou, I gave your comment some thought and moved the 3 liner from "onShowerChange" to loop, now (after days or even weeks) it works perfectly :nerd_face:
Nick

PS: I'm open to any sudjestions to improve the code

You are welcome. I'm glad it is working now.

You should post your updated code so that the forum helpers can make more relevant suggestions.

Glad it works now thanks to @ptillisch!

And you see how relevant it was to post the complete sketch :wink:

Please do not forget to mark @ptillisch ' s post as the solution!

Good luck and have fun with Arduino!

ec2021

Hi attached the working code although I have just noticed that I might have a problem with the filter turning back on before it should . I will try and find the reason!

void run_Shower() {
    if ((currentSTime - previousSTime) >= Run) {  
          Count++;
            switch(Count){
                case 1:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  if(filter_Active){
                    lcd.print("Filter active turn Off"); 
                    digitalWrite(Relay4, HIGH); //Filter Off     <----------this apears to be turning on to soon

Any way here is the complete and nearly working code as requested:


/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled 2"
  https://create.arduino.cc/cloud/things/0fb7db16-7499-4f12-8d3b-033a81cb8d3b 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String message;
  float controller_Humid;
  float controller_Temp;
  float humidDHT2;
  float inlet_Pressure;
  float pH_sensor;
  float sensor_01;
  float sensor_02;
  float sensor_03;
  float sensor_04;
  float tempDHT2;
  CloudSchedule poolScheduleEvening;
  CloudSchedule poolScheduleMorning;
  bool filter_Active;
  bool filter_Override;
  bool humid_Warning;
  bool pool_deck;
  bool shower;
  bool sW1_PoolDeck;
  bool sW2_LowerDeck;
  bool sW3_TikiBar;
  bool sW4_Pool;
  bool uV_Reactor;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"
#include <Arduino.h>
#include "EthernetENC.h"
#include "DHT.h"
#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD
#include <OneWire.h>              //for DS18b20
#include <DallasTemperature.h>     //for DS18b20         
#include <Streaming.h>

#define DHTPin1 4
#define DHTPin2 3
#define DHTTYPE1 DHT22
#define DHTTYPE2 DHT22


LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);

DHT dht1(DHTPin1, DHTTYPE1);
DHT dht2(DHTPin2, DHTTYPE2);

// Sensor at pin 2 for DS18B20
OneWire bus(2);
DallasTemperature sensors(&bus);         //**************************

// Addresses of DS18B20s
DeviceAddress sensor_1 = { 0x28, 0xFF, 0x64, 0x1D, 0xF1, 0xC9, 0x48, 0x47 }; //Inlet:
DeviceAddress sensor_2 = { 0x28, 0xFF, 0x64, 0x1D, 0xF1, 0xF7, 0xC1, 0xA6 }; //Skimer:
DeviceAddress sensor_3 = { 0x28, 0xFF, 0x0A, 0x01, 0xA3, 0x17, 0x04, 0x8B }; //Pool Floor:
DeviceAddress sensor_4 = { 0x28, 0xFF, 0xC7, 0x1B, 0xA2, 0x17, 0x05, 0x93 }; //Filter Room:

/* As installed for the pool
Ambi = 0x28, 0x05, 0x17, 0xa2, 0x1b, 0xa7, 0xff
Filter = 0x28, 0x05, 0x17, 0xa2, 0x45, 0xbb, 0xff
Floor = 0x28, 0x01, 0x20, 0x58, 0xfe, 0x5e, 0x4a
Inlet = 0x28, 0x01, 0x20, 0x58, 0xf8, 0x4a, 0x6c
Skim = 0x28, 0x01, 0x20, 0x5b, 0xc3, 0x99, 0x9b
*/
///************Pressure**********////
int pressureInput = A3; //select the analog input pin for the pressure transducer
float V, Pin;
float P_total  = 0;

///**************PH***************///
float calibration_value = 16.61;
int phval = 0; 
unsigned long int avgval; 
int buffer_arr[10],temp;
float ph_act = 0.0;

///***************Shower Variables*******************************///
const long WAIT_1Sec = 1000; //1Sec
const long WAIT_1Min = 60000; //1Min
const long WAIT_5Min = 300000; //5Mins

static unsigned long previousSTime = 0;
static unsigned long startSTime = 0; 
static unsigned long currentSTime;// = millis();
static int Count = 0;
unsigned long Run = 1; 


int page_counter=1 ;       //To move beetwen pages
//Variables for auto scroll
unsigned long previousPagetime = 0;
unsigned long interval = 10000; //Desired wait time 10 seconds

int temp_interval = 2000; //interval between two temperature check
int temp_time_mark; //store the millis of the last temperature check

//**********************counter for loop execution*******************
const long eventTime_HumTemp = 1000; //in ms
const long eventTime_SensTemp = 1000; //in ms
const long eventTime_Press = 1000; //in ms
const long eventTime_Ph = 1000; //in ms

unsigned long previousTime_HTemp = 0;
unsigned long previousTime_Temp = 0;
unsigned long previousTime_Press = 0;
unsigned long previousTime_Ph = 0;


// Arduino Digital I/O pin numbers for UNO R3
enum {Relay1=13, Relay2=5, Relay4=6, Relay6=7, Relay8=8, Relay10=9, Relay12=10,
       Relay14=11, Relay16=12};   //*****Setting A4 & A5 looses the screen!!!!!!!!! obviously clashes with i2c connections

int relays[] = {Relay1,Relay2,Relay4,Relay6,Relay8,Relay10,Relay12,Relay14,Relay16};
// Number of relays in the array
enum { maxRelayCount = sizeof relays / sizeof relays[0] };
enum { RELAY_OFF = HIGH}; 


void dosensors(){          
  if ( millis() - temp_time_mark >= temp_interval) {
    sensors.requestTemperatures(); // Send the command to get temperatures
  }
    sensors.requestTemperatures();  
    float temp_Inlet = round(sensors.getTempC(sensor_1) * 10.0) / 10;
    float temp_Skim = round(sensors.getTempC(sensor_2) * 10.0) / 10;
    float temp_Floor = round(sensors.getTempC(sensor_3) * 10.0) / 10;
    float temp_Filter = round(sensors.getTempC(sensor_4) * 10.0) / 10;
    sensor_01 = temp_Inlet;
    sensor_02 = temp_Skim;
    sensor_03 = temp_Floor;
    sensor_04 = temp_Filter;
    delay(1000); 
}

void HumTemp(){ 
    humidDHT2 = dht1.readHumidity(); //Ambient
    tempDHT2 = dht1.readTemperature();
    controller_Humid = dht2.readHumidity(); //Controller
    controller_Temp = dht2.readTemperature();
    delay(1000);
}

void getPressure(){  
  const float  OffSet = 0.51 ;
    Pin = analogRead(0);
    V = Pin * 5.00 / 1024;     //Sensor output voltage
    inlet_Pressure = (((V - OffSet) * 250) * 0.1450377377);             //Calculate water pressure in psi
    inlet_Pressure = fabs(inlet_Pressure);
}

void getPH(){ 
   for(int i=0;i<10;i++) 
   { 
   buffer_arr[i]=analogRead(A1);
   delay(30);
   }
   for(int i=0;i<9;i++)
   {
   for(int j=i+1;j<10;j++)
   {
   if(buffer_arr[i]>buffer_arr[j])
   {
   temp=buffer_arr[i];
   buffer_arr[i]=buffer_arr[j];
   buffer_arr[j]=temp;
   }
   }
   }
   avgval=0;
   for(int i=2;i<8;i++)
   avgval+=buffer_arr[i];
   float volt=(float)avgval*5.0/1024/6;
   ph_act = -5.70 * volt + calibration_value;
   pH_sensor = ph_act;
   delay(100);
}

/* for multi tasking display*/
void display_Sensors(){
    float temp_Inlet = round(sensors.getTempC(sensor_1) * 10.0) / 10;
    float temp_Skim = round(sensors.getTempC(sensor_2) * 10.0) / 10;
    float temp_Floor = round(sensors.getTempC(sensor_3) * 10.0) / 10;
    float temp_Filter = round(sensors.getTempC(sensor_4) * 10.0) / 10;
    lcd.setCursor(0, 0);
    lcd.print("Inlet: ");
    lcd.setCursor(13, 0);
    lcd.print(temp_Inlet,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 1);
    lcd.print("Skimmer: ");
    lcd.setCursor(13, 1);
    lcd.print(temp_Skim,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 2);
    lcd.print("Floor: ");
    lcd.setCursor(13, 2);
    lcd.print(temp_Floor,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 3);
    lcd.print("Filter Room: ");
    lcd.setCursor(13, 3);
    lcd.print(temp_Filter,1);
    lcd.print((char)223); lcd.print("C"); 
}

void display_Humid(){
  lcd.setCursor(0, 0);
  lcd.print("Ambient Temp: ");
  lcd.print(tempDHT2,1);
  lcd.print(char(223));
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Ambient Hum.: ");
  lcd.print(humidDHT2,1);
  lcd.print("%");

  lcd.setCursor(0, 2);
  lcd.print("Control Temp: ");
  lcd.print(controller_Temp,1);
  lcd.print(char(223));
  lcd.print("C");

  lcd.setCursor(0, 3);
  lcd.print("Control Hum.: ");
  lcd.print(controller_Humid,1);
  lcd.print("%");
}

void display_Pressure(){
  //lcd.setCursor(0, 0);
  //lcd.print("Voltage:");
  //lcd.print(V, 3);
  //lcd.print("V");
  lcd.setCursor(5, 0);
  lcd.print("Pressure: ");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
  lcd.setCursor(6, 2);
  lcd.print(inlet_Pressure , 1);
  lcd.setCursor(9, 2);
  lcd.print(" Psi");
  lcd.setCursor(0, 3);
  lcd.print("--------------------");
}

void display_PH(){
  lcd.setCursor(6, 0);
  lcd.print("PH Val:");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
  lcd.setCursor(7, 2);
  lcd.print(pH_sensor);
  lcd.setCursor(0, 3);
  lcd.print("--------------------");
}

void setup() {
    // Defined in thingProperties.h
  initProperties();
  // Initialize serial and wait for port to open:
  
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  Serial.begin(9600);
  sensors.begin();
  dht1.begin();
  dht2.begin();
  delay(1000); 
  lcd.init();
  lcd.backlight(); 
  shower = 0;

  //Set pins to OFF & declare pins as OUTPUTS
  for(int i = 0; i < maxRelayCount; ++i) {
    pinMode(relays[i], OUTPUT);
    digitalWrite(relays[i], RELAY_OFF);
  }
 // Check that all relays are inactive at Reset
   delay(1000);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}
           
void loop() {
  ArduinoCloud.update();

  unsigned long currentTime = millis();
  currentSTime = millis();
  //now = millis();
  runUvFilter();
  if(shower==1){       
    run_Shower();    
  }

  if (currentTime - previousTime_HTemp >= eventTime_HumTemp) {
    HumTemp();
    Serial.print(controller_Temp,1);
    Serial.print(controller_Humid,1);
    Serial.print(tempDHT2,1);
    Serial.print(humidDHT2,1);
    previousTime_HTemp = currentTime;
  }

  if (currentTime - previousTime_Temp >= eventTime_SensTemp) {
    dosensors();
    Serial.print(sensor_01,0);
    Serial.print(sensor_02,0);
    Serial.print(sensor_03,0);
    Serial.print(sensor_04,0);
    previousTime_Temp = currentTime;
  }

  if (currentTime - previousTime_Press >= eventTime_Press) {
    getPressure();
    Serial.print(inlet_Pressure,2);
    previousTime_Press = currentTime;
  }

  if (currentTime - previousTime_Ph >= eventTime_Ph) {
    getPH();
    Serial.print(pH_sensor,1);
    previousTime_Ph = currentTime;
  }

  switch (page_counter) {
    case 1:{     //page 1
      display_Sensors();
    }
    break;
    case 2: { //page 2 
     display_Humid(); 
    }
    break;
    case 3: {   //page 3 
      display_Pressure();
    }
    break;
    case 4: {   //page 4
      display_PH();
    }
    break;
  }

//-----------Auto scroll function---------------//
     unsigned long currentPagetime = millis();            
     
     if (currentPagetime - previousPagetime > interval) {  
     previousPagetime = currentPagetime;                   
     lcd.clear();                                      
     if (page_counter < 4){                            
     page_counter = page_counter +1;                   
     }
     else{
      page_counter=1;                                  
     }
    } 
/*    
  if (poolScheduleMorning.isActive() || poolScheduleEvening.isActive()) {
    uV_Reactor = true;
    filter_Active = true;
  }else {
    uV_Reactor = false;
    filter_Active = false;
  }
*/ 
  ArduinoCloud.update();
    //}

}


/* ******************Not Require ****************************/

/*
  Since Message is READ_WRITE variable, onMessageChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onMessageChange()  {
  // Add your code here to act upon Message change
}

/* ******************Not Require ****************************/
/*
  Since PoolDeck is READ_WRITE variable, onPoolDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolDeckChange()  {
  // Add your code here to act upon PoolDeck change
}

/* ******************Not Require ****************************/
/*
  Since FilterOverride is READ_WRITE variable, onFilterOverrideChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onFilterOverrideChange()  {
  // Add your code here to act upon FilterOverride change
}

/* ******************Not Require ****************************/
/*
  Since PoolSchedule is READ_WRITE variable, onPoolScheduleChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleChange()  {
  // Add your code here to act upon PoolSchedule change
  
/*
  Since PoolScheduleMorning is READ_WRITE variable, onPoolScheduleMorningChange() is
  executed every time a new value is received from IoT Cloud.

void onPoolScheduleMorningChange()  {
  // Add your code here to act upon PoolScheduleMorning change
}*/  
  
  
}
/*******************************************************************************/

/*
  Since SW1PoolDeck is READ_WRITE variable, onSW1PoolDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW1PoolDeckChange()  {
  // Add your code here to act upon SW1PoolDeck change
    if (sW1_PoolDeck == 1) {
      digitalWrite(Relay12, LOW);
    } 
    else {
      digitalWrite(Relay12, HIGH);
    }
}

/*
  Since SW2LowerDeck is READ_WRITE variable, onSW2LowerDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW2LowerDeckChange()  {
  // Add your code here to act upon SW2LowerDeck change
      if (sW2_LowerDeck == 1) {
      digitalWrite(Relay14, LOW);
    } 
    else {
      digitalWrite(Relay14, HIGH);
    }
}

/*
  Since SW3TikiBar is READ_WRITE variable, onSW3TikiBarChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW3TikiBarChange()  {
  // Add your code here to act upon SW3TikiBar change
    if (sW3_TikiBar == 1) {
      digitalWrite(Relay16, LOW);
    } 
    else {
      digitalWrite(Relay16, HIGH);
    }
}

/*
  Since SW4Pool is READ_WRITE variable, onSW4PoolChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW4PoolChange()  {
  // Add your code here to act upon SW4Pool change
  if (sW4_Pool == 1) {
      digitalWrite(Relay1, LOW);
    } 
    else {
      digitalWrite(Relay1, HIGH);
    }
}


/*
  Since Shower is READ_WRITE variable, onShowerChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onShowerChange(){
}

void run_Shower() {
    if ((currentSTime - previousSTime) >= Run) {  
          Count++;
            switch(Count){
                case 1:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  if(filter_Active){
                    lcd.print("Filter active turn Off"); 
                    digitalWrite(Relay4, HIGH); //Filter Off
                  }else{
                    lcd.print("Filter not active");
                    }
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo ON ");
                  lcd.setCursor(0, 3);
                  lcd.print("Case 1");                              
                  digitalWrite(Relay6, LOW); //3 Way Trafo On                  
                  Run = WAIT_1Sec;
                  break;

                case 2:
                  lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("3Way Valve ON->Pump");
                  lcd.setCursor(0, 3);
                  lcd.print("Case  2");                   
                  digitalWrite(Relay10, LOW); //3 Way over to shower pump (Posibly) LOW???                  
                  Run = WAIT_1Min;
                  break;

                case 3:
                  lcd.clear();
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter back ON");
                    digitalWrite(Relay4, LOW); //Filter ON
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump ON");                  
                  lcd.setCursor(0, 3);
                  lcd.print("Case   3");                    
                  digitalWrite(Relay8, LOW); //Shower Pump ON                  
                  Run = WAIT_5Min;
                  break;

                case 4:
                  lcd.clear();
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter Off"); 
                    digitalWrite(Relay4, HIGH); //Filter Off                      
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump OFF");                                             
                  lcd.setCursor(0, 2);
                  lcd.print("3Way back <- Filter");
                  lcd.setCursor(0, 3);
                  lcd.print("Case    4");                                   
                  digitalWrite(Relay8, HIGH); //Shower Pump Off
                  digitalWrite(Relay10, HIGH); //3 Way over to filter (Posibly) HIGH???                  
                  Run = WAIT_1Min;
                  break;

                case 5:
                  lcd.clear();
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter back ON"); 
                    digitalWrite(Relay4, LOW); //Filter ON 
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo OFF");  
                  lcd.setCursor(0, 3);
                  lcd.print("Case     5");                         
                  digitalWrite(Relay6, HIGH); //3 Way Trafo Off                  
                  Run = WAIT_1Sec;
                  break;    

                default:   
                  if(Count = 5){
                    shower = 0; //Turn cloud switch back to OFF
                    Count = 0;
                    Run = 1;
                    break;
                  }
            }
            previousSTime = currentSTime;  
          }
}


/*
  Since PoolScheduleMorning is READ_WRITE variable, onPoolScheduleMorningChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleMorningChange(){
  // Add your code here to act upon PoolScheduleMorning change
}

/*
  Since PoolScheduleEvening is READ_WRITE variable, onPoolScheduleEveningChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleEveningChange() {
  // Add your code here to act upon PoolScheduleEvening change
  }

void runUvFilter(){
   if (poolScheduleMorning.isActive()||poolScheduleEvening.isActive()) {
    digitalWrite(Relay4, LOW); //Is On
    digitalWrite(Relay2, LOW);
    uV_Reactor = true;
    filter_Active = true;
    } else {
      digitalWrite(Relay4, HIGH);//Is OFF
      digitalWrite(Relay2, HIGH);
      uV_Reactor = false;
      filter_Active = false;
    }   
}







The condition in this if statement will always evaluate as true. The reason is that you used the assignment operator (=) instead of the comparison operator (==). This has the side effect of setting the value of Count to 5, which is surely not what was intended, but happens to not cause a problem in this program because you later set it to 0 as intended:

Beyond the inappropriate operator, the value in the condition is also wrong. This default case can never be reached when Count has a value of 5 because you have an explicit case for that value:

Even though you could "fix" it by changing the condition to Count == 6, I would suggest instead to use an explicit case for that value and removing the conditional entirely:

                case 6:

In a state machine type of use case as you have here, the default case would typically only ever be used if the programmer wanted to add a safety mechanism to handle a condition that should never occur if the program is working as intended. You could do something like this:

                default:
                  Serial.print("Error: Unexpected value of Count: ");
                  Serial.println(Count);

Wow I wasn't expecting that!
Ok I'll have a look, Thanks

HI ptillisch,
Thanks for all your help and not to forget ec2021 it all runs perfectly now, obviously there's room for improvment but I'm happy with the results for now. In the mean time I've added a variable for the shower run time. Attached the working code:


/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled 2"
  https://create.arduino.cc/cloud/things/0fb7db16-7499-4f12-8d3b-033a81cb8d3b 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String message;
  float controller_Humid;
  float controller_Temp;
  float humidDHT2;
  float inlet_Pressure;
  float pH_sensor;
  float sensor_01;
  float sensor_02;
  float sensor_03;
  float sensor_04;
  float tempDHT2;
  int showerTime;
  CloudSchedule poolScheduleEvening;
  CloudSchedule poolScheduleMorning;
  bool filter_Active;
  bool filter_Override;
  bool humid_Warning;
  bool pool_deck;
  bool shower;
  bool sW1_PoolDeck;
  bool sW2_LowerDeck;
  bool sW3_TikiBar;
  bool sW4_Pool;
  bool uV_Reactor;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"
#include <Arduino.h>
#include "EthernetENC.h"
#include "DHT.h"
#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD
#include <OneWire.h>              //for DS18b20
#include <DallasTemperature.h>     //for DS18b20         
#include <Streaming.h>

#define DHTPin1 4
#define DHTPin2 3
#define DHTTYPE1 DHT22
#define DHTTYPE2 DHT22


LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);

DHT dht1(DHTPin1, DHTTYPE1);
DHT dht2(DHTPin2, DHTTYPE2);

// Sensor at pin 2 for DS18B20
OneWire bus(2);
DallasTemperature sensors(&bus);         //**************************

// Addresses of DS18B20s
DeviceAddress sensor_1 = { 0x28, 0xFF, 0x64, 0x1D, 0xF1, 0xC9, 0x48, 0x47 }; //Inlet:
DeviceAddress sensor_2 = { 0x28, 0xFF, 0x64, 0x1D, 0xF1, 0xF7, 0xC1, 0xA6 }; //Skimer:
DeviceAddress sensor_3 = { 0x28, 0xFF, 0x0A, 0x01, 0xA3, 0x17, 0x04, 0x8B }; //Pool Floor:
DeviceAddress sensor_4 = { 0x28, 0xFF, 0xC7, 0x1B, 0xA2, 0x17, 0x05, 0x93 }; //Filter Room:

/* As installed for the pool
Ambi = 0x28, 0x05, 0x17, 0xa2, 0x1b, 0xa7, 0xff
Filter = 0x28, 0x05, 0x17, 0xa2, 0x45, 0xbb, 0xff
Floor = 0x28, 0x01, 0x20, 0x58, 0xfe, 0x5e, 0x4a
Inlet = 0x28, 0x01, 0x20, 0x58, 0xf8, 0x4a, 0x6c
Skim = 0x28, 0x01, 0x20, 0x5b, 0xc3, 0x99, 0x9b
*/
///************Pressure**********////
int pressureInput = A3; //select the analog input pin for the pressure transducer
float V, Pin;
float P_total  = 0;

///**************PH***************///
float calibration_value = 16.61;
int phval = 0; 
unsigned long int avgval; 
int buffer_arr[10],temp;
float ph_act = 0.0;

///***************Shower Variables*******************************///
const long WAIT_1Sec = 1000; //1Sec
const long WAIT_1Min = 60000; //1Min
const long WAIT_5Min = 300000; //5Mins
long newRun = 0;

static unsigned long previousSTime = 0;
static unsigned long startSTime = 0; 
static unsigned long currentSTime;// = millis();
static int Count = 0;
unsigned long Run = 1; 


int page_counter=1 ;       //To move beetwen pages
//Variables for auto scroll
unsigned long previousPagetime = 0;
unsigned long interval = 10000; //Desired wait time 10 seconds

int temp_interval = 2000; //interval between two temperature check
int temp_time_mark; //store the millis of the last temperature check

//**********************counter for loop execution*******************
const long eventTime_HumTemp = 1000; //in ms
const long eventTime_SensTemp = 1000; //in ms
const long eventTime_Press = 1000; //in ms
const long eventTime_Ph = 1000; //in ms

unsigned long previousTime_HTemp = 0;
unsigned long previousTime_Temp = 0;
unsigned long previousTime_Press = 0;
unsigned long previousTime_Ph = 0;


// Arduino Digital I/O pin numbers for UNO R3
enum {Relay1=13, Relay2=5, Relay4=6, Relay6=7, Relay8=8, Relay10=9, Relay12=10,
       Relay14=11, Relay16=12};   //*****Setting A4 & A5 looses the screen!!!!!!!!! obviously clashes with i2c connections

int relays[] = {Relay1,Relay2,Relay4,Relay6,Relay8,Relay10,Relay12,Relay14,Relay16};
// Number of relays in the array
enum { maxRelayCount = sizeof relays / sizeof relays[0] };
enum { RELAY_OFF = HIGH}; 


void dosensors(){          
  if ( millis() - temp_time_mark >= temp_interval) {
    sensors.requestTemperatures(); // Send the command to get temperatures
  }
    sensors.requestTemperatures();  
    float temp_Inlet = round(sensors.getTempC(sensor_1) * 10.0) / 10;
    float temp_Skim = round(sensors.getTempC(sensor_2) * 10.0) / 10;
    float temp_Floor = round(sensors.getTempC(sensor_3) * 10.0) / 10;
    float temp_Filter = round(sensors.getTempC(sensor_4) * 10.0) / 10;
    sensor_01 = temp_Inlet;
    sensor_02 = temp_Skim;
    sensor_03 = temp_Floor;
    sensor_04 = temp_Filter;
    delay(1000); 
}

void HumTemp(){ 
    humidDHT2 = dht1.readHumidity(); //Ambient
    tempDHT2 = dht1.readTemperature();
    controller_Humid = dht2.readHumidity(); //Controller
    controller_Temp = dht2.readTemperature();
    delay(1000);
}

void getPressure(){  
  const float  OffSet = 0.51 ;
    Pin = analogRead(0);
    V = Pin * 5.00 / 1024;     //Sensor output voltage
    inlet_Pressure = (((V - OffSet) * 250) * 0.1450377377);             //Calculate water pressure in psi
    inlet_Pressure = fabs(inlet_Pressure);
}

void getPH(){ 
   for(int i=0;i<10;i++) 
   { 
   buffer_arr[i]=analogRead(A1);
   delay(30);
   }
   for(int i=0;i<9;i++)
   {
   for(int j=i+1;j<10;j++)
   {
   if(buffer_arr[i]>buffer_arr[j])
   {
   temp=buffer_arr[i];
   buffer_arr[i]=buffer_arr[j];
   buffer_arr[j]=temp;
   }
   }
   }
   avgval=0;
   for(int i=2;i<8;i++)
   avgval+=buffer_arr[i];
   float volt=(float)avgval*5.0/1024/6;
   ph_act = -5.70 * volt + calibration_value;
   pH_sensor = ph_act;
   delay(100);
}

/* for multi tasking display*/
void display_Sensors(){
    float temp_Inlet = round(sensors.getTempC(sensor_1) * 10.0) / 10;
    float temp_Skim = round(sensors.getTempC(sensor_2) * 10.0) / 10;
    float temp_Floor = round(sensors.getTempC(sensor_3) * 10.0) / 10;
    float temp_Filter = round(sensors.getTempC(sensor_4) * 10.0) / 10;
    lcd.setCursor(0, 0);
    lcd.print("Inlet: ");
    lcd.setCursor(13, 0);
    lcd.print(temp_Inlet,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 1);
    lcd.print("Skimmer: ");
    lcd.setCursor(13, 1);
    lcd.print(temp_Skim,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 2);
    lcd.print("Floor: ");
    lcd.setCursor(13, 2);
    lcd.print(temp_Floor,1);
    lcd.print((char)223); lcd.print("C");  
    lcd.setCursor(0, 3);
    lcd.print("Filter Room: ");
    lcd.setCursor(13, 3);
    lcd.print(temp_Filter,1);
    lcd.print((char)223); lcd.print("C"); 
}

void display_Humid(){
  lcd.setCursor(0, 0);
  lcd.print("Ambient Temp: ");
  lcd.print(tempDHT2,1);
  lcd.print(char(223));
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Ambient Hum.: ");
  lcd.print(humidDHT2,1);
  lcd.print("%");

  lcd.setCursor(0, 2);
  lcd.print("Control Temp: ");
  lcd.print(controller_Temp,1);
  lcd.print(char(223));
  lcd.print("C");

  lcd.setCursor(0, 3);
  lcd.print("Control Hum.: ");
  lcd.print(controller_Humid,1);
  lcd.print("%");
}

void display_Pressure(){
  //lcd.setCursor(0, 0);
  //lcd.print("Voltage:");
  //lcd.print(V, 3);
  //lcd.print("V");
  lcd.setCursor(5, 0);
  lcd.print("Pressure: ");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
  lcd.setCursor(6, 2);
  lcd.print(inlet_Pressure , 1);
  lcd.setCursor(9, 2);
  lcd.print(" Psi");
  lcd.setCursor(0, 3);
  lcd.print("--------------------");
}

void display_PH(){
  lcd.setCursor(6, 0);
  lcd.print("PH Val:");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
  lcd.setCursor(7, 2);
  lcd.print(pH_sensor);
  lcd.setCursor(0, 3);
  lcd.print("--------------------");
}

void setup() {
    // Defined in thingProperties.h
  initProperties();
  // Initialize serial and wait for port to open:
  
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  Serial.begin(9600);
  sensors.begin();
  dht1.begin();
  dht2.begin();
  delay(1000); 
  lcd.init();
  lcd.backlight(); 
  shower = 0;

  //Set pins to OFF & declare pins as OUTPUTS
  for(int i = 0; i < maxRelayCount; ++i) {
    pinMode(relays[i], OUTPUT);
    digitalWrite(relays[i], RELAY_OFF);
  }
 // Check that all relays are inactive at Reset
   delay(1000);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}
           
void loop() {
  ArduinoCloud.update();

  unsigned long currentTime = millis();
  currentSTime = millis();

  runUvFilter();
  if(shower==1){       
    run_Shower();    
  }

  if (currentTime - previousTime_HTemp >= eventTime_HumTemp) {
    HumTemp();
    Serial.print(controller_Temp,1);
    Serial.print(controller_Humid,1);
    Serial.print(tempDHT2,1);
    Serial.print(humidDHT2,1);
    previousTime_HTemp = currentTime;
  }

  if (currentTime - previousTime_Temp >= eventTime_SensTemp) {
    dosensors();
    Serial.print(sensor_01,0);
    Serial.print(sensor_02,0);
    Serial.print(sensor_03,0);
    Serial.print(sensor_04,0);
    previousTime_Temp = currentTime;
  }

  if (currentTime - previousTime_Press >= eventTime_Press) {
    getPressure();
    Serial.print(inlet_Pressure,2);
    previousTime_Press = currentTime;
  }

  if (currentTime - previousTime_Ph >= eventTime_Ph) {
    getPH();
    Serial.print(pH_sensor,1);
    previousTime_Ph = currentTime;
  }

  switch (page_counter) {
    case 1:{     //page 1
      display_Sensors();
    }
    break;
    case 2: { //page 2 
     display_Humid(); 
    }
    break;
    case 3: {   //page 3 
      display_Pressure();
    }
    break;
    case 4: {   //page 4
      display_PH();
    }
    break;
  }

//-----------Auto scroll function---------------//
     unsigned long currentPagetime = millis();            
     
     if (currentPagetime - previousPagetime > interval) {  
     previousPagetime = currentPagetime;                   
     lcd.clear();                                      
     if (page_counter < 4){                            
     page_counter = page_counter +1;                   
     }
     else{
      page_counter=1;                                  
     }
    } 
 
  ArduinoCloud.update();
  
}


/* ******************Not Require ****************************/

/*
  Since Message is READ_WRITE variable, onMessageChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onMessageChange()  {
  // Add your code here to act upon Message change
}

/* ******************Not Require ****************************/
/*
  Since PoolDeck is READ_WRITE variable, onPoolDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolDeckChange()  {
  // Add your code here to act upon PoolDeck change
}

/* ******************Not Require ****************************/
/*
  Since FilterOverride is READ_WRITE variable, onFilterOverrideChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onFilterOverrideChange()  {
  // Add your code here to act upon FilterOverride change
}

/* ******************Not Require ****************************/
/*
  Since PoolSchedule is READ_WRITE variable, onPoolScheduleChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleChange()  {
  // Add your code here to act upon PoolSchedule change
}
/*
  Since PoolScheduleMorning is READ_WRITE variable, onPoolScheduleMorningChange() is
  executed every time a new value is received from IoT Cloud.

void onPoolScheduleMorningChange()  {
  // Add your code here to act upon PoolScheduleMorning change
}  */
  
  

/*******************************************************************************/

/*
  Since SW1PoolDeck is READ_WRITE variable, onSW1PoolDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW1PoolDeckChange()  {
  // Add your code here to act upon SW1PoolDeck change
    if (sW1_PoolDeck == 1) {
      digitalWrite(Relay12, LOW);
    } 
    else {
      digitalWrite(Relay12, HIGH);
    }
}

/*
  Since SW2LowerDeck is READ_WRITE variable, onSW2LowerDeckChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW2LowerDeckChange()  {
  // Add your code here to act upon SW2LowerDeck change
      if (sW2_LowerDeck == 1) {
      digitalWrite(Relay14, LOW);
    } 
    else {
      digitalWrite(Relay14, HIGH);
    }
}

/*
  Since SW3TikiBar is READ_WRITE variable, onSW3TikiBarChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW3TikiBarChange()  {
  // Add your code here to act upon SW3TikiBar change
    if (sW3_TikiBar == 1) {
      digitalWrite(Relay16, LOW);
    } 
    else {
      digitalWrite(Relay16, HIGH);
    }
}

/*
  Since SW4Pool is READ_WRITE variable, onSW4PoolChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSW4PoolChange()  {
  // Add your code here to act upon SW4Pool change
  if (sW4_Pool == 1) {
      digitalWrite(Relay1, LOW);
    } 
    else {
      digitalWrite(Relay1, HIGH);
    }
}


/*
  Since Shower is READ_WRITE variable, onShowerChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onShowerChange(){
}

void run_Shower() {
    if ((currentSTime - previousSTime) >= Run) {  
          Count++;
            switch(Count){
                case 1:
                 /* lcd.clear();
                  lcd.setCursor(0, 0);
                  if(filter_Active){
                    lcd.print("Filter active turn Off"); 
                    digitalWrite(Relay4, HIGH); //Filter Off
                  }else{
                    lcd.print("Filter not active");
                    }
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo ON ");
                  lcd.setCursor(0, 3);
                  lcd.print("Case 1");  */                            
                  digitalWrite(Relay6, LOW); //3 Way Trafo On                  
                  Run = WAIT_1Sec;
                  break;

                case 2:
               /*   lcd.clear();
                  lcd.setCursor(0, 0);
                  lcd.print("3Way Valve ON->Pump");
                  lcd.setCursor(0, 3);
                  lcd.print("Case  2");    */               
                  digitalWrite(Relay10, LOW); //3 Way over to shower pump (Posibly) LOW???                  
                  Run = WAIT_1Min;
                  break;

                case 3:
                 /* lcd.clear();
                  
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter back ON");
                    digitalWrite(Relay4, LOW); //Filter ON
                  }
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump ON");                  
                  lcd.setCursor(0, 3);
                  lcd.print("Case   3");   */                 
                  digitalWrite(Relay8, LOW); //Shower Pump ON                  
                  Run = WAIT_1Min * showerTime;
                  break;

                case 4:
                  lcd.clear();
                  /*
                  if(filter_Active){
                    lcd.setCursor(0, 0);
                    lcd.print("Filter Off"); 
                    digitalWrite(Relay4, HIGH); //Filter Off                      
                  }*/
                  lcd.setCursor(0, 1);
                  lcd.print("Shower Pump OFF");                                             
                  lcd.setCursor(0, 2);
                  lcd.print("3Way back <- Filter");
                  lcd.setCursor(0, 3);
                  lcd.print("Case    4");                                   
                  digitalWrite(Relay8, HIGH); //Shower Pump Off
                  digitalWrite(Relay10, HIGH); //3 Way over to filter (Posibly) HIGH???                  
                  Run = WAIT_1Min;
                  break;

                case 5:
                  /*lcd.clear();
                  lcd.setCursor(0, 1);
                  lcd.print("Trafo OFF");  
                  lcd.setCursor(0, 3);
                  lcd.print("Case     5");  */                       
                  digitalWrite(Relay6, HIGH); //3 Way Trafo Off                  
                  Run = WAIT_1Sec;
                  break;    

              case 6:
                    shower = 0; //Turn cloud switch back to OFF
                    Count = 0;
                    Run = 1;
                    break;

              
                default:   
                    Serial.print("Error: Unexpected value of Count: ");
                    Serial.println(Count);
            }
            previousSTime = currentSTime;  
          }
}


/*
  Since PoolScheduleMorning is READ_WRITE variable, onPoolScheduleMorningChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleMorningChange(){
  // Add your code here to act upon PoolScheduleMorning change
}

/*
  Since PoolScheduleEvening is READ_WRITE variable, onPoolScheduleEveningChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPoolScheduleEveningChange() {
  // Add your code here to act upon PoolScheduleEvening change
  }


void runUvFilter(){
  if (poolScheduleMorning.isActive()||poolScheduleEvening.isActive()) {
    uV_Reactor = true;
    filter_Active = true;

    switch(shower){
      case 0:
        digitalWrite(Relay4, LOW);//Filter ON
        digitalWrite(Relay2, LOW); //UV ON
        break;
      case 1:
        digitalWrite(Relay4, HIGH);//Filter OFF
        digitalWrite(Relay2, HIGH);//UV Off
        break;
    }
  }else{
      uV_Reactor = false;
      filter_Active = false;
      digitalWrite(Relay4, HIGH);//Filter OFF
      digitalWrite(Relay2, HIGH);//UV Off
  }
}


/*
  Since ShowerTime is READ_WRITE variable, onShowerTimeChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onShowerTimeChange()  {
  // Add your code here to act upon ShowerTime change
}
1 Like

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