Script Stopped working Corectly after a year, Arduino Serial Monior freezes ?

Strange one here folks. I have an Arduino (Uno) with a 4 relay board attached and an RTC. Its primary use is to turn some white and blue lights on and off via the relays.

It has been working in a project bix now for a year. Apart from noticing the RTC has been losing time (and the time will not update using a recompile and upload ?) I noticed a few weeks ago it was not turning the lights on and off at their set times any more.

I have as part of a unit a button to control the lights manually and this will still work. I plugged it into my PC via the serial port to look at the Serial monitor as I output all events to serial and all looked fine.

I then found that as the Arduino turns on the lights, it mostly hangs the Serial monitor and the TX light on the Arduino sticks on. When it does this the TimeAlarm function I use also stops working. Strangely the Arduino Void Loop section still seems to run as the LEDs I use to blink and manual button still work and control the lights.

I have to rest the Arduino to get it working again, but as soon as the relay activates the lights (tried without them actually plugged in and the result is the same) The Arduino Seriel monitor freezes and all the Alarm timer functions stops working.

Any ideas ? I though it may be a dogey relay board with some sort of surge but have swapped this and the result is still the same. I’m lost .. the code is below …..

the code is below …..

I can't see anything wrong with it, but then again I can't see any code ...

Part 1

#include <Wire.h>
#include "RTClib.h"
#include "Time.h"
#include "TimeAlarms.h"
#include <dht11.h>

#define RELAY1  7  // Setup and Define the Relays                       
#define RELAY2  8                         
#define RELAY3  9
#define RELAY4  10

#define DHT11PIN 6  //  Pin 6 for the DHT

int dialone = 11;    // Analogue Dial Connected to digital pin 11 - Temp
int dialtwo = 5;    // Analogue Dial Connected to digital pin 5 - Light
int dialthree = 3;    // Analogue Dial Connected to digital pin 3 - Stats

int pushButton = 13;  // Digital Button Connected to digital pin 13 - Light Swap
int lightstate = 0;  // Light state for advance and reset
int lastlight = 0;  // Last light setting used

int powerled = 2;    // Yellow Power LED Connected to digital pin 2

int pin = 0; // Analog pin for Temp
int tempc = 0;// Temperature variable in C
int samples[8]; // variables to make a better precision
int tempi; // Increment variable for temp taking

int htemp = 0; // value of hood temp
int hhume = 0; // value of hood humidity
int hoodcheck = 0;  // value to hold hood check value, is it hot or humid (temp)
int hoodfan =0;  // Is the fan on or off.  1 On 0 Off
 
RTC_DS1307 RTC;  // RTC call
dht11 DHT11;   // DHT11 call
 
void setup()
{    

// Initialise the Arduino data pins for Relay OUTPUT
  pinMode(RELAY1, OUTPUT);        
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);

// Initialise the Power LED for OUTPUT
  pinMode(powerled, OUTPUT);  
  //pinMode(buttonPin, INPUT); 

Serial.begin(9600); // start serial communication for logging to PC


pinMode(pushButton, INPUT); // Set Button to an Input


//  Starts the sets thr RTC  Real Time Clock
RTC.begin();
Wire.begin();
    
     if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    
    RTC.adjust(DateTime(__DATE__, __TIME__));  // Sets the RTC to the date & time this sketch was compiled
  }
   DateTime now = RTC.now();
  setTime(hour(), minute(), second(), day(), month(), year());
  setTime(now.hour(),now.minute(),now.second(),now.day(),now.month(),now.year()); 

// Relay Time Controls  ---------->

RelaySet(); // Reset Relays Off Procedure Call

// Times on and off settings :  (arduino lost 1.5 hours)

//Royal Blue ON
Alarm.alarmRepeat(9,30,0, LightBlue);  // 10:00am Turn Blue Lights On & Turn Dial2 to Blue

// White ON
Alarm.alarmRepeat(9,30,0, LightWhite);  // 11:00am Turn White Lights On & urn Dial2 to White

// White OFF
Alarm.alarmRepeat(18,30,0, LightBlue);  // 8:00pm Turn White Lights Off & Turn Dial2 to Blue

// Royal Blue OFF
Alarm.alarmRepeat(20,30,30, LightOff);  // 10:00pm Turn Blue Lights Off & Turn Dial2 to Zero

// Dose NoPoX
Alarm.alarmRepeat(13,00,00, Relay3ON);  // 11:00pm Turn Dosing Pump On
Alarm.alarmRepeat(13,03,00, Relay3OFF);  // 11:01pm Turn Dosing Pump Off
Alarm.alarmRepeat(13,00,00, DialDose);   //  11:00pm Turn Dial3 to Dose
Alarm.alarmRepeat(13,03,00, DialDoseSet);   // 11:01pm Turn Dial2 to Zero and Dial 3 back to Fan status

}



 void loop()
{

  
// *****************************----------------------------------------------------------------------------------  
//  Print Time out for Serial port logs
// *****************************

  DateTime now = RTC.now(); 
  setTime(now.hour(),now.minute(),now.second(),now.day(),now.month(),now.year());
    Serial.print("Arduino Time :  ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
  
// *****************************----------------------------------------------------------------------------------  
//  Light Manual Button Control  
// *****************************


  int buttonState = digitalRead(pushButton); // read the input pin for button state:
  Serial.print("Button State :  ");
  Serial.println(buttonState); // print out the state of the button:
  Serial.print("Light State :  ");
  Serial.println(lightstate); // print out the light state number:
  
  if (buttonState == 1)   // If the buttom is pressed change light state number from 0 to 3
{
    if (lightstate == 4)
    {
    lightstate = 0;
    }
    else
    {
    lightstate = (lightstate+1);
    }
}


// *****************************----------------------------------------------------------------------------------  
//  Light State Control  
// *****************************

// lightstate 0 is Off
// lightstate 1 is Blue Only
// lightstate 2 is Blue & White
// lightstate 3 is White (Not used in Time setting)


if (lightstate == 0)
    {
        if (lastlight != 0)
        {
          Relay1OFF();  //White Lights Off
          Relay2OFF();  //Blue Lights Off
          DialSet();  //Turn Dial2 to Off
          lastlight = 0;
        } 
    }

if (lightstate == 1)
    {
        if (lastlight != 1)
        {            
          Relay2ON();  //Turn Blue Lights On
          Relay1OFF();  //White Lights Off
          DialBlue();  //Turn Dial2 to Blue
          lastlight = 1;
        } 
    }

if (lightstate == 2)
    {
        if (lastlight != 2)
        {   
          Relay2ON();  //Turn Blue Lights On
          Relay1ON();  //Turn White Lights On
          DialWhite();  //Turn Dial2 to White
          lastlight = 2;
        }  
  }

if (lightstate == 3)  // Only used as a Manual setting
    {
        if (lastlight != 3)
        {          
          Relay1ON();  //White Lights Off
          Relay2OFF();  //Blue Lights Off
          DialSet();  //Turn Dial2 to Off
          lastlight = 3;
        }  
    }
  

// *****************************----------------------------------------------------------------------------------  
//  LED Control  
// *****************************
  
digitalWrite(powerled, HIGH);   // turn the LED on (HIGH is the voltage level)


Alarm.delay(0); // Alarm Script needs this delay call even if 0

Part 2

// *****************************----------------------------------------------------------------------------------
// Temperature Check and Display
// *****************************

for(tempi = 0;tempi<=7;tempi++){    // gets 8 samples of temperature
  
  samples[tempi] = ( 5.0 * analogRead(pin) * 100.0) / 1024.0;
  tempc = tempc + samples[tempi];
//  delay(1000);
}
tempc = tempc/8.0; // better precision finding average

tempc = tempc + 3; // Temp Error corection and calidration

Serial.print("Water Temp : ");
Serial.println(tempc, DEC); // Test Print to serial port
Serial.println(" ");

if (tempc > 40)   // Check and drop temp if its over the max of 40 to protect dial1
{
  tempc = 20;
}

analogWrite(dialone, (tempc - 15) * 10);  // Calculate and display on Analogue one temp

tempc = 0;  // reset Tempc

digitalWrite(powerled, LOW);

delay(500);               // wait for a second


// *****************************----------------------------------------------------------------------------------
// Temperature Check and Humidity
// *****************************


int chk = DHT11.read(DHT11PIN);

  Serial.print("DHT: ");
  switch (chk)
  {
    case 0: Serial.println("OK"); break;
    case -1: Serial.println("Checksum error"); break;
    case -2: Serial.println("Time out error"); break;
    default: Serial.println("Unknown error"); break;
  }

  htemp = DHT11.temperature; // Get the temperature form the DHT11
  htemp = htemp - 2; // Calibration of Temp on the DHT11
  Serial.print("Hood Temp : ");
  Serial.println(htemp);

  hhume = DHT11.humidity; // Get the Humidity form the DHT11 
  Serial.print("Hood Humidity : ");
  Serial.println(hhume);

  CleanAir();  // Check Air routine based on above

}
 
// *****************************----------------------------------------------------------------------------------
// Relay Initial Off
// *****************************

void RelaySet(){
   digitalWrite(RELAY1,HIGH);          // Turns Relay 1 Off
   digitalWrite(RELAY2,HIGH);          // Turns Relay 2 Off
   digitalWrite(RELAY3,HIGH);          // Turns Relay 3 Off 
   digitalWrite(RELAY4,HIGH);          // Turns Relay 4 Off
   Serial.println("Relays all reset to Off");   
}

 
// *****************************----------------------------------------------------------------------------------
// Dial Commands for Dials 2 and 3
// *****************************

void DialSet(){
   analogWrite(dialtwo,0); // set dial2 to read 0
   Serial.println("Light Dial 2 Reset");
}   
   
void DialWhite(){
   analogWrite(dialtwo,51); // Point Dial2 to BW (Blue White)
   Serial.println("Light Dial 2 Set BW");
}  
 
void DialBlue(){
   analogWrite(dialtwo,204); // Point Dial2 to RB (Royal Blue)
   Serial.println("Light Dial 2 Set RB");
}

void DialDose(){
   analogWrite(dialthree,130); // Point Dial3 to Dose Middle
   Serial.println("Light Dial 3 Set Dose");
}


void DialFan(){
   analogWrite(dialthree,250); // Point Dial3 to Fan End
   Serial.println("Light Dial 3 Set Fan On");
}

void DialDoseSet() // Checks and sets Dial 3 back to fan setting after diplaying dose
{
 if (hoodfan == 0){ 
    analogWrite(dialthree,10);
 }
 if (hoodfan == 1){
    analogWrite(dialthree,250);
 }    
}


// *****************************----------------------------------------------------------------------------------
// Relay Activation and test for Clean air
// *****************************

void CleanAir()
{
  
hoodcheck=0;  //Set the check to zero to begin

if (htemp > 35)   // Check and alert Fan is Hood Temp is over value
{hoodcheck=1;}

if (hhume > 35)   // Check and alert Fan is Hood Humidity is over value
{ hoodcheck=1;}

if (hoodcheck>0)
{
Serial.println("Air Check FAIL");
  if (hoodfan == 0)
  {
    Relay4ON();
   Serial.println("Clean Air Fan ON");
   analogWrite(dialthree,250); // set dial 3 to fan on
   hoodfan=1;
  }
}

if (hoodcheck==0)
{
Serial.println("Air Check PASS");
if (hoodfan == 1)
  {
   Relay4OFF();
   Serial.println("Clean Air Fan OFF");
   analogWrite(dialthree,10); // set dial 3 to fan off
   hoodfan=0;
  }
}

Serial.println("Clean Air Check Complete");  
     
}


// *****************************----------------------------------------------------------------------------------
// Light Timers Function Section - Needs a call in Setup with a Alarm Times
// *****************************

// lightstate 0 is Off
// lightstate 1 is Blue Only
// lightstate 2 is Blue & White
// lightstate 3 is White (Not used in Time setting)

void LightBlue(){
  lightstate = 1;       
}

void LightWhite(){
  lightstate = 2;          
}

void LightOff(){
  lightstate = 0;        
}


// *****************************----------------------------------------------------------------------------------
// Relay Timers Function Section - Needs a call in Setup with a time
// *****************************

void Relay1ON(){
  Serial.println("Relay 1 On - White Light");
  digitalWrite(RELAY1,LOW);           // Turns ON Relays 1  (White Lights)
}
void Relay1OFF(){
  Serial.println("Relay 1 Off - White Light");
  digitalWrite(RELAY1,HIGH);           // Turns OFF Relays 1  (White Lights)
}

void Relay2ON(){
  Serial.println("Relay 2 On - Blue Light");
  digitalWrite(RELAY2,LOW);           // Turns ON Relays 2  (Blue Lights)
}
void Relay2OFF(){
  Serial.println("Relay 2 Off - Blue Light");
  digitalWrite(RELAY2,HIGH);           // Turns OFF Relays 2  (Blue Lights)
}


void Relay3ON(){
  Serial.println("Relay 3 On - Dosing Pump");
  digitalWrite(RELAY3,LOW);           // Turns ON Relays 3   (Doseing Pump)
}
void Relay3OFF(){
  Serial.println("Relay 3 Off - Dosing Pump");
  digitalWrite(RELAY3,HIGH);           // Turns OFF Relays 3   (Doseing Pump)
}

void Relay4ON(){
  Serial.println("Relay 4 On");
  digitalWrite(RELAY4,LOW);           // Turns ON Relays 4   (Hood Fan)
}
void Relay4OFF(){
  Serial.println("Relay 4 Off");
  digitalWrite(RELAY4,HIGH);           // Turns OFF Relays 4   (Hood Fan)
}

Had to split it as it seemed to be above the max num of Chars per post !

UKHeliBob:

the code is below …..

I can't see anything wrong with it, but then again I can't see any code ...

BigMrTong:
It has been working in a project bix now for a year.

Since code doesn't go bad over time you have a hardware problem on your hands.

Since you already swapped out the relay board I suspect that back emf from the relays has already damaged your Arduino. Try replacing it. However you should check the power supply (voltage) in your circuit and on your Arduino before hand to make sure they are correct.

Of course this is all conjecture based on what you said but if you show some schematics it would really help.

If you are having random strange behavior and lockups, it may be worth exploring whether you are running out of SRAM. I recently had some code that was working right "suddenly" stop working and start hanging my chips after a change that I thought was innocuous turned out not to be.

You can use this function to print the amount of available memory as your program runs, and see if you are getting close to running out.

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Another easy test to see if SRAM is your problem is to just upload the blinkwithoutdelay example sketch and let it run for a while and see if it hangs. If it runs for a while, your hardware is probably fine.

Yes one of my thoughts. I have ordered a new Arduino to check this.

Interestingly, all the Buttons, LED's running from the Arduino and analogue dials I use all continue to act and read as they should and buttons respond. Everything that runs in the loop. It just seems to be TimeAlarms include I use and the Serial monitor that lock up as soon as a relay is activated.

I have not got a drawing as it has that much stuff plugged into it.

mstanley:

BigMrTong:
It has been working in a project bix now for a year.

Since code doesn't go bad over time you have a hardware problem on your hands.

Since you already swapped out the relay board I suspect that back emf from the relays has already damaged your Arduino. Try replacing it. However you should check the power supply (voltage) in your circuit and on your Arduino before hand to make sure they are correct.

Of course this is all conjecture based on what you said but if you show some schematics it would really help.

Sounds plausible, How do I output the code below to the serial window to view ?
sorry cracked it .. Serial.println(freeRam());

Ill run it now and test

joshuabardwell:
If you are having random strange behavior and lockups, it may be worth exploring whether you are running out of SRAM. I recently had some code that was working right "suddenly" stop working and start hanging my chips after a change that I thought was innocuous turned out not to be.

You can use this function to print the amount of available memory as your program runs, and see if you are getting close to running out.

int freeRam () {

extern int __heap_start, *__brkval;
 int v;
 return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Free SRAM starts at 754 and stays that way at all times.

Anyone any ideas why when I compile the script and upload it , its not setting the RTC time like it used too ?

BigMrTong:
Anyone any ideas why when I compile the script and upload it , its not setting the RTC time like it used too ?

I suspect (based on your #includes) you're using the Adafruit RTC breakout board, right?

According to your code, the RTC is only set (to the sketch build time) if it's not "running" during startup. As per RTCLib.cpp and the DS1307 datasheet (page 8), the isrunning method used for that check looks at the "clock halt" bit in the "seconds" register of the DS1307 chip. That "clock halt" bit is set when the DS1307 is powered up and remains so until overwritten when the RTC is set to a valid time.

As far as I can see, there's an on-board battery on that Adafruit board, so I guess the DS1307 has always been in "running" mode during Arduino startup ever since you started it up for the first time, and therefore its time isn't being set.

To have your code set the time of the RTC module, remove and replace its battery before starting the Arduino board.

I am indeed using the breakout board with inboard battery and it never stops running. Ill give this a go ! appreciate your time !!!

I think I may have found the issue but am still testing. I thought I would do an update for when this shows on search engines and for those kind enough to spend time looking at it for me. (I hate it when you see your issue posted and there is no post with the final solution)

I swapped out the relay board and the Arduino and all was the same. After 1 or 2 switches of the Relays, the Arduino would freeze its Serial logging and comms, but the core Loop script would keep running. As it had worked for a year and I thought I had done nothing, I like a lot of you assumed it was a hardware fault and suspected the relays themselves.

Thanks to you guys above it gave me a few more clues and started me thinking, What have I done? I must of changed something.

No, the only thing I have changed is some of the alarm timings to alter the light times, and I have done that a few times

I then had a thought whilst scrolling many times through the script. I had created the code originally and been using IDE 1.0.3

I had in the last few weeks downloaded and been using 1.0.5 Most of my Arduino scripts I ran through this and they all compiled without errors.

However, I also suspected maybe the fault was in the "TimeAlarms.h" I had included to handle the timed events. Putting the two together I decided to recompile the whole lot back in 1.0.3 and upload it to the Arduino. This seems to have worked. I need to let it run longer to be sure, but it looks like the issue is TimeAlarms.h include does not like the new 1.0.5 IDE software.