0

I have tried to make a water heater relay controlled by an ESP8266 (NodeMCU v1.0). The ESP8266 is connected to a central WiFi in my house, the ESP8266 also has its own WiFi so I use STA and AP mode for the ESP8266. The ESP8266 will give a webpage when its IP address accessed. I have been able to use it for about a month, even though sometimes the ESP8266 restarting after 4-24h of use. But then after 1 month the ESP8266 just die. I have tried to upload blink led, and it doesn't work, even though I can upload the program successfully using Arduino IDE.

Here is my Arduino ESP8266 code

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Arduino.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Hash.h>
#include <Ticker.h>
#include <SD.h>
#include <SPI.h>

//Client
#define STASSID "******"
#define STAPSK  "*********"

//Host
#define APSSID "**********"
#define APPSK "*********"

#define relayheaterPin D1
#define relaypompaPin D2
#define temperaturPin 3
#define CS_PIN  D8
#define voltagedetectorPin 1

IPAddress staticIP(192, 168, 100, 186); //ESP8266 static ip
IPAddress gateway(192, 168, 100, 1); //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255, 255, 255, 0); //Subnet mask
IPAddress DNS(8, 8, 8, 8); //DNS
IPAddress DNS2(8, 8, 4, 4); //DNS

OneWire oneWire(temperaturPin); 
DallasTemperature sensors(&oneWire);

AsyncWebServer server(80);

Ticker timer_pompa;
Ticker get_Temperature;

File dataFile;
String dataMessage;
unsigned long seeks;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
unsigned long timeOffset = 25200;
String formattedDate;
String dayStamp;
String timeStamp;

const char* ssid = STASSID;
const char* password = STAPSK;
const char* APssid = APSSID;
const char* APpassword = APPSK;

bool b_Pompa = 0;
bool b_Pompa_Temp=0;
bool b_Heater = 0;
unsigned int i = 0;

unsigned long ret=0;
float f_temp;
unsigned long ul_max_temp = 38;
unsigned long ul_min_temp = 36;

void v_SD_setup() {
  if (!SD.begin(CS_PIN)) {
//    Serial.println("An Error has occurred while mounting SD Card");
    return;
  }
  dataFile = SD.open("temperature.csv", FILE_WRITE);
  dataFile.close();
}

void v_OTA_setup () {
//  Serial.begin(115200);
  WiFi.persistent(false);
  WiFi.disconnect(true);
  WiFi.mode(WIFI_AP_STA);
  WiFi.softAP(APssid, APpassword);
  WiFi.config(staticIP, subnet, gateway, DNS, DNS2);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }
//  Serial.println(WiFi.localIP());
//  Serial.println(WiFi.softAPIP());
  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_SPIFFS
      type = "filesystem";
    }
  });
  ArduinoOTA.begin();
}

void getTimeStamp() {
  timeClient.update();
  formattedDate = timeClient.getFormattedDate();

  // Extract date
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);

  // Extract time
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
}

// Write the sensor readings on the SD card
void logSDCard() {
  dataFile = SD.open("temperature.csv", FILE_WRITE);
  dataMessage = String(dayStamp) + "T" + String(timeStamp) + "," + 
                String(f_temp) + "," + String(b_Pompa) + "," + String(!digitalRead(voltagedetectorPin))+ "\r\n";
  if (dataFile) {
    dataFile.print(dataMessage);
    dataFile.close();
  }
}

//Send Temperature, Pump, and Heater Condition Data from SD Card until EOF
String s_Read_Data(){
  String dataString= "Waktu, Temperature, Pompa, Heater\r\n";
  unsigned int len;
  dataFile = SD.open("temperature.csv");
  if (dataFile) {
    if (dataFile.size()>5580) {
      seeks=dataFile.size()-5580;  
    } else {
      seeks=0;
    }
    dataFile.seek(seeks);
    while(dataFile.available()) {
     dataString+=dataFile.readString(); 
    }
    dataFile.close(); 
  } else {
    dataString="Error Opening File";
  }
  return dataString;
}

char* v_Pompa_On(){
   b_Pompa=1;
   digitalWrite(relaypompaPin, b_Pompa);
   return "Pompa is ON";
}

char* v_Pompa_Off(){
   b_Pompa=0;
   digitalWrite(relaypompaPin, b_Pompa);
   timer_pompa.detach();
   return "Pompa is OFF";
}

char* v_Heater(){
   b_Heater=!b_Heater;
   digitalWrite(relayheaterPin, b_Heater);
   if(digitalRead(voltagedetectorPin) ==0) {
    return "Heater is ON";
   } else {
    return "Heater is OFF";
   }
}

char* c_Heater_Condition(){
   if(digitalRead(voltagedetectorPin) ==0) {
    return "Heater is ON";
   } else {
    return "Heater is OFF";
   }
}

char* c_Pompa_Conditon(){
   if(b_Pompa ==1) {
    return "Pompa is ON";
   } else {
    return "Pompa is OFF";
   }
}

void v_getTemp () {
//  char buf[20];
  sensors.requestTemperatures();
  f_temp = sensors.getTempCByIndex(0);
  if (f_temp!=-127) {
   getTimeStamp();
   if (dayStamp!="1970-01-01") {
    logSDCard(); 
   }
  }
}

char* c_getTemperature () {
  char buf[20];
  sensors.requestTemperatures();
  sprintf(buf, "%f", sensors.getTempCByIndex(0));
  return buf;
}

void v_Timer_Pompa() {
  if (b_Pompa ==0) {
     v_Pompa_On();
  }
  if (ret<=0) {
    v_Pompa_Off();
    timer_pompa.detach();
    return;
  }
  ret--; 
}

char* v_Pompa_10_min () {
  ret=10;
  v_Timer_Pompa();
  timer_pompa.attach(60, v_Timer_Pompa);
  return "Pompa is ON";
}

void v_server_setup () {
  // Initialize SPIFFS
  if(!SPIFFS.begin()){
//    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html");
  });
  server.on("/phone", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index-phone.html");
  });
  server.on("/pompa_timer", HTTP_POST, [](AsyncWebServerRequest * request){},NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
     char str[30];
     char *ptr;
     for (size_t i = 0; i < len; i++) {
       str[i]=data[i];
     }
     ret = strtol(str, &ptr, 10); 
     v_Timer_Pompa();
     timer_pompa.attach(60, v_Timer_Pompa);
     request->send(200);
  });
  server.on("/max_temp", HTTP_POST, [](AsyncWebServerRequest * request){},NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
     char str[30];
     char *ptr;
     for (size_t i = 0; i < len; i++) {
       str[i]=data[i];
     }
     ul_max_temp = strtol(str, &ptr, 10); 
     request->send(200);
  });
  server.on("/min_temp", HTTP_POST, [](AsyncWebServerRequest * request){},NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
     char str[30];
     char *ptr;
     for (size_t i = 0; i < len; i++) {
       str[i]=data[i];
     }
     ul_min_temp = strtol(str, &ptr, 10); 
     if (ul_min_temp<=ul_max_temp) {
        request->send(200, "text/plain", "Success!");
     } else {
        request->send(200, "text/plain", "Minimum Temperature has to be lower than Maximum Temperature");
     }
  });
  server.on("/read_data", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", s_Read_Data());
  });
  server.on("/time_left", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", (String)ret);
  });
  server.on("/heater_condition", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", c_Heater_Condition());
  });
  server.on("/pompa_condition", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", c_Pompa_Conditon());
  });
  server.on("/heater", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Heater() );
  });
  server.on("/pompa_on", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Pompa_On() );
  });
  server.on("/pompa_off", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Pompa_Off() );
  });
  server.on("/get_temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",c_getTemperature() );
  });
  server.on("/10_min_on", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Pompa_10_min() );
  });
  server.begin();
}

void setup() {
  //WiFi Setup
  v_OTA_setup();
  v_server_setup();
  v_SD_setup();

  //Pin Setup
  pinMode(relayheaterPin,OUTPUT);
  pinMode(relaypompaPin,OUTPUT);
  pinMode(temperaturPin,INPUT);
  pinMode(voltagedetectorPin,INPUT_PULLUP);

  //Sensors and time Setup
  sensors.begin();
  timeClient.begin();
  timeClient.setTimeOffset(timeOffset);

  //Get Sensors Reading
  v_getTemp();
  get_Temperature.attach(120, v_getTemp);
}

void loop() {
  ArduinoOTA.handle();
  if (WiFi.status() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }
  if ((b_Pompa ==1) && ((f_temp-ul_max_temp) <= 0)) {
    b_Pompa_Temp=1;
    b_Heater=1;
    digitalWrite(relayheaterPin, b_Heater);
  } else {
    if (b_Pompa_Temp==0) {
     if (f_temp<=ul_min_temp) {
       b_Heater=1;
       digitalWrite(relayheaterPin, b_Heater);
     } else if(f_temp>=ul_max_temp){
       b_Heater=0;
       digitalWrite(relayheaterPin, b_Heater);
     } 
    } else {
      b_Heater=0;
      digitalWrite(relayheaterPin, b_Heater);
      b_Pompa_Temp=0;
    }
  }
}

Additionally, sometimes when I access ip_address/read_data I got no response, but after waiting for a while I got some response. Before the ESP8266 dies (after 1 month of use) when I accessed ip_address/read_data I got no response, and then when I restart the ESP8266 It just dies. Any idea why? 2 of my ESP8266s have died this past 2 months :(

Note: I powered my ESP8266 using LM7805 with supply from 12V 1A switching power supply.

  • 1
    one problem is the String class. the esp8266 arduino is always unreachable on network after a while even it works and accesses the network as client. that is a know issue and the solution is not merged into the library yet github.com/esp8266/Arduino/pull/6889 – Juraj Dec 20 '19 at 11:08
  • Is it possible for me to solve the String class problem by changing the String class into array of char? I have tried changing the string into array of char and getting the char from SD card file by using dataFile.readString().c_str(); but then the hardware wdt turns on and the esp restarts when I access ip_address/read_data. – shafiyyah Dec 20 '19 at 11:23
  • How do you control the relay? – Sim Son Dec 20 '19 at 15:07
  • 1
    Exactly how are you connecting the microcontroller to the relay? Exactly how are you connecting the 5V power to the microcontroller? – Elliot Alderson Dec 20 '19 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.