Mushroom Fruiting Chamber Controller Nodemcu - blynk - wifimanager - Ota

Board Esp8266 Nodemcu 1.0
Blynk 0.61
Mushroom growining terrarium

I’m just starting my adventure with arduino programming. I’m not a programmer but by trial and error I managed to create something like this. It meets my expectations and even exceeds them and is still developing. Not all code is mine, I was inspired by other similar projects.

I’m looking for inspiration. If you see any mistakes in the code or something can be improved, I look forward to your suggestions :D.

Edit . corrected few things in heatmat control logic .



/**************************************
*  V0  ==  DHT Temperature            *
*  V1  ==  DHT Humidity               *
*  V2  ==  DHT HEATINDEX              *
*  V3  ==  StatusLED  ==  led         *
*  V4  ==  StatusLED  ==  fanIn       *
*  V5  ==  StatusLED  ==  fanOut      *
*  V6  ==  StatusLED  ==  humidifier  *
*  V7  ==  StatusLED  ==  heatmat     *
*  V8  ==  StatusLED  ==  dhtReaderror*
*  V11 ==  Led ON/OFF Button          *
*  V12 ==  FanIn ON/OFF Button        *
*  V13 ==  FanOut ON/OFF Button       *
*  V21 ==  Temoerature slider         *
*  V22 ==  Humidity slider            *
*  V30 ==  Terminal                   *
*                                     *             
*************************************/

#include <FS.h>
#include <ESP8266WebServer.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#include <DNSServer.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>          //last v5 build
#include <ArduinoOTA.h>
#include <EEPROM.h>


//DEFINE RELAY PINS
#define relayLED D2
#define relayFANin D3
#define relayFANout D4
#define relayFOGGER D5
#define relayHEATMAT D7

//DHT setup
#define DHTPIN D1
#define DHTTYPE DHT22
DHT dhtA(DHTPIN, DHTTYPE);

//Debug Console
#define BLYNK_PRINT Serial

//Timer
BlynkTimer timer;

// Attach virtual serial terminal to Virtual Pin V1
WidgetTerminal terminal(V30);                                      

//VARIABLES

char blynk_token[34] = "YOUR_BLYNK_TOKEN";              //added from WiFiManager - AutoConnectWithFSParameters

bool shouldSaveConfig = false;                          //flag for saving data

float humidity;
float temp;
float heatindex;
float tempDiff = 0.3;
int desiredTemp = 0;
int desiredHum = 0;
int humDiff = 5;
int previousDesiredTemp = 0;
int previousDesiredHum = 0;
int maximumTemp = 31;

//temperature comparition 
bool tempRising = false;
bool tempDroping = false;
bool tempStady = false;
float temp90sec;
float currentTemperature;
unsigned long previousMillis = millis();
long ninetySeconds = 90000L;



//Status Leds
WidgetLED led(V3);
WidgetLED fanIn(V4);
WidgetLED fanOut(V5);
WidgetLED humidifier(V6);
WidgetLED heatmat(V7);
WidgetLED dhtReaderror(V8);


// Buttons
BLYNK_WRITE(V11)                                 // Led ON/OFF Button 
  {
    if (param.asInt())
      {
        digitalWrite(D2, HIGH);
        led.on();
      }
    else
      {
        digitalWrite(D2, LOW);
        led.off();
      }
  }
BLYNK_WRITE(V12)                                 // FanIn ON/OFF Button
  {
    if (param.asInt())
      {
        digitalWrite(D3, HIGH);
        fanIn.on();
      }
    else
      {
        digitalWrite(D3, LOW);
        fanIn.off();
      }
  }

BLYNK_WRITE(V13)                                // FanOut ON/OFF Button 
  {
    if (param.asInt())
      {
        digitalWrite(D4, HIGH);
        fanOut.on();
      }
    else
      {
        digitalWrite(D4, LOW);
        fanOut.off();
      }
  }
BLYNK_WRITE(V14)  // Reset
{
if (param.asInt()==1) 
  {
   ESP.reset();
  } 
}

//Temoerature and humidity sliders
BLYNK_WRITE(V21)
  {
    desiredTemp = param.asInt();
  }
BLYNK_WRITE(V22)
  {
    desiredHum = param.asInt();                    
  }

//VOIDS

void sensorRead()
  {
    humidity = dhtA.readHumidity();
    temp = dhtA.readTemperature();
    heatindex = dhtA.computeHeatIndex(temp, humidity, false);
  }

void temperatureComparision()
  {
    if (millis() - previousMillis >= ninetySeconds) 
      {
        previousMillis += ninetySeconds;
        temp90sec = currentTemperature;
        currentTemperature = dhtA.computeHeatIndex(temp, humidity, false);

        terminal.clear();
        terminal.print("Actual temperature = ");
        terminal.print(currentTemperature);
        terminal.println("°C  ");
        terminal.print("Temperature 90s Ago  = ");
        terminal.print(temp90sec);
        terminal.println("°C  ");
        terminal.flush();
           
        if (currentTemperature > temp90sec) 
          {
            Serial.println(F("  - Warming"));
            terminal.print("Temperature is Warming");
            terminal.flush();
            tempRising = true;
            tempDroping = false;
            tempStady = false;
          }
        else if (currentTemperature < temp90sec) 
          {
            Serial.println(F("  - Cooling"));
            terminal.print("Temperature is Cooling ");
            terminal.flush();
            tempRising = false;
            tempDroping = true;
            tempStady = false;
          }
        else if (currentTemperature == temp90sec) 
          {
            Serial.println(F("  - Steady"));
            terminal.print("Temperature is Steady");
            terminal.flush();
            tempRising = false;
            tempDroping = false;
            tempStady = true;
          }
      }
  }
  
void blynkSendSensor()
  {
    Blynk.virtualWrite(V0, temp);                      
    Blynk.virtualWrite(V1, humidity);                  
    Blynk.virtualWrite(V2, heatindex);
  }
  
void logData()
  {
    Serial.print(F("Humidity:  "));
    Serial.print(humidity);
    Serial.print(F("%    Temperature:  "));
    Serial.print(temp);
    Serial.print(F("°C    Heat index:  "));
    Serial.print(heatindex);
    Serial.println(F("°C"));
  }

void heatmatSliderControl()   //logic used to determine whether or not temperature should be raised
  { 
    temp = dhtA.readTemperature();
    
    if (temp <= 0 || isnan(temp))               //HeatMat OFF - DHT22 Read Error
      {
        digitalWrite(D7, LOW);                  //Heater Relay OFF.
        heatmat.off();                          //HeatMat Led OFF
        dhtReaderror.on();                      //DHT Error Led ON
        Serial.println("DHT22 Sensor Malfunction - HEATING/MISTING operation terminated");
        Blynk.notify("DHT22 Sensor Malfunction - HEATING/MISTING operation terminated");
      }
    if (temp >= maximumTemp)               //If the Temp is too High turn on the exhaust fan and Bypassing Heatmat
      {
        digitalWrite(D4, HIGH);                 //FanOut Relay ON.
        digitalWrite(D7, LOW);                  //Heater Relay OFF.
        desiredTemp = 23;                       //Sets Desired temperature 23
        fanOut.on();                            //FanOut ON
        heatmat.off();                          //HeatMat Led OFF
        Blynk.notify("Temperature to High !! - Venting OUT ON - Heatmat OFF - Humidifier OFF - New desired temperature saved: 23°C");
        Serial.println("Temperature to High !! - Venting OUT ON - Heatmat OFF - Humidifier OFF - - New desired temperature saved: 23°C");
      }
    else
      { 
        if ((temp < desiredTemp && tempDroping == true) || (temp < desiredTemp - tempDiff && tempStady == true))     // HeatMat ON
          {
            digitalWrite(D7, HIGH);             //Heater Relay ON.
            heatmat.on();                       //HeatMat Led ON
            dhtReaderror.off();                 //DHT Error Led OFF
          }  
        
        if ((temp < desiredTemp - tempDiff && tempRising == true) || (temp > desiredTemp - tempDiff && tempStady == true))     //HeatMat OFF
          {
            digitalWrite(D7, LOW);              //HeatMat Relay OFF.
            heatmat.off();                      //HeatMat Led OFF
            dhtReaderror.off();                 //DHT Error Led OFF
          }
      }
      
  }

void humidifierSliderControl()                  //logic used to determine whether or not humidity should be raised
  {
    if (humidity <= 0 ||  isnan(humidity))      //HeatMat OFF - DHT22 Read Error
      {
        digitalWrite(D5, LOW);                  //Hunidifier Relay OFF.
        humidifier.off();                       //Humidifier Led OFF
        dhtReaderror.on();                      //DHT Error Led ON
        
        
      }
    else if (temp >= maximumTemp)                 //If the Temp is too High Bypassing Humidifier
      {
        digitalWrite(D5, LOW);                  //Humidifier Relay OFF.
        fanOut.on();                            //FanOut ON
        humidifier.off();                       //Humidifier Led OFF
      }    
    else
      {    
        if (humidity < desiredHum - humDiff)              //Humidifier ON
          {
            digitalWrite(D5, HIGH);             //Humidifier Relay ON.
            humidifier.on();                    //Humidifier Led ON
            dhtReaderror.off();                 //DHT Error Led OFF
          }
          if (humidity > desiredHum)  //HUMIDIFIER OFF - Desired Range
            {
            digitalWrite(D5, LOW);              //Hunidifier Relay OFF.
            humidifier.off();                    //Humidifier Led OFF
            dhtReaderror.off();                 //DHT Error Led OFF
            }
      }
  }
  
void saveConfigCallback ()                      //callback notifying the need to save config
  {
    Serial.println("Should save config");
    shouldSaveConfig = true;
  }

void GetPresets()                               // Pre-set Humidity/Temperature values are stored in ESP8266 memory.
  {
    if (desiredTemp != previousDesiredTemp)     //update the EEPROM if desired temperature has changed.
      {
        EEPROM.write(1, desiredTemp);
        EEPROM.commit();
        Serial.print(F("New desired temperature saved: "));
        Serial.println(desiredTemp);
        previousDesiredTemp = desiredTemp;
      }
    if (desiredHum != previousDesiredHum)     //update the EEPROM if desired humidity has changed.
      {
        EEPROM.write(2, desiredHum);
        EEPROM.commit();
        Serial.print(F("New desired humidity level saved: "));
        Serial.println(desiredHum);
        previousDesiredHum = desiredHum;
      }

    desiredTemp = EEPROM.read(1);
      if ((desiredTemp < 18) || (desiredTemp > 30))
        {
          desiredTemp = 20;
          Serial.println(F("No saved temperature setting."));
        }
    
    desiredHum = EEPROM.read(2);
      if ((desiredHum < 0) || (desiredHum > 120))
        {
          desiredHum = 50;
          Serial.println(F("No saved humidity setting."));
        }
  }

void setupSpiffs()
  {
    Serial.println("mounting FS...");
    if (SPIFFS.begin())
      {
        Serial.println("mounted file system");
        if (SPIFFS.exists("/config.json"))
          {
            Serial.println("reading config file");
            File configFile = SPIFFS.open("/config.json", "r");
            if (configFile)
              {
                Serial.println("opened config file");
                size_t size = configFile.size();
                std::unique_ptr<char[]> buf(new char[size]);
                configFile.readBytes(buf.get(), size);
                DynamicJsonBuffer jsonBuffer;
                JsonObject& json = jsonBuffer.parseObject(buf.get());
                json.printTo(Serial);
                if (json.success())
                  {
                    Serial.println("\nparsed json");
                    strcpy(blynk_token, json["blynk_token"]);
                  }
                else
                  {
                    Serial.println("failed to load json config");
                  }
              }
          }
      }
    else
      {
        Serial.println("failed to mount FS");
      }

  }

void WifiManager()
  {
    WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 34);
    WiFiManager wifiManager;
    wifiManager.setSaveConfigCallback(saveConfigCallback);
    wifiManager.addParameter(&custom_blynk_token);
    wifiManager.setMinimumSignalQuality();
    wifiManager.setTimeout(300);
    if (!wifiManager.autoConnect("SMART-TERRA AP"))
      {
        Serial.println("failed to connect and hit timeout");
        delay(3000);
        ESP.reset();
        delay(5000);
      }
  
    // always start configportal for a little while
    wifiManager.setConfigPortalTimeout(60);
    wifiManager.startConfigPortal("SMART-TERRA AP","terrarium");
  
    Serial.println("TERRA connected :)");
    strcpy(blynk_token, custom_blynk_token.getValue());
    if (shouldSaveConfig)
      {
        Serial.println("saving config");
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.createObject();
        json["blynk_token"] = blynk_token;
        File configFile = SPIFFS.open("/config.json", "w");
          if (!configFile)
            {
              Serial.println("failed to open config file for writing");
            }
        json.printTo(Serial);
        json.printTo(configFile);
        configFile.close();
        shouldSaveConfig = false;
      }
    Serial.println("local ip");
    Serial.println(WiFi.localIP());
    Blynk.connect();
    Blynk.config(blynk_token);
    Blynk.syncAll();
    delay(1000);
    if (!blynk_token)
      {
        Serial.println("Failed to connect to Blynk server");
        wifiManager.resetSettings(); //ESP.reset();
        delay(1000);
      }
  }

  
void setup()
  { 
    //Initialise EEPROM for storing values
    EEPROM.begin(20);
    Serial.println(F("LOADING SETTINGS FROM MEMORY"));
    Serial.println(F(""));
    delay(1000);

    //Set Output pins to outputs
    pinMode(relayLED, OUTPUT);
    pinMode(relayFANin, OUTPUT);
    pinMode(relayFANout, OUTPUT);
    pinMode(relayFOGGER, OUTPUT);
    pinMode(relayHEATMAT, OUTPUT);

    //Debug console
    Serial.begin(115200);
    
    //Starting the DHT-22
    dhtA.begin();

    //Timer Events
    timer.setInterval(2000L, sensorRead);
    timer.setInterval(1000L, heatmatSliderControl);
    timer.setInterval(1000L, humidifierSliderControl);
    timer.setInterval(5000L, blynkSendSensor);
    timer.setInterval(5000L, GetPresets);
    timer.setInterval(10000L, logData);
    timer.setInterval(91000L, temperatureComparision);
    
    
    ArduinoOTA.begin();
    setupSpiffs();
    WifiManager();
  }

void loop()
{
  Blynk.run();
  timer.run();
  ArduinoOTA.handle();
}

Did you see this topic…

Pete.