1 (edited by jhome0005 2022-05-24 03:24:34)

Topic: Coding Ideas and Suggestions, Irrigation System

Hello,
I have a working 12 zone sprinkler controller that I have troubles with the arduino resetting from time to time. Which I believe is a forced reset from RemoteXY. It also doesn't seem to be a consistent reset that I could pinpoint a section of code either.
Here is a detail of the project I copied from my github:

# SPSYS
## Arduino Sprinkler Control System with Heater and Fan Control/Thermostat

Using two ESP8266, one for [RemoteXY](https://remotexy.com/en/) App control, and one for automatic "Season Adjust" weather updates and time update, with daily data gmail sent.

### Features:
+ WIFI control via cloud using RemoteXY [App](https://remotexy.com/en/download/)
  + This Setup requires PRO version of App
  + Also requires RemoteXY Cloud Token
+ Up to 12 Zone Control
+ Season Adjust capable, used in all run modes
  + Example: Season Adjust of 100 is 100%
+ Auto Run all zones by set start time with zone run time
  + Ability to set which days of week for Auto Run
+ Manual Run all zones with zone run time
+ Individually run zones with zone run time
+ Zone run time setting (each zone)
  + Zone "run time left" diplayed in app
+ With master valve control
  + Ability to run only master valve
  + With Delays (default 10 seconds) between master start and zone start for pump pressure rebuilding
  + Keeps track and displays daily run time of master valve
+ Ability to link zones together to run two zones at once
  + 1&2, 3&4, 5&6, 7&8, 9&10, 11&12
  + With Delays (default 30 seconds) between first zone start and second zone start for pump pressure rebuilding
+ Indoor and outdoor temp displayed in App (using DS3231 and DS18B20)
+ Ability to set DS3231 time in App (not really needed anymore)

+ Update Page 3 (in App)
  + Nothing saved to EEPROM
    + Updates Switches Only (not really needed)
  
+ Update Page 2 (in App)
  + Saves settings to EEPROM
    + Saves Auto Run switch position
    + Saves start time hour and minute
    + Saves Season Adjust
    + Saves days of week to run in Auto Run
    + Saves Auto SA switch position
      + (if ON) Season Adjust is calculated by real weather data daily
  
+ Update Page 3 (in App)
  + Saves settings to EEPROM
    + Saves individual zone run time
    
+ Update Heater (in App)
  + Saves settings to EEPROM
    + Saves Heat switch position
    + Saves heat desired temp
    + Saves heat drop to run

+ Also implemented garage heater control/thermostat
  + Heat control (setting of 35 to 85)
  + "Fan Only" control
  + Uses temp from DS3231
  + Heat "temp drop to run" control
    + Amount of temp drop for heater to run (setting of 0 to 10)
    
### Second ESP Features:
+ Daily gets and sends time (ntp) to Mega 2560 to set DS3231 time
+ Daily gets weather info [accuweather.com](https://developer.accuweather.com/)
  + Then calculates Season Adjust and sends to Mega 2560
    + Uses: 
      + Current day max temp
      + Current day hours of sun
      + Current day 24 hour Forcasted Precip. Total Amount
      + Past 24 hour Precip. Total Amount

+ Sends daily gmail 
  + Containing:
    + Time Stamp
    + Weather Data
    + New Calculated Season Adjust
    + Master Pump Day Run Time
    + Heater Day Run Time
+ Uses SHA1 Fingerprint for email sending
  + Fingerprint can be updated via web server IP address (within first 5 minutes of system restart)
    + Example to send: C4:7E:A3:97:FD:A0:51:4E:45:EA:C4:E2:48:4A:2D:43:F1:2B:51:66
    + Fingerprint will then be saved to EEPROM

I Currently have almost 5000 lines of code in this project as my coding is not well polished due to being a somewhat rookie.

I am wondering of ideas of a quicker (lesser code) way of running through 12 sprinkler zones either when in auto mode (scheduled time) or manual mode.
I have the ability (when water table is higher, (more water from pump)) to run two zones at once.
I have a pump delay adjustable time between zone starts (amount of time passed between zones for pump to catch back up), and a linked zone delay (running two zones at same time, delay between start of second zone after first zone start)

So these would be the variables needed to check when going through zones:
Time of day to start (for auto mode)
Manual mode (runs through all zones when told)
Pump delay between each zone start (amount of time pump runs before zone start)
Zone run time (each zone has it's own run time)
If linked zones is enabled (running two zones at once)
Linked zone delay (delay between start of second zone after first zone start)
Season adjust percentage (Zone run time * season adjust percentage)

Currently I'm basically doing it now with about 35 switch cases and a separate function for each zone start and stop and pump start and stop.

Any ideas would be appreciated.

2

Re: Coding Ideas and Suggestions, Irrigation System

One other question,
Is there a way to distinguish (when powered up again) between when the power goes and the unit restarts vs. when the unit restarts when there is a code issue and a restart is forced?

3

Re: Coding Ideas and Suggestions, Irrigation System

It is very difficult to understand why the controller is reset. Stack overflows, out of memory in heap, power failures and much more. Also a watchdog would be good for any controller for large and responsible projects.

4

Re: Coding Ideas and Suggestions, Irrigation System

I do currently have a watchdog timer in, which is set for 8 seconds. It seems that when a reset occurs, it is almost immediate.

5

Re: Coding Ideas and Suggestions, Irrigation System

@remotexy

An idea or insight why for my sprinkler control, I set it to manual (run through all zones per each set run time), one day it will work just fine, then the next day it has a "breakdown" somewhere through and does a reset?

I'm not the most knowledgeable in coding but I thought that either a set of code would work or it doesn't work.
I don't quite understand why the same code would work one day and not the next.

Any insight would be appreciated!

6

Re: Coding Ideas and Suggestions, Irrigation System

In my program redo, I was thinking of putting some of these variables in an array.
Would this be a smart way to do it?
And is labeling the array type as "int" not correct?

// this structure defines all the variables and events of your control interface
struct {

  // input variables
  float season_Adj;
  uint8_t zone_2; // =1 if switch ON and =0 if OFF
  uint8_t zone_3; // =1 if switch ON and =0 if OFF
  uint8_t zone_1; // =1 if switch ON and =0 if OFF
  uint8_t zone_4; // =1 if switch ON and =0 if OFF
  uint8_t zone_5; // =1 if switch ON and =0 if OFF
  uint8_t zone_6; // =1 if switch ON and =0 if OFF
  uint8_t zone_7; // =1 if switch ON and =0 if OFF
  uint8_t zone_8; // =1 if switch ON and =0 if OFF
  uint8_t zone_9; // =1 if switch ON and =0 if OFF
  uint8_t zone_10; // =1 if switch ON and =0 if OFF
  uint8_t zone_11; // =1 if switch ON and =0 if OFF
  uint8_t zone_12; // =1 if switch ON and =0 if OFF
  uint8_t pump_1; // =1 if switch ON and =0 if OFF
  uint8_t auto_Run; // =1 if switch ON and =0 if OFF
  int16_t rTzone_1;  // 32767.. +32767
  int16_t rTzone_4;  // 32767.. +32767
  int16_t rTzone_5;  // 32767.. +32767
  int16_t rTzone_9;  // 32767.. +32767
  int16_t rTzone_2;  // 32767.. +32767
  int16_t rTzone_3;  // 32767.. +32767
  int16_t rTzone_8;  // 32767.. +32767
  int16_t rTzone_6;  // 32767.. +32767
  int16_t rTzone_10;  // 32767.. +32767
  int16_t rTzone_7;  // 32767.. +32767
  int16_t rTzone_12;  // 32767.. +32767
  int16_t rTzone_11;  // 32767.. +32767
  int16_t start_Time_Hour;  // 32767.. +32767
  int16_t start_Time_Minute;  // 32767.. +32767
  uint8_t linked_Valves; // =0 if select position A, =1 if position B, =2 if position C, ...
  uint8_t manual_Run; // =1 if switch ON and =0 if OFF
  int16_t set_Time_Hour;  // 32767.. +32767
  int16_t set_Time_Minute;  // 32767.. +32767
  uint8_t set_Time; // =1 if switch ON and =0 if OFF
  uint8_t updateZoneSwitchs; // =1 if button pressed, else =0
  uint8_t updatePage2; // =1 if button pressed, else =0
  uint8_t updatePage3; // =1 if button pressed, else =0
  uint8_t resetPT; // =1 if button pressed, else =0
  uint8_t satD; // =1 if switch ON and =0 if OFF
  uint8_t friD; // =1 if switch ON and =0 if OFF
  uint8_t thuD; // =1 if switch ON and =0 if OFF
  uint8_t wedD; // =1 if switch ON and =0 if OFF
  uint8_t tueD; // =1 if switch ON and =0 if OFF
  uint8_t monD; // =1 if switch ON and =0 if OFF
  uint8_t sunD; // =1 if switch ON and =0 if OFF
  int16_t set_Day;  // 32767.. +32767
  uint8_t autoSeasonAdjust; // =1 if switch ON and =0 if OFF
  uint8_t override_SA; // =1 if switch ON and =0 if OFF
  uint8_t heat; // =1 if switch ON and =0 if OFF
  uint8_t fan; // =1 if switch ON and =0 if OFF
  int16_t heat_Temp;  // 32767.. +32767
  int16_t heat_Drop;  // 32767.. +32767
  uint8_t updateHeater; // =1 if button pressed, else =0
  int16_t appPumpDelay;  // 32767.. +32767
  int16_t appLinkedPumpDelay;  // 32767.. +32767

  // output variables
  uint8_t led_Heat_b; // =0..255 LED Blue brightness
  uint8_t led_Pump_b; // =0..255 LED Blue brightness
  uint8_t led_12_b; // =0..255 LED Blue brightness
  uint8_t led_8_b; // =0..255 LED Blue brightness
  uint8_t led_7_b; // =0..255 LED Blue brightness
  uint8_t led_11_b; // =0..255 LED Blue brightness
  uint8_t led_10_b; // =0..255 LED Blue brightness
  uint8_t led_9_b; // =0..255 LED Blue brightness
  uint8_t led_6_b; // =0..255 LED Blue brightness
  uint8_t led_5_b; // =0..255 LED Blue brightness
  uint8_t led_4_b; // =0..255 LED Blue brightness
  uint8_t led_3_b; // =0..255 LED Blue brightness
  uint8_t led_2_b; // =0..255 LED Blue brightness
  uint8_t led_1_b; // =0..255 LED Blue brightness
  char time_Hour[11];  // string UTF8 end zero
  char time_Minute[11];  // string UTF8 end zero
  char sTH_show[11];  // string UTF8 end zero
  char sTM_show[11];  // string UTF8 end zero
  char sAdj_show[11];  // string UTF8 end zero
  char rTzone_1show[11];  // string UTF8 end zero
  char rTzone_5show[11];  // string UTF8 end zero
  char rTzone_9show[11];  // string UTF8 end zero
  char rTzone_4show[11];  // string UTF8 end zero
  char rTzone_8show[11];  // string UTF8 end zero
  char rTzone_12show[11];  // string UTF8 end zero
  char rTzone_11show[11];  // string UTF8 end zero
  char rTzone_7show[11];  // string UTF8 end zero
  char rTzone_3show[11];  // string UTF8 end zero
  char rTzone_2show[11];  // string UTF8 end zero
  char rTzone_6show[11];  // string UTF8 end zero
  char rTzone_10show[11];  // string UTF8 end zero
  char zTimeLeft[11];  // string UTF8 end zero
  char in_Temp[11];  // string UTF8 end zero
  char out_Temp[11];  // string UTF8 end zero
  char pTOn[11];  // string UTF8 end zero
  char day_Of_Week[11];  // string UTF8 end zero
  char weatherTimeStamp[35];  // string UTF8 end zero
  char rst_Times[11];  // string UTF8 end zero
  char SA_text[21];  // string UTF8 end zero
  char heatTemp_show[11];  // string UTF8 end zero
  char heatDrop_show[11];  // string UTF8 end zero
  char heatRunTime[23];  // string UTF8 end zero

  // other variable
  uint8_t connect_flag;  // =1 if wire connected, else =0

} RemoteXY;
#pragma pack(pop)

Arrays:

int pumpORzone[] = {RemoteXY.pump_1, RemoteXY.zone_1, RemoteXY.zone_2, RemoteXY.zone_3, RemoteXY.zone_4, RemoteXY.zone_5, RemoteXY.zone_6, RemoteXY.zone_7, RemoteXY.zone_8, RemoteXY.zone_9, RemoteXY.zone_10, RemoteXY.zone_11, RemoteXY.zone_12};
int zoneRunTime[] = {RemoteXY.rTzone_1, RemoteXY.rTzone_2, RemoteXY.rTzone_3, RemoteXY.rTzone_4, RemoteXY.rTzone_5, RemoteXY.rTzone_6, RemoteXY.rTzone_7, RemoteXY.rTzone_8, RemoteXY.rTzone_9, RemoteXY.rTzone_10,RemoteXY.rTzone_11, RemoteXY.rTzone_12};
int pumpORzoneLED[] = {RemoteXY.led_Pump_b, RemoteXY.led_1_b, RemoteXY.led_2_b, RemoteXY.led_3_b, RemoteXY.led_4_b, RemoteXY.led_5_b, RemoteXY.led_6_b, RemoteXY.led_7_b, RemoteXY.led_8_b, RemoteXY.led_9_b, RemoteXY.led_10_b, RemoteXY.led_11_b, RemoteXY.led_12_b};

7

Re: Coding Ideas and Suggestions, Irrigation System

It won't work. You declare an array and write the current values of the variables from the RemoteXY structure. In the future, these values are not related in any way.
Try the following. Declare an array of references to variables of RemoteXY structure, then refer to the variables by reference through the array.

uint8_t * zones[] = {&RemoteXY.zone_1, &RemoteXY.zone_2, &RemoteXY.zone_3, &RemoteXY.zone_4, &RemoteXY.zone_5, &RemoteXY.zone_6, &RemoteXY.zone_7, &RemoteXY.zone_8, &RemoteXY.zone_9, &RemoteXY.zone_10, &RemoteXY.zone_11, &RemoteXY.zone_12};

*zones[2] = 1;  // write
uint8_t v = *zones[2] ;  // read

8

Re: Coding Ideas and Suggestions, Irrigation System

Thanks for the reply. Yes your example worked out well.
I managed to somewhat shorten and refine my code which seems to be working properly..... so far.
I'm sure there is more refining that can be done but will see how this works out for a bit.

I didn't understand what you meant by

In the future, these values are not related in any way.

Here's a chunk of my reworked:

int relays[] = {PIN_PUMP_1, PIN_ZONE_1, PIN_ZONE_2, PIN_ZONE_3, PIN_ZONE_4, PIN_ZONE_5, PIN_ZONE_6, PIN_ZONE_7, PIN_ZONE_8, PIN_ZONE_9, PIN_ZONE_10, PIN_ZONE_11, PIN_ZONE_12};
uint8_t *pumpORzone[] = {&RemoteXY.zone_1, &RemoteXY.zone_2, &RemoteXY.zone_3, &RemoteXY.zone_4, &RemoteXY.zone_5, &RemoteXY.zone_6, &RemoteXY.zone_7, &RemoteXY.zone_8, &RemoteXY.zone_9, &RemoteXY.zone_10, &RemoteXY.zone_11, &RemoteXY.zone_12};
int *zoneRunTime[] = {&RemoteXY.rTzone_1, &RemoteXY.rTzone_2, &RemoteXY.rTzone_3, &RemoteXY.rTzone_4, &RemoteXY.rTzone_5, &RemoteXY.rTzone_6, &RemoteXY.rTzone_7, &RemoteXY.rTzone_8, &RemoteXY.rTzone_9, &RemoteXY.rTzone_10, &RemoteXY.rTzone_11, &RemoteXY.rTzone_12};
uint8_t *pumpORzoneLED[] = {&RemoteXY.led_1_b, &RemoteXY.led_2_b, &RemoteXY.led_3_b, &RemoteXY.led_4_b, &RemoteXY.led_5_b, &RemoteXY.led_6_b, &RemoteXY.led_7_b, &RemoteXY.led_8_b, &RemoteXY.led_9_b, &RemoteXY.led_10_b, &RemoteXY.led_11_b, &RemoteXY.led_12_b};
int currentZone = 0;   // current zone that is running
int singleZoneOn = -1; // single zones or zones started


loop:

// ADDED, A or M Switch Change////////////////////////////////////////////////////////////////////////////////////
  if ((RemoteXY.auto_Run == 1) && (!autoON))
  {
    checkAorM();
  }
  if ((RemoteXY.manual_Run == 1) && (!manualON))
  {
    checkAorM();
  }
  if ((autoON) && (RemoteXY.auto_Run == 0))
  {
    checkAorM();
  }
  if ((manualON) && (RemoteXY.manual_Run == 0))
  {
    checkAorM();
  }

  if (autoON)
  {
    if (AorM == 1)
    {
      if (RemoteXY.start_Time_Hour == t.hour)
      {
        if (RemoteXY.start_Time_Minute == t.min)
        {
          checkWeekday();
          if (((((((monDay) || (tueDay) || (wedDay) || (thuDay) || (friDay) || (satDay) || (sunDay)))))))
          {
            if (RemoteXY.season_Adj >= 1)
            {
              valvesShutDown();
              AorM = 3;
              autoON = true;
              digitalWrite(PIN_AUTO_RUN, LOW);   // GREEN
              digitalWrite(AUTO_BLUE_PIN, HIGH); // BLUE
              DebugPrintln("Auto Time to Start");
            }
            else
            {
              AorM = 2;
              DebugPrintln("Skipping Autorun, Season Adjust Below 1");
            }
          }
        }
      }
    }
  }

  // Reset AorM after Autorun Season Adjust Too Low
  if ((AorM == 2) && ((RemoteXY.start_Time_Minute + 1) == t.min))
  {
    AorM = 1;
    DebugPrintln("Autorun AorM Reset, Season Adjust Below 1");
  }

  if ((manualON) && (AorM == 1))
  {
    AorM = 3;
    digitalWrite(PIN_MANUAL_RUN, HIGH); // RED
    DebugPrintln("Manual Time to Start, Red LED ON");
  }

  if ((AorM >= 3) && (AorM < 8))
  {
    if (AorM == 3)
    {
      DebugPrintln("AorM = 3, Going to Start Pump");
      AorMisRunning();
    }

    if (AorM == 4)
    {
      if ((millis() - z1Mill) >= pumpDelay)
      {
        AorM = 5;
        DebugPrintln("AorM = 5, Pump Delay is Over");
        AorMisRunning();
      }
    }
    if (AorM == 6)
    {
      if (millis() - z1Mill >= xz1)
      {
        DebugPrintln("AorM = 6, Shutting Down and Switching Zones");
        AorMisSwitching();
      }
    }
    if (AorM == 7)
    {
      // if (currentZone == 1 || currentZone == 3 || currentZone == 5 || currentZone == 7)
      //{
      if ((millis() - z1Mill) >= linkedPumpDelay)
      {
        AorM = 5;
        DebugPrintln("AorM = 7, Linked, Starting Second Zone");
        AorMisRunning();
      }
      //}
    }
  }
  // ADDED, A or M Switch Change////////////////////////////////////////////////////////////////////////////////////

  // ADDED, Single Zone Switchs ////////////////////////////////////////////////////////////////////////////////////
  if ((stateApp == 1) || (pumpRunning))
  {
    if ((AorM == 1) || (AorM == 16))
    {
      if (!manualON)
      {
        checkSingleZones();
      }
    }
  }

  if (singleZoneOn != -1)
  {
    if ((AorM == 8) || (AorM == 9))
    {
      if (zcrc == 0)
      {
        valvesShutDown();
        AorM = 8;
      }
      singleZoneStarting();
    }
    if (AorM == 14)
    {
      if ((millis() - z1Mill) >= pumpDelay)
      {
        AorM = 15;
        DebugPrintln("Single Zone, Pump Delay is Over");
        singleZoneStarting();
      }
    }
    if (AorM == 16)
    {
      if (millis() - z1Mill >= xz1)
      {
        DebugPrintln("Single Zones, Shutting Down Zones");
        currentZone = 0;
        singleZoneOn = -1;
        AorM = 1;
        valvesShutDown();
      }
    }
  }
  // ADDED, Single Zone Switchs ////////////////////////////////////////////////////////////////////////////////////
  
  // ADDED, Checking A or M Switches//////////////////////////////////////////////////////////////////////////////
void checkAorM()
{
  // If Auto was on and Auto Switch now off
  if ((autoON) && (RemoteXY.auto_Run != 1))
  {
    valvesShutDown();
    AorM = 1;
    digitalWrite(PIN_AUTO_RUN, LOW); // GREEN
    RemoteXY.auto_Run = 0;
    DebugPrintln("Auto Was On and User Turned OFF, autoON Now is FALSE");
  }
  // If Manual was on and Manual Switch now off
  if ((manualON) && (RemoteXY.manual_Run != 1))
  {
    valvesShutDown();
    AorM = 1;
    RemoteXY.manual_Run = 0;
    DebugPrintln("Manual Was On and User Turned OFF, autoON Now is FALSE");
  }
  // Turn off Auto Green LED while Manual is Running
  if ((autoON) && (RemoteXY.manual_Run == 1))
  {
    AorM = 1;
    digitalWrite(PIN_AUTO_RUN, LOW); // GREEN
    valvesShutDown();
    manualON = true;
    DebugPrintln("Override Auto to Manual, manualON Now is TRUE");
  }
  // Turn on Auto Green LED after Manual is done
  if (((!manualON) && (AorM == 1) && (RemoteXY.auto_Run == 1)))
  {
    valvesShutDown();
    digitalWrite(PIN_AUTO_RUN, HIGH); // GREEN
    autoON = true;
    DebugPrintln("Manual Cycle Done Or Just Turning Auto ON, autoON Now is TRUE");
  }
  // Turn on Manual
  if ((!manualON) && (RemoteXY.manual_Run == 1))
  {
    valvesShutDown();
    AorM = 1; // Should already be at 1???
    manualON = true;
    DebugPrintln("Manual Not ON, manualON Now is TRUE");
  }
}
// ADDED, Checking A or M Switches//////////////////////////////////////////////////////////////////////////////

// ADDED, Auto or Manual is Running/////////////////////////////////////////////////////////////////////////////
void AorMisRunning()
{
  if (sAdjust <= 0)
  {
    sprintf(RemoteXY.SA_text, "<-THIS TASK ONLY");
    AorM = 1;
    RemoteXY.manual_Run = 0;
    valvesShutDown();
    DebugPrintln("AorM Season Adjust Less Than 1, Now Ending");
  }
  if (!pumpRunning)
  {
    pumpStart();
    currentZone = 0;
    AorM = 4;
  }
  if (AorM == 5)
  {
    int zonePlusOne = currentZone + 1; // Add 1 for Pump is at Zero Index
    digitalWrite(relays[zonePlusOne], LOW);
    xz1 = *zoneRunTime[currentZone] * 60000;
    // Check For Linked Zones
    if (RemoteXY.linked_Valves == 1)
    {
      if (currentZone < 8)
      {
        // One Zone Already Started
        if (zcrc >= 1)
        {
          AorM = 6;
        }
        // No Zones Started Yet
        else
        {
          AorM = 7;
        }
        //  if (currentZone == 1 || currentZone == 3 || currentZone == 5 || currentZone == 7)
        if (AorM == 6)
        {
          int tempZoneRT = currentZone;
          xz2 = *zoneRunTime[tempZoneRT] * 60000;
          xz1 = max(xz1, xz2);
          DebugPrintln("Linked Zone Run Time = ");
          DebugPrint(xz1);
        }
      }
      // Stopping Linking Zones After 7 and 8 Get Linked (Don't Link 9-12)
      else
      {
        AorM = 6;
      }
    }
    if (RemoteXY.linked_Valves == 0)
    {
      AorM = 6;
    }
    xz1 = round(xz1 * sAdjust);
    zTime = xz1;
    if (xz1 < 1)
    {
      pumpDelay = 0;
      linkedPumpDelay = 0;
    }
    else
    {
      pumpDelay = tempPumpDelay;
      linkedPumpDelay = tempLinkedPumpDelay;
    }
    DebugPrintln(sAdjust);
    DebugPrintln(zTime);
    *pumpORzone[currentZone] = 1;
    z1Mill = millis();
    zcrc++;
    *pumpORzoneLED[currentZone] = 255;
    DebugPrintln("Auto or Manual- Zone Started");
    currentZone++;
    // itoa(resetCounter, RemoteXY.rst_Times, 10); // MOVED HERE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    itoa(currentZone, RemoteXY.rst_Times, 10); // MOVED HERE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  }
}
// ADDED, Auto or Manual is Running/////////////////////////////////////////////////////////////////////////////

// ADDED, Auto or Manual is Shutting Down Zones/////////////////////////////////////////////////////////////////
void AorMisSwitching()
{
  if (currentZone < 12)
  {
    if (zcrc > 1)
    {
      int zPlusOne = currentZone - 1; // Add 1 for Pump is at Zero Index
      int tempZone = currentZone - 2;
      digitalWrite(relays[zPlusOne], HIGH);
      *pumpORzone[tempZone] = 0;
      *pumpORzoneLED[tempZone] = 0;
      DebugPrintln("Auto or Manual Linked Zones Shutting Down");
    }
    int tempZone2 = currentZone - 1;
    digitalWrite(relays[currentZone], HIGH); // Add 1 for Pump is at Zero Index
    *pumpORzone[tempZone2] = 0;
    *pumpORzoneLED[tempZone2] = 0;
    AorM = 4;
    zcrc = 0;
    z1Mill = millis();
    DebugPrintln("Auto or Manual Zone Shutting Down");
  }
  else
  {
    if (RemoteXY.manual_Run != 0)
    {
      RemoteXY.manual_Run = 0;
    }
    AorM = 1;
    valvesShutDown();
  }
}
// ADDED, Auto or Manual is Shutting Down Zones/////////////////////////////////////////////////////////////////

// ADDED, Checking Single Zones for Control/////////////////////////////////////////////////////////////////////
void checkSingleZones()
{
  if (zcrc == 1)
  {
    int szo = *pumpORzone[singleZoneOn];
    if (szo == 0)
    {
      DebugPrintln("Single Zones, User Shut Down Zone");
      currentZone = 0;
      singleZoneOn = -1;
      AorM = 1;
      valvesShutDown();
    }
  }
  if (zcrc == 2)
  {
    int czo = *pumpORzone[currentZone];
    if (czo == 0)
    {
      DebugPrintln("Single Zones, User Shut Down Zone, Shutting Down Both");
      currentZone = 0;
      singleZoneOn = -1;
      AorM = 1;
      valvesShutDown();
    }
  }
  if (zcrc < 2)
  {
    int z = 0;
    while (z < 12)
    {
      uint8_t wz = *pumpORzone[z];
      if (wz == 1)
      {
        if (singleZoneOn == -1)
        {
          currentZone = z;
          singleZoneOn = z;
          AorM = 8;
          DebugPrintln("Single Zone, 1 Zone Set to Turn On");
          break;
        }
        if (singleZoneOn != -1)
        {
          if (z != singleZoneOn)
          {
            currentZone = z;
            AorM = 9;
            DebugPrintln("Single Zone, 2nd Zone Set to Turn On");
            break;
          }
        }
      }
      z++;
      // Below Prints Constantly
      // DebugPrintln("Single Zone, Zone Not On, Checking Next");
    }
  }
}

// ADDED, Checking Single Zones for Control/////////////////////////////////////////////////////////////////////

// ADDED, Single Zone Starting//////////////////////////////////////////////////////////////////////////////////
void singleZoneStarting()
{
  if (sAdjust <= 0)
  {
    sprintf(RemoteXY.SA_text, "<-THIS TASK ONLY");
    AorM = 1;
    valvesShutDown();
    DebugPrintln("Single Zone Season Adjust Less Than 1, Now Ending");
  }
  if ((AorM == 8) || (AorM == 9))
  {
    if (!pumpRunning)
    {
      pumpStart();
      AorM = 14;
    }
    else
    {
      AorM = 14;
    }
  }
  if (AorM == 15)
  {
    int zonePlusOne = currentZone + 1; // Add 1 for Pump is at Zero Index
    digitalWrite(relays[zonePlusOne], LOW);
    xz1 = *zoneRunTime[currentZone] * 60000;
    xz1 = round(xz1 * sAdjust);
    zTime = xz1;
    if (xz1 < 1)
    {
      pumpDelay = 0;
      linkedPumpDelay = 0;
    }
    else
    {
      pumpDelay = tempPumpDelay;
      linkedPumpDelay = tempLinkedPumpDelay;
    }
    DebugPrintln(sAdjust);
    DebugPrintln(zTime);
    *pumpORzone[currentZone] = 1;
    z1Mill = millis();
    zcrc++;
    AorM = 16;
    *pumpORzoneLED[currentZone] = 255;
    DebugPrintln("Single Zone- Zone Started");
    //  itoa(resetCounter, RemoteXY.rst_Times, 10); // MOVED HERE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    itoa(currentZone, RemoteXY.rst_Times, 10); // MOVED HERE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  }
}
// ADDED, Single Zone Starting////////////////////////////////////////////////////////////////////////////////

9

Re: Coding Ideas and Suggestions, Irrigation System

Well I guess my single zones are not working now. Automatic and manual run through all zones is working fine.
Funny thing, single zones worked fine while testing on short time frames but now when I start using again it runs the zone from start to finish but the board resets after zone ends.
Back to the drawing board....

10

Re: Coding Ideas and Suggestions, Irrigation System

jhome0005 wrote:

I didn't understand what you meant by

In the future, these values are not related in any way.

I mean. You have copied the values of the variables from RemoteXY struct into your new array. And now they are just different variables. If you change the values in the array, they will not change in the RemoteXY structure. And if the value of the variable in the RemoteXY structure changes, it will not change in the array. The variables are not bound.
Sorry for my English.

11 (edited by jhome0005 2022-06-12 02:27:52)

Re: Coding Ideas and Suggestions, Irrigation System

I mean. You have copied the values of the variables from RemoteXY struct into your new array. And now they are just different variables. If you change the values in the array, they will not change in the RemoteXY structure. And if the value of the variable in the RemoteXY structure changes, it will not change in the array. The variables are not bound.
Sorry for my English.

Ok. Thank you. Think I understand what your saying.

After still having some issue yet and doing more testing, I'm possibly thinking I may have an interference issue of some kind.

In the image below:

I have a separate 24v power supply coming into and looping through the relays for the load side.
In my testing I usually have this unplugged so the zones don't actually run (open up).
And with what appears to be "bugless" code, I don't experience an arduino restarts while testing.
But when I am running zones again (24v plugged in), I have intermittent unexplained restarts.

So with this thought in mind I have done more testing with 24v unplugged and am not having restart issues.

Is it possible to have some kind of interference from the 24v that has a completely separate power supply from the rest?
I am using this relay board: https://www.amazon.com/gp/product/B0057 … 8&th=1

https://gcdnb.pbrd.co/images/4vpRpIIgGnda.png

Edit: I don't know how to put an image on here.
https://pasteboard.co/4vpRpIIgGnda.png

12

Re: Coding Ideas and Suggestions, Irrigation System

Interference possible when switching high currents or inductive loads ??

13

Re: Coding Ideas and Suggestions, Irrigation System

Interference possible when switching high currents or inductive loads ??

I'm thinking this seem to be my issue. Thanks.
I've tested multiple times running through single zones, manual (run all zones), and auto run with the 24v DC unplugged (not running zones), and have not had any restarts.

I am thinking from my "googling" that maybe adding in a diode at the zone solenoid might help with the issue?

14 (edited by jhome0005 2022-06-14 01:58:46)

Re: Coding Ideas and Suggestions, Irrigation System

I stand corrected, the solenoids are ran from 24VAC, not DC.

I'm a little unsure of how to fix this interference issue. A snubber on the solenoid load perhaps?
FYI, my electrical design is almost as bad as my coding, lol.

Edit: Or maybe a varistor perhaps?

15

Re: Coding Ideas and Suggestions, Irrigation System

these interferences propagate as electromagnetic waves. Try to put the controller in an iron case and leave everything else outside

16 (edited by jhome0005 2022-06-16 03:42:52)

Re: Coding Ideas and Suggestions, Irrigation System

Thanks for the reply.
Sad part is, I've had my box set up for a year or so and there's not too much free space.
The 2560 and the communications esp is behind the relay board.
Maybe if I put an iron plate behind the relay board, might be possible.

https://i.ibb.co/RjC0z5C/spsys-Photo.jpg

17

Re: Coding Ideas and Suggestions, Irrigation System

Do you have the controller under the relay module? Try to place a metal plate wrapped with a dielectric between the controller and the relay module.

18

Re: Coding Ideas and Suggestions, Irrigation System

Yes I do. The controller and main esp module are behind the relay board.
I will have to see if I can fit something in there.
Basically to try and shield off the relay board and wires that have 24VAC right?

So a varistor or snubber on the solenoid load is not the proper approach, better to try your shielding method?

19

Re: Coding Ideas and Suggestions, Irrigation System

I think I may have corrected this issue now.
I have installed a grounded metal plate between the relay board and the controller.
I probably don't have the dielectric like it should be, all I have is a layer of plastic on each side of the plate where the controller and relay board are.
Another what I think was an issue is I had the wires for the clock module running in parallel next to the 24VAC lines.
I rerouted those wires as well.
So far, so good.

https://i.ibb.co/B6KXrpJ/spsys-Plate.jpg

20

Re: Coding Ideas and Suggestions, Irrigation System

This is good!
To paste an image, right-click on the image and select "copy image URL". Do not copy URL from browser line.

21

Re: Coding Ideas and Suggestions, Irrigation System

To paste an image, right-click on the image and select "copy image URL". Do not copy URL from browser line.

Ok, thanks for the info.

And thanks for your help with the project as well!