Code is freezing up after running for an hour or so

So I am only using the sersorReading() during debugging, that whole function is commented out during normal operation. I thought the switch case would just update the screen once ever time mode ticks over.

I deleted this earlier, but
you can call setup() just like any function.

Ok so I think I got it up and working properly. I implemented two different fixes, one that lowers the queries the I2C bus is making to two second intervals and using the Timeout function of the Wire library to handle any missed signals.



/**************************************************************************
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 <I2C.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "SparkFun_SCD30_Arduino_Library.h" 
//#include <MemoryFree.h>
// #include <pgmStrToRAM.h>

// Start the SCD30 air sensor                  
SCD30 airSensor;

// Setup the OLED display
#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     -1                                      // 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 byte lightswitchA = 13;
const byte lightswitchB = 12;
const byte waterswitchC = 11;
const byte fanswitchD = 10;
const byte controlswitchE = 9;

// outputs for SSR and control LED
const byte outputA = 8;
const byte outputB = 7;
const byte outputC = 6;
const byte outputD = 5;
const byte outputE = 4;

// Var to store state of switch
byte switchAstate = 0;
byte switchBstate = 0;
byte switchCstate = 0;
byte switchDstate = 0;
byte switchEstate = 0;

// Var for the timing function
const int interval = 2000;           // interval for (simulated) modula operator
unsigned long currentMillis;
unsigned long lastMillis;
int TimerA = 0;

// Var to store the sensor readings
int c; 
int t; 
int h; 
int lightsTime; 
int waterTime;
int tempF;

// Var for the switching of display
int mode = 0;

int wireTimeoutCount;
 
void setup() {                           
  
Serial.begin(9600);
  Serial.println(F("SCD30 And SD1306 Read and Write")); 
  Wire.begin(); 

// Different method for syncing the Time library with the RTC
//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);
  
// Warning of state of RTC
if(timeStatus()!= timeSet) 
     {Serial.println(F("Unable to sync with the RTC"));}
  else
     {Serial.println(F("RTC has set the system time"));}  

// Warning for SCD30 sensor       
 if (airSensor.begin() == false)
  {Serial.println(F("Air sensor not detected. Please check wiring. Freezing..."));
    while (1);}


// Establishes the pinMode inputs
pinMode(lightswitchA, INPUT_PULLUP);   
pinMode(lightswitchB, INPUT_PULLUP);    
pinMode(waterswitchC, INPUT_PULLUP);    
pinMode(fanswitchD, INPUT_PULLUP);    
pinMode(controlswitchE, INPUT_PULLUP);  

// 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
  

// Clear the buffer
  display.clearDisplay();
}



void loop() {
switchAstate = digitalRead(lightswitchA);
switchBstate = digitalRead(lightswitchB);
switchCstate = digitalRead(waterswitchC);
switchDstate = digitalRead(fanswitchD);
switchEstate = digitalRead(controlswitchE);

currentMillis = millis();
TimerA = currentMillis - lastMillis;

 if ( TimerA < interval ) 
 { return; }

 Wire.setWireTimeout(3000, true);
 wireTimeoutCount = 0;
 Wire.clearWireTimeoutFlag();

 if (TimerA >= interval)
    {lastMillis += interval;
    mode = (mode + 1) % 4;
    c = airSensor.getCO2();
    t = airSensor.getTemperature();
    h = airSensor.getHumidity();
    lightsTime = hour(); 
    waterTime = minute();
    }   
 
if(switchEstate == LOW)
{manualControl();}
else
{automaticControl();}
 

  printData();
//  sensorReading();
}

// This function prints the sensor readings and the date and time to the OLED display
void printData(){
  
//Serial.println(remainder);    
  
  switch (mode)
  {case 0:                                     // CO2 data                                
    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
    break;

   case 1:                                    // Temp data
    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
    break;
  
   case 2:
    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.print(h, 1);
    display.print("%");
    display.display();      // Show initial text
    break;

   case 3:
    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(3, 27);
    display.print(hourFormat12());
    display.print(F(":"));
    display.print(minute());
    display.print(F(":"));
    display.print(second());
    if (isAM() == HIGH)
      {display.print(F("AM"));}
    else
      {display.print(F("PM"));}
    display.setCursor(5,47);
    display.print(month());
    display.print(F("-"));
    display.print(day());
    display.print(F("-"));
    display.print(year()); 
    display.display();  
  }
  }

// This function is for the manual control of the SSR's
void manualControl(){

 digitalWrite(outputE, HIGH);

// send data to the OLED screen
//   printData();
//   sensorReading(); 
  
  digitalWrite(outputA, switchAstate);
  digitalWrite(outputB, switchBstate);  
  digitalWrite(outputC, switchCstate);
  digitalWrite(outputD, switchDstate);
}

// function to print sensor readings to the serial monitor 
void sensorReading(){
  if (TimerA >= 1950)
  { 
    Serial.println(switchAstate);
    Serial.println(switchBstate);
    Serial.println(switchCstate);
    Serial.println(switchDstate);
    Serial.println(switchEstate);
    
    Serial.print(F("co2(ppm):"));
    Serial.print(airSensor.getCO2());

    Serial.print(F(" temp(C):"));
    Serial.print(airSensor.getTemperature(), 1);

    Serial.print(F(" humidity(%):"));
    Serial.println(airSensor.getHumidity(), 1);

//    Serial.print(F("freeMemory:"));
//    Serial.println(freeMemory());  // print how much RAM is available in bytes.
  } 
}

void automaticControl(){

 digitalWrite(outputE, LOW);
  


//  Serial.print(F("hours:"));
//  Serial.println(lightsTime);

//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 <18)
   {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 == 9 || lightsTime == 13){
    if (waterTime >= 0 && waterTime <= 10)
    {digitalWrite(outputC, HIGH);}
    else if (waterTime > 10)
    {digitalWrite(outputC, LOW);}
   } 
}