Hello World,
I am working on a controller for a greenhouse and have the code working properly but I am running into an issue where the program freezes up after an half an hour and the board needs to be reset. I am not receiving any errors when I compile it and it works properly for a while. I am having to use the <DS1307RTC.h> library in place of the normal DS3231 library as I can't get it to function with the Time library properly. Here is the code...
/**************************************************************************
This is code to run a greenhouse. It uses the SCD30 airsensor and a DS3231 rtc module to take sensor readings and keep the date. It
has two functions, an automatic mode and a manual control mode. The automatic mode runs the SSR's controlling the various outputs
depending on the sensor readings. Manual Control allows the SSR's to be controlled by 4 switches along with a 5 to toggle between
modes.
This example is for a 128x64 pixel display using I2C to communicate
3 pins are required to interface (two I2C and one reset).
**************************************************************************/
// Libraries to include
#include <SPI.h>
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "SparkFun_SCD30_Arduino_Library.h"
// Start the SCD30 air sensor
SCD30 airSensor;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C //< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Input for the switch contol of SSR
const int lightswitchA = 3;
const int lightswitchB = 5;
const int waterswitchC = 6;
const int fanswitchD = 7;
const int controlswitchE = 12;
// outputs for SSR and control LED
const int outputA = 8;
const int outputB = 9;
const int outputC = 10;
const int outputD = 11;
const int outputE = 13;
// Var to store state of switch
int switchAstate = 0;
int switchBstate = 0;
int switchCstate = 0;
int switchDstate = 0;
int switchEstate = 0;
// interval for cumulating function and timing of screen display
const int interval = 8000;
unsigned long currentMillis;
unsigned long lastMillis;
int remainder = 0;
void setup() { // put your setup code here, to run once:
Serial.begin(9600);
Serial.println("SCD30 And SD3231 Read and Write");
Wire.begin();
// Warning of state of RTC
if(timeStatus()!= timeSet)
{Serial.println("Unable to sync with the RTC");}
else
{Serial.println("RTC has set the system time");}
// Warning for SCD30 sensor
if (airSensor.begin() == false)
{Serial.println("Air sensor not detected. Please check wiring. Freezing...");
while (1);}
// Establishes the pinMode inputs
pinMode(lightswitchA, INPUT);
pinMode(lightswitchB, INPUT);
pinMode(waterswitchC, INPUT);
pinMode(fanswitchD, INPUT);
pinMode(controlswitchE, INPUT);
// Establishes the pinMode OUTPUT
pinMode(outputA, OUTPUT);
pinMode(outputB, OUTPUT);
pinMode(outputC, OUTPUT);
pinMode(outputD, OUTPUT);
pinMode(outputE, OUTPUT);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
{Serial.println(F("SSD1306 allocation failed"));
for(;;);} // Don't proceed, loop forever
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(500); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
}
void loop() {
switchAstate = digitalRead(lightswitchA);
switchBstate = digitalRead(lightswitchB);
switchCstate = digitalRead(waterswitchC);
switchDstate = digitalRead(fanswitchD);
switchEstate = digitalRead(controlswitchE);
int c = airSensor.getCO2();
int t = airSensor.getTemperature();
float h = airSensor.getHumidity();
// alternate method to getting RTC data
//tmElements_t tm;
//RTC.read(tm);
//setTime(tm.Hour, tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year); //(hours, minutes, seconds, days, months, years)
// the function to get the time from the RTC
setSyncProvider(RTC.get);
currentMillis = millis();
remainder = currentMillis - lastMillis;
if (remainder >= interval)
{lastMillis += interval;}
if(switchEstate == HIGH)
{manualControl();
printData();}
else
{automaticControl();
printData();}
printData();
// sensorReading();
}
// This function prints the sensor readings and the date and time to the OLED display
void printData(){
int c = airSensor.getCO2();
int t = airSensor.getTemperature();
float h = airSensor.getHumidity();
if (remainder >= 0 && remainder <2000)
{display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(45, 0);
display.println(F("CO2"));
display.setTextSize(3); // Draw 2X-scale text
display.setCursor(35, 27);
display.println(c);
display.display(); // Show initial text
}
else if (remainder >= 2000 && remainder <4000)
{display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(32, 0);
display.println(F("Temp(F)"));
display.setTextSize(3); // Draw 2X-scale text
display.setCursor(35, 27);
display.println((int)(1.8*t+32));
display.display(); // Show initial text
}
else if (remainder >= 4000 && remainder <6000)
{display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(22, 0);
display.println(F("Humidity"));
display.setTextSize(3); // Draw 2X-scale text
display.setCursor(35, 27);
display.println(h, 1);
display.display(); // Show initial text
}
else
{display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(27, 0);
display.println(F("Time"));
display.setTextSize(2); // Draw 2X-scale text
display.setCursor(12, 27);
display.print(hourFormat12());
display.print(":");
display.print(minute());
display.print(":");
display.print(second());
display.setCursor(5,47);
display.print(month());
display.print("-");
display.print(day());
display.print("-");
display.print(year());
display.display(); // Show initial text
}
}
// This function is for the manual control of the SSR's
void manualControl(){
digitalWrite(outputE, HIGH);
// send data to the OLED screen
printData();
// sensorReading();
if(switchAstate == HIGH)
{digitalWrite(outputA, HIGH);}
else
{digitalWrite(outputA, LOW);}
if(switchBstate == HIGH)
{digitalWrite(outputB, HIGH);}
else
{digitalWrite(outputB, LOW);}
if(switchCstate == HIGH)
{digitalWrite(outputC, HIGH);}
else
{digitalWrite(outputC, LOW);}
if(switchDstate == HIGH)
{digitalWrite(outputD, HIGH);}
else
{digitalWrite(outputD, LOW);}
}
// function to print sensor readings to the serial monitor
void sensorReading(){
if (remainder == 2000 )
{
Serial.println(switchAstate);
Serial.println(switchBstate);
Serial.println(switchCstate);
Serial.println(switchDstate);
Serial.println(switchEstate);
Serial.print("co2(ppm):");
Serial.print(airSensor.getCO2());
Serial.print(" temp(C):");
Serial.print(airSensor.getTemperature(), 1);
Serial.print(" humidity(%):");
Serial.print(airSensor.getHumidity(), 1);
}
}
void automaticControl(){
digitalWrite(outputE, LOW);
int c = airSensor.getCO2();
int t = airSensor.getTemperature();
float h = airSensor.getHumidity();
int lightsTime = hour();
int waterTime = minute();
int tempF = (1.8*t+32);
//Send data to the OLED screen
printData();
//sensorReading();
// Fan Control based of temp 85F degrees
if (tempF >= 85)
{digitalWrite(outputD, HIGH);}
else
{digitalWrite(outputD, LOW);}
// Control of Lights 7am to 7pm on
if (lightsTime >= 7 && lightsTime <=19)
{digitalWrite(outputA, HIGH);
digitalWrite(outputB, HIGH);}
else
{digitalWrite(outputA, LOW);
digitalWrite(outputB, LOW);}
// Control of the watering, at 8am and 1pm for 10 minutes
if (lightsTime == 8 || lightsTime == 13){
if (waterTime >= 0 && waterTime <= 10)
{digitalWrite(outputC, HIGH);}
else if (waterTime > 10)
{digitalWrite(outputC, LOW);}
}
}
I have a stable working version that doesn't use the DS3231 RTC module and just relies on the millis() function to run and sync the time up but I don't want to run into the overflow issues after 50 days