Hi.
I've built a humidity and temperature controller for an incubator that runs the code shown below.
I'ts my first project in arduino ever, but it works perfectly, except for that the codes stops running and the LCD screen goes blank and eventually turns off after a few hours.
It's based on a Arduino Mega, its connected to two bme280 humid/temperature sensors , four ds18b20 temperature sensors, one LCD display, a 8x relay (no external power) and a 16x relay (with external power). Both the arduino mega and the 16x relay are powered with separate 12v 1a power supplies.
My local electronic dealer suggested it was overheating so i installed a fan, which didn't solve the issue.
Everything is wired up as it should, and since it runs perfectly for 7-14 hours, it seems more like it's a programming issue, rather than a hardware issue.
I read online it could be related to memory, I'm not sure why that could be and how to fix it. other suggestions are welcome as well.
Also when I verifies the code in platformio, it looks like there is plenty of memory left.
additional info that might not be relevant:
the reason there is 2 separate relays, is because when it turned on a 230v 5a heating element on the 8x relay, the arduino would slowly lose power and reboot. Therefor it was necessary to use a externally powered relay. But I didnt wanna redo all the wiring for all the low current electronics that ran without a problem on the 8x relay. That's why I use two relay modules. Also it seems that the arduino can run on the power supplied from the 16x relays external power supply, without its own power supply connected as well. so the problem should not be rooted in insufficient power.
#include <Arduino.h>
//------Temperature------
//Temperature goal Koji
float TG_koji = 35; //temperature goal for koji
//Temperature range koji
float TH_koji = 0.5; //high temperature range for koji
float TL_koji = 0.25; //low temperature range for koji
//Temperature goal air
float TG_air = 35; //temperature goal for air
//Temperature range air
float TH_air = 2; //high temperature range for air
float TL_air = 0; //low temperature range for air
//------Humidity------
//humidity goal
float HG_air = 75; //humidity goal
//humidity range
float HH_air = 5; //low humidiy range
float HL_air = 0; //high humidity range
//--advandced controls---
float Air_T_avg_1 = 5; //Koji_T_avg=TG_koji & Air_T_avg>TG_air
float T_koji_2 = 2; //Koji_T_avg>TG_koji & Air_T_avg=TG_air
float T_koji_3 = 2; //Koji_T_avg>TG_koji & Air_T_avg<TG_air
float T_koji_4 = 2; //Koji_T_avg>TG_koji & Air_T_avg>TG_air
//------libraries------
//import libraries for DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
//import libraries for BME280
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
//import libraries for LCD
#include <LiquidCrystal_I2C.h>
//------defines-------
//BME280
#define SEALEVELPRESSURE_HPA (1013.25)
//DS18B20
#define ONE_WIRE_BUS 2
//------objects-------
Adafruit_BME280 bme1; //Creates a bme280 object called "bme" with
Adafruit_BME280 bme2; //Creates a bme280 object called "bme" with
OneWire oneWire(ONE_WIRE_BUS); //Creates a one-wire object called "oneWire", usinge "one_wire_bus" as reference.
DallasTemperature sensors(&oneWire); //Creates a DS18B20 object called sensors, using the "oneWire" as reference.
LiquidCrystal_I2C lcd(0x27,20,4); //Sets the LCD address to x for a 20 chars and 4 line display
uint8_t T1[8] = { 0x28, 0xFF, 0x64, 0x02, 0xE9, 0x25, 0x27, 0x96 }; //1
uint8_t T2[8] = { 0x28, 0xFF, 0x64, 0x02, 0xE9, 0x29, 0x02, 0xC7 }; //2
uint8_t T3[8] = { 0x28, 0xFF, 0x64, 0x02, 0xE9, 0x2E, 0x91, 0x5A }; //3
uint8_t T4[8] = { 0x28, 0xFF, 0x64, 0x02, 0xEB, 0xD5, 0x9C, 0x52 }; //4
//------variables-------
//relay pin and name
const int RELAY1 = 22;
const int RELAY2 = 23;
const int RELAY3 = 26;
const int RELAY4 = 28;
const int RELAY5 = 30;
const int RELAY6 = 32;
const int RELAY7 = 34;
const int RELAY8 = 36;
//humid
int circlationfan = RELAY7;
int humidifier1 = RELAY5;
//heater
int heatElement = RELAY2;
int heatFan = RELAY8;
//outlet
int outlet = RELAY6;
//serial
String serialtemperaturelogic;
String serialhumiditylogic;
String serialheatfanlogic;
String serialheatelementlogic;
String serialhumidifierlogic;
String serialoutletLogic;
//--loop--
unsigned long currentTime;
unsigned long previousTime;
unsigned int cycleTime = 10;
//sensor readings
float Air_T_bme1;
float Air_T_bme2;
float Air_H_bme1;
float Air_H_bme2;
float Air_T_avg;
float Air_H_avg;
float Koji_T_T1;
float Koji_T_T2;
float Koji_T_T3;
float Koji_T_avg;
float Koji_T_T4;
//-------code------
//lcd
void LCDstatus (){
lcd.clear();
lcd.print("Koji T:");
lcd.print(Koji_T_avg);
lcd.setCursor(0,1);
lcd.print("Air T:");
lcd.print(Air_T_avg);
lcd.setCursor(0,2);
lcd.print("Air H:");
lcd.print(Air_H_avg);
}
//outlet
void outletLogic(bool condition) {
if (condition==true) {
if (digitalRead(outlet)==LOW) {
digitalWrite(outlet, HIGH);
serialoutletLogic="Outlet status: OPEN";
}
}
else {
if (digitalRead(outlet)==HIGH) {
digitalWrite(outlet, LOW);
serialoutletLogic="Outlet status: CLOSED";
}
}
}
//humidifier
void humidifierLogic(bool condition) {
if (condition==true) {
if (digitalRead(humidifier1)==LOW ) {
digitalWrite(humidifier1, HIGH);
serialhumidifierlogic="Humidifier status: ON";
}
}
else {
if (digitalRead(humidifier1)==HIGH ) {
digitalWrite(humidifier1, LOW);
serialhumidifierlogic="Humidifier status: OFF";
}
}
}
//heat element
void heatelementlogic (bool condition){
if (condition==true) {
if (digitalRead(heatElement)==HIGH){
digitalWrite(heatElement, LOW);
serialheatelementlogic="Heat Element Status: ON";
}
}
else {
if (digitalRead(heatElement)==LOW) {
digitalWrite(heatElement, HIGH);
serialheatelementlogic="Heat Element Status: OFF";
}
}
}
//heat fan
void heatfanlogic (bool status){
if (status==true) {
if (digitalRead(heatFan)==LOW) {
digitalWrite(heatFan, HIGH);
serialheatfanlogic="Heat fan Status: ON";
}
}
else {
if (digitalRead(heatFan)==HIGH) {
digitalWrite(heatFan, LOW);
serialheatfanlogic="Heat fan Status: OFF";
}
}
}
//temperature logic
void temperatureLogic() {
if ((TG_koji-TL_koji)<Koji_T_avg && Koji_T_avg<(TG_koji+TH_koji) && (TG_air-TL_air)<Air_T_avg && Air_T_avg<(TG_air+TH_air)) {
heatelementlogic(true);
heatfanlogic(true);
serialtemperaturelogic="Koji_T_avg=TG_koji & Air_T_avg=TG_air";
}
else if ((TG_koji-TL_koji)<Koji_T_avg && Koji_T_avg<(TG_koji+TH_koji) && Air_T_avg<(TG_air-TL_air)) {
heatelementlogic(true);
heatfanlogic(true);
serialtemperaturelogic="Koji_T_avg=TG_koji & Air_T_avg<TG_air";
}
else if ((TG_koji-TL_koji)<Koji_T_avg && Koji_T_avg<(TG_koji+TH_koji) && Air_T_avg>(TG_air+TH_air)) {
heatelementlogic(false);
heatfanlogic(false);
serialtemperaturelogic="Koji_T_avg=TG_koji & Air_T_avg>TG_air";
if ((Air_T_avg-(TG_air-TL_air))>=Air_T_avg_1){
outletLogic(true);
serialtemperaturelogic="Koji_T_avg=TG_koji & Air_T_avg>TG_air +!";
}
else {
outletLogic(false);
}
}
else if (Koji_T_avg>(TG_koji+TH_koji) && (TG_air-TL_air)<Air_T_avg && Air_T_avg<(TG_air+TH_air)) {
heatelementlogic(false);
heatfanlogic(false);
serialtemperaturelogic="Koji_T_avg>TG_koji & Air_T_avg=TG_air";
if ((Koji_T_avg-(TG_koji+TH_koji))>=T_koji_2){
outletLogic(true);
serialtemperaturelogic="Koji_T_avg>TG_koji & Air_T_avg=TG_air +!";
}
else {
outletLogic(false);
}
}
else if (Koji_T_avg>(TG_koji+TH_koji) && Air_T_avg<(TG_air-TL_air)) {
heatelementlogic(false);
heatfanlogic(false);
serialtemperaturelogic="Koji_T_avg>TG_koji & Air_T_avg<TG_air";
Serial.println();
if ((Koji_T_avg-(TG_koji+TH_koji))>=T_koji_3){
outletLogic(true);
serialtemperaturelogic="Koji_T_avg>TG_koji & Air_T_avg<TG_air +!";
}
else {
outletLogic(false);
}
}
else if (Koji_T_avg>(TG_koji+TH_koji) && Air_T_avg>(TG_air+TH_air)) {
heatelementlogic(false);
heatfanlogic(false);
serialtemperaturelogic="Koji_T_avg>TG_koji & Air_T_avg>TG_air";
if ((Koji_T_avg-(TG_koji+TH_koji))>=T_koji_4){
outletLogic(true);
serialtemperaturelogic="Koji_T_avg>TG_koji & Air_T_avg>TG_air +!";
}
else {
outletLogic(false);
}
}
else if (Koji_T_avg<(TG_koji-TL_koji) && (TG_air-TL_air)<Air_T_avg && Air_T_avg<(TG_air+TH_air)) {
heatelementlogic(true);
heatfanlogic(true);
serialtemperaturelogic="Koji_T_avg<TG_koji & Air_T_avg=TG_air";
}
else if (Koji_T_avg<(TG_koji-TL_koji) && Air_T_avg<(TG_air-TL_air)) {
heatelementlogic(true);
heatfanlogic(true);
serialtemperaturelogic="Koji_T_avg<TG_koji & Air_T_avg<TG_air";
}
else if (Koji_T_avg<(TG_koji-TL_koji) && Air_T_avg>(TG_air+TH_air)) {
heatelementlogic(false);
heatfanlogic(false);
serialtemperaturelogic="Koji_T_avg<TG_koji & Air_T_avg>TG_air";
}
}
//humidity logic
void humidityLogic(){
if ((HG_air-HL_air)<Air_H_avg && Air_H_avg<(HG_air+HH_air)){
serialhumiditylogic="Air_H_avg=HG_air";
outletLogic(false);
humidifierLogic(false);
}
if (Air_H_avg<(HG_air-HL_air)){
serialhumiditylogic="Air_H_avg<HG_air";
outletLogic(false);
humidifierLogic(true);
}
if (Air_H_avg>(HG_air+HH_air)){
serialhumiditylogic="Air_H_avg>HG_air";
outletLogic(true);
humidifierLogic(false);
}
}
//Serial monitor messages
void Serialmonitorstatus (){
Serial.println("--------------------------------------------------------------------");
Serial.println("average koji temperature: ");
Serial.println(Koji_T_avg);
Serial.println();
Serial.println("Individual temperatures:");
Serial.println();
Serial.print("T1: ");
Serial.println(Koji_T_T1);
Serial.print("T2: ");
Serial.println(Koji_T_T2);
Serial.print("T3: ");
Serial.println(Koji_T_T3);
Serial.print("T4: ");
Serial.println(Koji_T_T4);
Serial.println();
Serial.println("average air temperature: ");
Serial.println(Air_T_avg);
Serial.println();
Serial.println("individual air temperature");
Serial.print("BME 1: ");
Serial.println(Air_T_bme1);
Serial.print("BME 2: ");
Serial.println(Air_T_bme2);
Serial.println();
Serial.println("average humidity:");
Serial.println(Air_H_avg);
Serial.println();
Serial.println("Individual humidity");
Serial.print("BME 1: ");
Serial.println(Air_H_bme1);
Serial.print("BME 2: ");
Serial.println(Air_H_bme2);
Serial.println();
Serial.println("----Logic----");
Serial.println("Time:");
Serial.print("currentime: ");
Serial.println(currentTime);
Serial.println();
Serial.println("Temperature:");
Serial.println(serialtemperaturelogic);
Serial.println(serialheatelementlogic);
Serial.println(serialheatfanlogic);
Serial.println();
Serial.println("Humidity:");
Serial.println(serialhumiditylogic);
Serial.println(serialhumidifierlogic);
Serial.println();
Serial.println("other:");
Serial.println(serialoutletLogic);
}
// -------------setup-------------
void setup(){
//serial boot
Serial.begin(9600);
Serial.print("booting up...");
Serial.println();
//LCD boot
lcd.init(); //initalizes the LCD
lcd.clear(); //clears display and moves cursor to top left corner
lcd.backlight(); //turns backlight on
lcd.noCursor(); //Hides the LCD cursor.
lcd.setCursor(0,0);
lcd.print("Koji ferminator v.1");
lcd.setCursor(0,1);
lcd.print("Booting up...");
//bme280 setup
bme1.begin(0x76);
bme2.begin(0x77);
//DS18B20 setup
sensors.begin();
//relay setup
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
pinMode(RELAY5, OUTPUT);
pinMode(RELAY6, OUTPUT);
pinMode(RELAY7, OUTPUT);
pinMode(RELAY8, OUTPUT);
//circulation fan
digitalWrite(circlationfan, HIGH);
}
//-----------loop-----------
void loop(){
currentTime = millis();
if (currentTime-previousTime >= cycleTime*1000) {
previousTime=currentTime;
//bme
Air_T_bme1 = bme1.readTemperature();
Air_T_bme2 = bme2.readTemperature();
Air_H_bme1 = bme1.readHumidity();
Air_H_bme2 = bme2.readHumidity();
//DS18B20
sensors.requestTemperatures();
Koji_T_T1 = sensors.getTempC(T1);
Koji_T_T2 = sensors.getTempC(T2);
Koji_T_T3 = sensors.getTempC(T3);
Koji_T_T4 = sensors.getTempC(T4);
//averages
Air_T_avg = (Air_T_bme1+Air_T_bme2)/2;
Air_H_avg = (Air_H_bme1+Air_H_bme2)/2;
Koji_T_avg = (Koji_T_T1+Koji_T_T2+Koji_T_T3+Koji_T_T4)/4;
//heat
temperatureLogic();
//humidity
humidityLogic();
//LCD
LCDstatus();
//serial
Serialmonitorstatus();
}
}