I am having an issue where my project freezes after a few hours, roughly 6-8. I just changed how it gathers and sends data using the millis function. Before adding the millis function i could run the sketch for over 24 hours without a problem.
#include <LiquidCrystal.h> // includes the LiquidCrystal Library
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7)
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
bool firstLoop = true;
bool fanOveride = false;
bool switched = false;
bool timerOn = false;
bool setupMode = false;
bool setupDone = false;
bool timerSetup = false;
bool setPointSetup = false;
double setPoint = 400;
int TVOC;
int CO2;
int highTvocCount = 0;
int setupSelect = 1;
int buttonCount = 0;
int multiply = 1;
int timerHrs = 0;
int dataTimerMin = 0;
int dataTimerHr = 0;
int dataTimerDay = 0;
int remainingTime;
unsigned long startTime;
unsigned long elapsedTime;
unsigned long dataTimerEnd;
unsigned long lcdDataTimer;
unsigned long timerDuration = 600;
unsigned long timerDurationMinusHrs = 0;
void setup() {
lcd.begin(16, 2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display }
Serial.begin(9600);
Serial.println("CCS811 test");
if (!ccs.begin()) {
Serial.println("Failed to start sensor! Please check your wiring.");
lcd.setCursor(0, 0);
lcd.print("check sensor");
while (1)
;
}
// Wait for the sensor to be ready
while (!ccs.available())
;
//Start Up LCD Display
lcd.setCursor(1, 0);
lcd.print("Air Nobel Pro");
delay(1000); // 1 second delay
lcd.setCursor(1, 1);
lcd.print("VOC Controller");
delay(2000);
lcd.clear(); // Clears the display
//Pin Mode Setup
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
//CCS118 SETUP
ccs.setDriveMode(1);
ccs.setBaseline(54206);
//Data Timer Setup
dataTimerEnd = 0;
lcdDataTimer = 0;
}
void loop() {
// Read the button state
int buttonState = digitalRead(2);
if (buttonState == LOW) { // Button is pressed
if (!setupMode) {
// Enter setup mode
setupMode = true;
Serial.println("Entering setup mode...");
lcd.clear();
lcd.print("Entering");
lcd.setCursor(0, 1);
lcd.print("Setup");
delay(500);
lcd.clear();
// Perform setup mode actions here
} else {
// Exit setup mode
setupMode = false;
Serial.println("Exiting setup mode...");
lcd.clear();
setupDone = false;
}
// Add a delay or other debounce mechanism to prevent rapid toggling
delay(500); // Adjust as needed
}
// ========================================================================================
// SETUP MODE START
//=========================================================================================
if (setupMode) {
if (setupDone == true) {
}
if (setupDone == false) {
while (setupSelect == 1 and setPointSetup == false and timerSetup == false) {
lcd.setCursor(0, 0);
lcd.print("Setpoint Setup");
if (digitalRead(3) == LOW or digitalRead(4) == LOW) {
setupSelect = 2;
Serial.println("Mode Switched");
lcd.clear();
delay(500);
}
if (digitalRead(2) == LOW or buttonCount > 0) {
setPointSetup = true;
delay(500);
}
}
while (setupSelect == 2 and setPointSetup == false and timerSetup == false) {
lcd.setCursor(0, 0);
lcd.print("Timer Setup");
if (digitalRead(3) == LOW or digitalRead(4) == LOW) {
Serial.println("Mode Switched");
setupSelect = 1;
lcd.clear();
delay(500);
}
if (digitalRead(2) == LOW or buttonCount > 0) {
timerSetup = true;
Serial.println("Enter Timer Setup");
delay(500);
}
}
}
//===========Set Point Setup START============================================
while (setPointSetup == true) {
//Print Set Point setup title
lcd.setCursor(0, 0);
lcd.print("Choose Set Point");
//Multiply setup for holding button making indexing faster
if (digitalRead(3) == HIGH and digitalRead(4) == HIGH) {
buttonCount = 1;
multiply = 1;
}
if (buttonCount > 7) {
multiply = 5;
}
if (buttonCount > 15) {
multiply = 10;
}
if (buttonCount > 25) {
multiply = 50;
}
if (setPoint < 50) {
multiply = 5;
buttonCount = 1;
}
if (setPoint < 10) {
multiply = 1;
buttonCount = 1;
}
//Add to Set Point with "UP" button
if (digitalRead(3) == LOW) {
setPoint = setPoint + multiply;
buttonCount = buttonCount + 1;
delay(100);
Serial.print("button Count: ");
Serial.println(buttonCount);
}
//Remove from Set Point with "DOWN" button
if (digitalRead(4) == LOW and setPoint > 0) {
setPoint = setPoint - multiply;
buttonCount = buttonCount + 1;
delay(100);
Serial.print("button Count: ");
Serial.println(buttonCount);
}
//Print current Set Point
lcd.setCursor(0, 1);
if (setPoint < 1000) {
lcd.print(" ");
if (setPoint < 100) {
lcd.print(" ");
if (setPoint < 10) {
lcd.print(" ");
}
}
}
lcd.print(setPoint, 0);
delay(25);
//Set Value by pressing set button
if (digitalRead(2) == LOW) {
setPointSetup = false;
lcd.clear();
lcd.print("Set Point Saved");
lcd.setCursor(0, 1);
lcd.print(setPoint, 0);
delay(1500);
lcd.clear();
setupMode = false;
}
}
//----------------Set Point Setup END---------------------------------
//===============Timer Setup START====================================
while (timerSetup == true) {
lcd.setCursor(0, 0);
lcd.print("Run Time");
//Multiply count for holding button
if (buttonCount > 5) {
multiply = 5;
}
if (buttonCount > 10) {
multiply = 30;
}
if (buttonCount > 15) {
multiply = 60;
}
if (buttonCount > 20) {
multiply = 300;
}
if (buttonCount > 25) {
multiply = 600;
}
//Increase Timer Duration when "UP" button pushed
if (digitalRead(3) == LOW) {
timerDuration = (timerDuration + multiply);
buttonCount = buttonCount + 1;
Serial.print("button Count: ");
Serial.println(buttonCount);
Serial.print("multiply: ");
Serial.println(multiply);
delay(150);
}
//Decrease Timer Duration when "DOWN" button pushed
if (digitalRead(4) == LOW and timerDuration > 0) {
if (timerDuration < 1201 and buttonCount > 25) {
multiply = 600;
}
if (timerDuration < 901 and buttonCount > 20) {
multiply = 300;
}
if (timerDuration < 301 and buttonCount > 15) {
multiply = 60;
}
if (timerDuration < 61 and buttonCount > 10) {
multiply = 10;
}
if (timerDuration < 30 and buttonCount > 5) {
multiply = 5;
}
if (timerDuration < 10) {
multiply = 1;
}
timerDuration = (timerDuration - multiply);
buttonCount = buttonCount + 1;
Serial.print("button Count: ");
Serial.println(buttonCount);
Serial.print("multiply: ");
Serial.println(multiply);
delay(150);
}
//......Print Current Timer Duration............
lcd.setCursor(0, 1);
//Calcualte minutes
double timerDurationMin = timerDuration / 60;
//Calculate Seconds
int timerDurationSec = timerDuration % 60;
//Print Minutes
if (timerDurationMin < 100) {
lcd.print(" ");
if (timerDurationMin < 10) {
lcd.print(" ");
}
}
lcd.print(timerDurationMin, 0);
lcd.print("m ");
//Print Seconds
if (timerDurationSec < 10) {
lcd.print(" ");
}
lcd.print(timerDurationSec);
lcd.print("s");
// Reset Button Count
if (digitalRead(3) == HIGH and digitalRead(4) == HIGH) {
buttonCount = 1;
multiply = 1;
}
//Set Timer when "SET" button Pushed
if (digitalRead(2) == LOW) {
lcd.clear();
lcd.print("Timer Set For");
lcd.setCursor(0, 1);
lcd.print(timerDuration / 60);
lcd.print("m ");
lcd.print(timerDurationSec);
lcd.print("s");
delay(1500);
timerSetup = false;
setupMode = false;
lcd.clear();
}
}
//----------------Timer Setup END--------------------------------------------
delay(250);
//----------------------------------------------------------------------------------------------
// SETUP MODE END
//----------------------------------------------------------------------------------------------
//================================================================================================
// RUN MODE
//================================================================================================
} else {
//============================Manual Fan START==================================================
while (digitalRead(3) == LOW and buttonCount < 12) {
buttonCount = buttonCount + 1;
Serial.println(buttonCount);
delay(100);
while (buttonCount > 10 and digitalRead(3) == LOW) {
if (switched == false) {
switched = true;
timerOn = !timerOn;
if (timerOn == false) {
lcd.clear();
lcd.print("Timer OFF");
}
if (timerOn == true) {
lcd.clear();
lcd.print("Timer ON");
startTime = millis();
Serial.print("Start Time: ");
Serial.println(startTime);
}
}
}
}
//-----------------------Manual Fan END------------------------------------------------------------
//============================ Fan Overide START==================================================
while (digitalRead(4) == LOW and buttonCount < 12) {
buttonCount = buttonCount + 1;
Serial.println(buttonCount);
delay(100);
while (buttonCount > 10 and digitalRead(4) == LOW) {
if (switched == false) {
switched = true;
fanOveride = !fanOveride;
Serial.println("Overide");
if (fanOveride == false) {
lcd.clear();
lcd.print("Overide OFF");
}
if (fanOveride == true) {
lcd.clear();
lcd.print("Overide ON");
if (digitalRead(4) == HIGH) {
}
}
}
}
}
//----------------------- Fan Overide END------------------------------------------------------------
if (digitalRead(3) == HIGH and digitalRead(4) == HIGH) {
buttonCount = 0;
switched = false;
}
//====================================================================================================================================================
//===========PRINT MEASUREMENTS START=========================================================================================================================
//====================================================================================================================================================
if (ccs.available()) {
if (!ccs.readData()) {
if (lcdDataTimer < millis()) {
lcdDataTimer = millis() + 1500;
TVOC = ccs.getTVOC();
CO2 = ccs.geteCO2();
//Print TVOC-------------------------------------------------------------------------------
lcd.setCursor(0, 0);
lcd.print("TVOC:");
if (TVOC < 1000) {
lcd.print(" ");
if (TVOC < 100) {
lcd.print(" ");
if (TVOC < 10) {
lcd.print(" ");
}
}
}
lcd.print(TVOC);
lcd.print("ppb");
//Print CO2--------------------------------------------------------------------------------
lcd.setCursor(0, 1);
lcd.print("CO2: ");
if (CO2 < 1000) {
lcd.print(" ");
if (CO2 < 100) {
lcd.print(" ");
if (CO2 < 10)
lcd.print(" ");
}
}
lcd.print(CO2);
lcd.print("ppm");
}
//Serial Data------------------------------------------------------------------------------
if (dataTimerEnd < millis()) {
dataTimerEnd = millis() + 300000;
if (firstLoop == false) {
//Data Timer day:hour:minute SETUP
dataTimerMin = dataTimerMin + 5;
if (dataTimerMin == 60) {
dataTimerMin = 0;
dataTimerHr = dataTimerHr + 1;
if (dataTimerHr == 24) {
dataTimerHr = 0;
dataTimerDay = dataTimerDay + 1;
}
}
}
//Print Recording Time
if (dataTimerDay < 10) {
Serial.print("0");
}
Serial.print(dataTimerDay); //Print Day
Serial.print(":");
if (dataTimerHr < 10) {
Serial.print("0");
}
Serial.print(dataTimerHr); //Print Hour
Serial.print(":");
if (dataTimerMin < 10) {
Serial.print("0");
}
Serial.print(dataTimerMin); //Print Min
//TVOC to Serial
Serial.print(" TVOC: ");
if (TVOC < 1000) {
Serial.print(" ");
if (TVOC < 100) {
Serial.print(" ");
if (TVOC < 10) {
Serial.print(" ");
}
}
}
Serial.print(TVOC); //Print TVOC
//CO2 to Serial
Serial.print(" CO2: ");
if (CO2 < 1000) {
Serial.print(" ");
if (CO2 < 100) {
Serial.print(" ");
if (CO2 < 10) {
Serial.print(" ");
}
}
}
Serial.print(CO2); //Print CO2
//Baseline to Serial
Serial.print(" Baseline: ");
Serial.println(ccs.getBaseline()); //Print Baseline
}
//-------------------------------------------------------------------------------------------------------------------------------------------------
//---------PRINT MEASUREMENTS END--------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------------
//====================Timer START====================================
if (timerOn == true and fanOveride == false) {
Serial.print("Start Time: ");
Serial.print(startTime);
//Calculate Minutes and Seconds
elapsedTime = millis() - startTime;
remainingTime = (timerDuration * 1000 - elapsedTime) / 1000;
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
lcd.setCursor(0, 1);
lcd.print("Shut Off ");
//Print Timer Minutes
if (minutes < 10) {
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
//Print Timer Seconds
if (seconds < 10) {
lcd.print("0");
}
lcd.print(seconds);
if (remainingTime < 0) {
lcd.clear();
timerOn = false;
}
}
//-------------------------Timer END-----------------------------------------------------------
delay(500);
//===================Fan Control START=========================================================
//Fan Overide to turn fan off
if (fanOveride == true) {
digitalWrite(5, LOW);
}
//Turn fan on if reading high or timer is on
if ((ccs.getTVOC() > setPoint || timerOn == true) and digitalRead(5) != HIGH and fanOveride == false) {
digitalWrite(5, HIGH);
startTime = millis();
timerOn = true;
}
// Reset Timer if Reading is still high
if (ccs.getTVOC() > setPoint and timerOn == false) {
startTime = millis();
timerOn = true;
}
//Turn fan off when timer is done and reading is safe
if (ccs.getTVOC() < setPoint and timerOn == false and digitalRead(5) != LOW) {
digitalWrite(5, LOW);
}
//Print messages
if (highTvocCount > 9) {
highTvocCount = 0;
}
highTvocCount = highTvocCount + 1;
if (fanOveride == true) {
if (ccs.getTVOC() < setPoint) {
if (highTvocCount > 7 and highTvocCount < 9) {
lcd.setCursor(0, 1);
lcd.print("Overide On ");
delay(1000);
lcd.clear();
}
}
}
if (ccs.getTVOC() > setPoint and highTvocCount > 6 and highTvocCount < 8) {
lcd.setCursor(0, 1);
lcd.print("TVOC TOO HIGH ");
delay(1000);
lcd.clear();
}
digitalWrite(6, digitalRead(5));
//------------------Fan Control END--------------------------------------------------------------
} else {
lcd.clear();
lcd.print("ERROR!");
lcd.setCursor(0, 1);
lcd.print("Sensor Connection");
while (1)
;
}
}
firstLoop = false;
}
//-----------------------------------------------------------------------------------------------------
// **RUN MODE END**
//-----------------------------------------------------------------------------------------------------
}

