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.