Arduino R3 not responding

Arduino R3 stops working for some unknown reason.
Works 100% for few hours with no issue but gets jammed up
After a restart everything works again as expected from a-z.

The scketch is to control a water pump mainly and to limit the amount of power(solar power) my house can utilize during the day without draining the solar batteries.
It gets complex as you can see the use of timers.

It appears after reading many topics it is a memory problem.
Any help to help me solve this pls.

enum STATES
{
  WAITING,
  RELEASED_AND_TIMING,
  TIMING
};
STATES pumpOverride = WAITING;

enum STATES2
{
  WAITING2,
  RELEASED_AND_TIMING2,
  TIMING2
};
STATES2 sunTimer = WAITING2;

enum STATES3
{
  WAITING3,
  RELEASED_AND_TIMING3,
  TIMING3
};
STATES3 pumpTime = WAITING3;

const int overrideButton = A1;
const int pumpSignal = A2;
const int waterLevelOk = A3;

// Start outputs
const int warnLowUVsun = 2;
const int sunActiveIndicate = 3;
const int overridePump = 4;
const int tankPump = 5;
const int geyser = 6;
const int irrigationPump = 7;

const int uvStrong = 8;
const int pin_9 = 9;
const int pin_10 = 10;
const int pumpFailed = 11;

byte currentButtonState;
byte previousButtonState;

unsigned long waitStartTime;
unsigned long currentTime;
unsigned long waitOverride = 40*60000UL;

byte currentButtonState2;
byte previousButtonState2;

unsigned long waitStartTime2;
unsigned long currentTime2;
unsigned long waitSunTimer = 64800000UL;

byte currentButtonState3;
byte previousButtonState3;

unsigned long waitStartTime3;
unsigned long currentTime3;
unsigned long waitPumpfillTime = 10800000UL;

boolean sunActiveTiming = false;
boolean uvEnough = false;
boolean waterLow = false;

int uvValue;
const int UV_SENSOR = A0;

const int UV_THRESHOLD2 = 50; 
const int UV_THRESHOLD3 = 60;
const int UV_THRESHOLD4 = 150;
const int UV_THRESHOLD5 = 350;
const int UV_THRESHOLD6 = 450;
const int UV_THRESHOLD7 = 500;
const int UV_THRESHOLD8 = 600;
const int UV_THRESHOLD9 = 700;

unsigned long RelayStartTime;
unsigned long RelayStopTime;

unsigned long RelayStartTime1;
unsigned long RelayStopTime1;

unsigned long RelayStartTime2;
unsigned long RelayStopTime2;

unsigned long RelayStartTime3;
unsigned long RelayStopTime3;

unsigned long RelayStartTime4;
unsigned long RelayStopTime4;

unsigned long RelayStartTime5;
unsigned long RelayStopTime5;

unsigned long RelayStartTime6;
unsigned long RelayStopTime6;

unsigned long RelayStartTime7;
unsigned long RelayStopTime7;

void setup()
{
  
  pinMode(overrideButton, INPUT_PULLUP);
  pinMode(pumpSignal, INPUT_PULLUP);
  pinMode(waterLevelOk, INPUT_PULLUP); 
 
  pinMode(warnLowUVsun, OUTPUT);
  pinMode(sunActiveIndicate, OUTPUT); 
  pinMode(overridePump, OUTPUT);
  pinMode(tankPump, OUTPUT); 
  pinMode(geyser, OUTPUT); 
  pinMode(irrigationPump, OUTPUT);
  pinMode(uvStrong, OUTPUT);
  pinMode(pin_9, OUTPUT);
  pinMode(pin_10, OUTPUT); 
  pinMode(pumpFailed, OUTPUT); 


 digitalWrite(warnLowUVsun, HIGH);
 digitalWrite(sunActiveIndicate, HIGH);
 digitalWrite(overridePump, HIGH);
 digitalWrite(tankPump, HIGH);
 digitalWrite(geyser, HIGH);
 digitalWrite(irrigationPump, HIGH);
 digitalWrite(uvStrong, HIGH);
 digitalWrite(pin_9, HIGH);
 digitalWrite(pin_10, HIGH);
 digitalWrite(pumpFailed, HIGH);
 }

void loop()
{  
  float sensorVoltage; 
  float UV_Sensor_Value; 

 UV_Sensor_Value = analogRead(UV_SENSOR);
  sensorVoltage = UV_Sensor_Value/1024*5.0;
   uvValue = UV_Sensor_Value;
  
 currentTime = millis(); 
 currentTime2 = millis(); 
 currentTime3 = millis(); 

 switch (pumpOverride)
  {
    case WAITING:
      previousButtonState = currentButtonState;
      currentButtonState = digitalRead(overrideButton);
      if (currentButtonState != previousButtonState) 
      {
        if (currentButtonState == LOW)  
        {
          digitalWrite(overridePump, LOW);
          waitStartTime = currentTime;
          pumpOverride = TIMING;
          pumpTime = TIMING3;
        }
      }
      break;
    case  TIMING:
      if (currentTime - waitStartTime >= waitOverride)
      {
        digitalWrite(overridePump, HIGH);
        pumpOverride = WAITING;
        pumpTime = WAITING3;
      }
      break;
    case RELEASED_AND_TIMING:
      break;
  }

 switch (sunTimer)
  {
    case WAITING2:
      previousButtonState2 = currentButtonState2;
      currentButtonState2 = digitalRead(pumpSignal);
      if (currentButtonState2 != previousButtonState2)
      {
        if (currentButtonState2 == LOW)
        {
         digitalWrite(sunActiveIndicate, LOW);
          waitStartTime2 = currentTime2;
          sunTimer = TIMING2;
        }
      }
      break;
    case  TIMING2:
      if (currentTime2 - waitStartTime2 >= waitSunTimer)
      {
        digitalWrite(sunActiveIndicate, HIGH);
        sunTimer = WAITING2;
      }
      break;
    case RELEASED_AND_TIMING2:
      break;
  }

 if (sunTimer == 2 && uvValue > UV_THRESHOLD3 && pumpTime == 0)
  {
    digitalWrite(pumpSignal, LOW);
  sunActiveTiming = true;
  } else { 
     digitalWrite(pumpSignal, HIGH);
    sunActiveTiming = false;
  }

 switch (pumpTime)
  {
    case WAITING3:
      previousButtonState3 = currentButtonState3;
      currentButtonState3 = digitalRead(pumpSignal);
      if (currentButtonState3 != previousButtonState3)
      {
        if (sunActiveTiming == 1 && uvEnough == 1)
        {
         digitalWrite(tankPump, LOW);
          waitStartTime3 = currentTime3;
          pumpTime = TIMING3;
        }
      }
      break;
    case  TIMING3:
      if (currentTime3 - waitStartTime3 >= waitPumpfillTime || uvEnough == 0)
      {
        digitalWrite(tankPump, HIGH);
        digitalWrite(sunActiveIndicate, HIGH);
        sunActiveTiming = false;
        pumpTime = WAITING3;
        sunTimer = WAITING2;
      }
      break;
    case RELEASED_AND_TIMING3:
    
      break;
  }
  uvValue = UV_Sensor_Value;
if (uvValue > UV_THRESHOLD2){

    if(millis()-RelayStopTime > 5000UL)
      {
      digitalWrite(warnLowUVsun, LOW);
      uvEnough = true; 
      RelayStartTime=millis();
      }      
}
  else if(millis()-RelayStartTime > 5000UL)
    {
    digitalWrite(warnLowUVsun, HIGH); 
  uvEnough = false;
    RelayStopTime=millis();
    }  

 if (digitalRead(waterLevelOk) == LOW)
  {
   waterLow = false;
  }
  if (digitalRead(pumpSignal) == LOW)
  {
    waterLow = true;
  }
  
  if (pumpTime == 2 && waterLow == 1)
  {
    if(millis()-RelayStopTime1 > 10*60000UL)
      {
      digitalWrite(pumpFailed, LOW);
      RelayStartTime1=millis();
      }      
    }
  else if(millis()-RelayStartTime1 > 1000UL)
    {
    digitalWrite(pumpFailed, HIGH);
    RelayStopTime1=millis(); 
      
    }   

  if(uvValue > UV_THRESHOLD5)
    {
    if(millis()-RelayStopTime2 > 2*60000UL)
      {
      digitalWrite(geyser, LOW);
      RelayStartTime2=millis();
      }      
    }
  else if(millis() - RelayStartTime2 > 2*60000UL)
    {
    digitalWrite(geyser, HIGH);
    RelayStopTime2=millis();        
    }

  if(uvValue > UV_THRESHOLD6)
    {
    if(millis()-RelayStopTime3 > 2*65000UL)
      {
      digitalWrite(irrigationPump, LOW);
      RelayStartTime3=millis();
      }      
    }
  else if(millis() - RelayStartTime3 > 2*65000UL)
    {
    digitalWrite(irrigationPump, HIGH);
    RelayStopTime3=millis();        
    }

  if(uvValue > UV_THRESHOLD7)
    {
    if(millis()-RelayStopTime4 > 2*70000UL)
      {
      digitalWrite(uvStrong, LOW);
      RelayStartTime4=millis();
      }      
    }
  else if(millis() - RelayStartTime4 > 2*70000UL)
    {
    digitalWrite(uvStrong, HIGH);
    RelayStopTime4=millis();        
    }

  if(uvValue > UV_THRESHOLD8)
    {
    if(millis()-RelayStopTime5 > 2*80000UL)
      {
      digitalWrite(pin_9, LOW);
      RelayStartTime5=millis();
      }      
    }
  else if(millis() - RelayStartTime5 > 2*80000UL)
    {
    digitalWrite(pin_9, HIGH);
    RelayStopTime5=millis();        
    }
}

A brief scan of the code doesn't reveal any of the usual suspects as far as memory issues are concerned. I think it's more likely that there's a semantic problem that is causing the code to get stuck in a state and doesn't set the appropriate boolean to ever move on.

I would add some serial debugging prints to help figure out where it's hanging.

I have done serial print to monitor what is going on in real time.
At some time the code also just stopped during this without me inputting anything low/high
More debugging? How?

It appears after reading many topics it is a memory problem

nothing seems to indicate memory issues.. You barely use memory, don't use dynamic allocation, don't use arrays which could overflow, don't have deep nested function calls...

I would start by putting a blinking LED to show if the loop is working fine (may be you have a bug in your logic and you get stuck in one of the state?) and look at a power / EMF issue

PS: side note, you don't need to duplicate the enumeration.

enum STATES
{
  WAITING,
  RELEASED_AND_TIMING,
  TIMING
};
STATES pumpOverride = WAITING;

enum STATES2
{
  WAITING2,
  RELEASED_AND_TIMING2,
  TIMING2
};
STATES2 sunTimer = WAITING2;

enum STATES3
{
  WAITING3,
  RELEASED_AND_TIMING3,
  TIMING3
};
STATES3 pumpTime = WAITING3;

just do

enum STATES
{
  WAITING,
  RELEASED_AND_TIMING,
  TIMING
};
STATES pumpOverride = WAITING;
STATES sunTimer = WAITING;
STATES pumpTime = WAITING;

(and get rid of the enumerators with the 2 and 3 at the end)

Nesting time stamp checks inside a conditional statement is a dangerous thing to do. If the conditional somehow remains false, the timing check is never performed and the timer never expires.

Hi,
Can you please post a circuit diagram of your R3 connections.
How have you got the controller powered.
How are you controlling the pump?

Can I suggest you use the on board LED as a heartbeat.
Place in your code the "Blink without delay" code.
While your code is running the LED will blink, if you have a code "freeze" the LED heartbeat will stop.

Tom... :smiley: :+1: :coffee: :australia:

That is 3 different states for 3 different timers
Using for pumpoverride, suntimer and pumptime
Will the change still be for all 3 timers?

I would make a function that prints your three states variables and call it whenever you execute code that changes any of them. I suspect that it will show that at least one of them gets stuck.

Will draw a picture and upload
Controller is powered with a decent 12v supply
Pump is only switched on via a micro switch and floater.

Pump to start when the float inside the water tanks reaches minimal water level, it sends a wireless signal to a receiver going low for 3 seconds then connected to arduino.
With the same float, if the float did rise and the micro switch change send again a signal to indicate pump did start and water is getting into the tank.

Hi,

So how does your code turn it on and off?

When you have a lockup, have you felt the onboard regulator to se if it is overheating and shutting down?

Tom... :smiley: :+1: :coffee: :australia:

you need the three variables, but the states indication are the same. Your sunTimer and. pumpTime might be in WAITING state whilst the pumpOverride is in TIMING state. You don't need to create extra labels

Pump is on a timer to pump only for 3hrs
Pumpoveride is also timed 40min

The onboard regulator is warm but not hot

Diagram


Regarding the timer never expires
on the code i have

if (uvValue > UV_THRESHOLD2){

    if(millis()-RelayStopTime > 5000UL)
      {
      digitalWrite(warnLowUVsun, LOW);
      uvEnough = true; 
      RelayStartTime=millis();
      }      
}
  else if(millis()-RelayStartTime > 5000UL)
    {
    digitalWrite(warnLowUVsun, HIGH); 
  uvEnough = false;
    RelayStopTime=millis();
    }  

So then if (uvValue > UV_THRESHOLD2){
wait 5 seconds then switch low
else uvValue < then wait 5 seconds if false to switch high
Or I'm missing something?

I don't recall waterLevelOk in earlier versions. What does it indicate?

@wildbill
Lets assume there is a broken pipe or something wrong, this will indicate to me there is a problem that the water did not rise in 10minutes time when the pump was started :wink:

Shame, I was hoping it meant full or halfway.

You the optimist. I though it meant halfway or empty. :expressionless:

@boerseun_petrus nice work BTW, looks like a very good and well documented project.

a7

There is another pin for that: pumpSignal.

1 Like

I have changed the enum STATES as suggested by Jackson

There also is a spare led to indicate the heartbeat on the front panel - however as im sitting typing here i can see the led flashing

I can connect the laptop to Serial.print - but what exactly are we looking for?
Any further tests?