I am developing a system that reads data from an LM35 temperature sensor and forwards it to a web page using an Arduino Uno and a ESP8266 WiFi Module. The data flow is as follows:
LM35 --> Arduino Uno --> ESP8266 (Having a web server) --> Webpage
The Uno sends data to the ESP8266 every SAMPLE_RATE
seconds (4 seconds in my example) but the ESP8266 keeps updating the web page as it is a dynamic web page running AJAX. The problem is that I can see the data updating only once in a while (I assume when the 4 second delay aligns with the instant when the ESP8266 updates the value on the web page).
How can I make it so that even if The Uno doesn't send new values (during the 4 second gap), the ESP8266 keeps updating the web page with the old values? I have tried numerous times but have failed. Here is my code so far:
ARDUINO SIDE:
#include <SoftwareSerial.h>
#include <String.h>
//a Header for the Filtering Algorithm
//*******************************************************************/
//#include "Filter.h"
//*******************************************************************/
//Set RESET PIN for ESP8266
//*******************************************************************/
#define RST_PIN_ESP8266 13
//*******************************************************************/
//Define Baud rate for Serial Communication and ESP8266 Software Serial
//*******************************************************************/
#define SERIAL_BAUD_RATE 9600
#define ESP8266_SOFT_SERIAL_BAUD_RATE 9600
//*******************************************************************/
//LM35 Temperature sensor used for this code
//*******************************************************************/
#define LM35 A0
//*******************************************************************/
//Define Sensor sampling rate
//*******************************************************************/
#define SAMPLE_RATE 4000
//*******************************************************************/
//Code Features . . Uncomment to enable
//*******************************************************************/
//#define LM35_RAW_DEBUG
//#define TEMP_READ
//#define PRINT_DEBUG
#define MEASURE_SALINE
//*******************************************************************/
//ESP8266 Software Serial Object
//*******************************************************************/
SoftwareSerial ESP8266_Serial(6,7);
//*******************************************************************/
//Global Variables
//*******************************************************************/
float tempC;
long rawValue = 0, initCount = 0;
int initRawValue = 0, i, START_VALUE = 0;
int SALINE_STARTED = 0, SALINE_IN_PROGRESS = 1, SALINE_EXHAUSTED = 2;
int saline_status_flag = 0;
String finalMSG;
//*******************************************************************/
//Needed objects for time counting and filtering
//*******************************************************************/
unsigned long StartTime = millis();
//ExponentialFilter<int> ADCFilter(5, 0);
//*******************************************************************/
void setup() {
long rawValue = 0, initCount = 0;
int initRawValue = 0, i;
//Set up Serial Communication
Serial.begin(SERIAL_BAUD_RATE);
ESP8266_Serial.begin(ESP8266_SOFT_SERIAL_BAUD_RATE);
pinMode(RST_PIN_ESP8266, OUTPUT);
Reset_ESP8266();
while(ESP8266_Serial.available()) {
getIP(); // Obtain IP for ESP8266
}
delay(1000);
//Increase accuracy
analogReference(INTERNAL);
//Start Sensor Calibration
#ifdef MEASURE_SALINE
Serial.print(". . . CALIBRATING SYSTEM . . .\n");
#ifdef PRINT_DEBUG
Serial.println("\n\nTime Elapsed :\n\n");
#endif
here:
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - StartTime;
#ifdef PRINT_DEBUG
Serial.println(elapsedTime);
#endif
if(elapsedTime < 20000) {
initCount++;
rawValue += analogRead(LM35);
#ifdef PRINT_DEBUG
Serial.println(rawValue);
#endif
goto here;
}
currentTime = 0;
elapsedTime = 0;
rawValue = rawValue / initCount;
//Averaging from 5000 sensor samples
initRawValue = rawValue;
START_VALUE = initRawValue;
Serial.println("\n. . . CALIBRATION COMPLETE . . .");
Serial.print("\nInitial Raw LM35 Value : ");
Serial.print(START_VALUE);
Serial.print("\n\n");
Reinitialize_Variables();
delay(2000);
#ifdef PRINT_DEBUG
Serial.println("\nLM35 Sample Count:\n");
Serial.println(initCount);
#endif
#endif
initCount = 0;
#ifdef LM35_RAW_DEBUG
Serial.println("\n. . . STARTING LM35 DEBUG READING . . .\n\n");
#endif
#ifdef MEASURE_SALINE
Serial.println("\n. . . STARTING SALINE MONITORING. . .\n\n");
#endif
}
void loop() {
#ifdef MEASURE_SALINE
Measure_Saline();
#endif
#ifdef LM35_RAW_DEBUG
rawValue = analogRead(LM35);
Serial.println(rawValue);
#endif
#ifdef TEMP_READ
Read_Temp();
#endif
Reinitialize_Variables();
}
void Measure_Saline() {
int dont_print_flag = 0;
unsigned long StartTime = millis();
//Take readings (SAMPLE_RATE times) and average them
here:
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - StartTime;
#ifdef PRINT_DEBUG
Serial.println(elapsedTime);
#endif
if(elapsedTime < SAMPLE_RATE) {
initCount++;
rawValue += analogRead(LM35);
#ifdef PRINT_DEBUG
Serial.println(rawValue);
#endif
goto here;
}
currentTime = 0;
elapsedTime = 0;
rawValue = rawValue / initCount;
#ifdef PRINT_DEBUG
Serial.print("initCount : ");
Serial.print(initCount);
#endif
if(saline_status_flag != SALINE_EXHAUSTED) {
if(rawValue < START_VALUE) {
saline_status_flag = SALINE_STARTED;
} else if(rawValue == START_VALUE) {
saline_status_flag = SALINE_IN_PROGRESS;
} else if(rawValue > START_VALUE) {
START_VALUE = rawValue;
delay(1000);
rawValue = analogRead(LM35);
delay(10);
if(rawValue > START_VALUE) {
saline_status_flag = SALINE_EXHAUSTED;
dont_print_flag = 1;
Serial.print(rawValue);
Serial.print(" Saline bottle EXHAUSTED\n");
finalMSG = (String(rawValue) + " EXHAUSTED\n");
ESP8266_Serial.println(finalMSG);
}
}
//Saline Therapy Ongoing
if((saline_status_flag == SALINE_STARTED || saline_status_flag == SALINE_IN_PROGRESS) && dont_print_flag == 0) {
Serial.print(rawValue);
Serial.print(" Saline Therapy IN PROGRESS\n");
finalMSG = (String(rawValue) + " IN PROGRESS\n");
ESP8266_Serial.println(finalMSG);
} else if(saline_status_flag == SALINE_EXHAUSTED && dont_print_flag == 0) {
//Saline Exhausted
Serial.print(rawValue);
Serial.print(" Saline bottle EXHAUSTED\n");
finalMSG = (String(rawValue) + " EXHAUSTED\n");
ESP8266_Serial.println(finalMSG);
}
START_VALUE = rawValue;
} else {
Serial.print(" Saline bottle EXHAUSTED\n");
finalMSG = (String(rawValue) + " EXHAUSTED\n");
ESP8266_Serial.println(finalMSG);
}
delay(200);
}
void Read_Temp() {
rawValue = analogRead(LM35);
tempC = rawValue * 0.48828125;
tempC = rawValue / 9.31;
Serial.println(tempC);
delay(2000);
}
void Reinitialize_Variables() {
initCount = 0;
rawValue = 0;
initRawValue = 0;
i = 0;
}
void getIP() {
Serial.println(ESP8266_Serial.readStringUntil('\n'));
}
void Reset_ESP8266() {
pinMode(RST_PIN_ESP8266, OUTPUT);
digitalWrite(RST_PIN_ESP8266, HIGH);
// (RST_PIN_ESP8266 = 1 -> RESET = 0 so ESP8266 RESET FALSE)
delay(1000);
digitalWrite(RST_PIN_ESP8266, LOW);
// (RST_PIN_ESP8266 = 0 -> RESET = 1 so ESP8266 RESET TRUE)
delay(1000);
digitalWrite(RST_PIN_ESP8266, HIGH);
// (RST_PIN_ESP8266 = 1 -> RESET = 0 so ESP8266 RESET FALSE)
delay(50);
}
ESP8266 side:
/*
* This Code is for the ESP8266 WiFi Module. It builds a website running AJAX (Asynchronous JavaScript and XML)
* which allows this webpage to update itself without having to refresh itself which may not be resource friendly
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define DEVICE_ID 1
ESP8266WebServer server(80);
const char* ssid="COLDSPOT"; // WiFi Access Point to connect to
const char* password="1234567890"; // Password for the Access Point
String webSite,javaScript,XML;
void buildWebsite() {
buildJavascript();
webSite = "<!DOCTYPE HTML>\n";
webSite += javaScript;
webSite += "<BODY onload='process()'>\n";
webSite += "<h1 align='center'><BR>SALINE MONITORING:<BR><h1>\n";
webSite += "STATUS = <A id='runtime'></A>\n";
webSite += "</BODY>\n";
webSite += "</HTML>\n";
}
void buildJavascript() {
javaScript = "<SCRIPT>\n";
javaScript += "var xmlHttp=createXmlHttpObject();\n";
javaScript += "function createXmlHttpObject(){\n";
javaScript += " if(window.XMLHttpRequest){\n";
javaScript += " xmlHttp=new XMLHttpRequest();\n";
javaScript += " }else{\n";
javaScript += " xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');\n";
javaScript += " }\n";
javaScript += " return xmlHttp;\n";
javaScript += "}\n";
javaScript += "function process(){\n";
javaScript += " if(xmlHttp.readyState==0 || xmlHttp.readyState==4){\n";
javaScript += " xmlHttp.open('PUT','xml',true);\n";
javaScript += " xmlHttp.onreadystatechange=handleServerResponse;\n"; // no brackets?????
javaScript += " xmlHttp.send(null);\n";
javaScript += " }\n";
javaScript += " setTimeout('process()',1000);\n";
javaScript += "}\n";
javaScript += "function handleServerResponse(){\n";
javaScript += " if(xmlHttp.readyState==4 && xmlHttp.status==200){\n";
javaScript += " xmlResponse=xmlHttp.responseXML;\n";
javaScript += " xmldoc = xmlResponse.getElementsByTagName('response');\n";
javaScript += " message = xmldoc[0].firstChild.nodeValue;\n";
javaScript += " document.getElementById('runtime').innerHTML=message;\n";
javaScript += " }\n";
javaScript += "}\n";
javaScript += "</SCRIPT>\n";
}
void buildXML() {
XML = "<?xml version='1.0'?>";
XML += "<response>";
XML += DataFromArduino(); //incoming data from Arduino. It means it is the value of mapping function.
XML += "</response>";
}
String DataFromArduino() {
String coming;
if(Serial.available()) {
while(Serial.available()) {
coming = Serial.readStringUntil('\n');
delay(1);
} // it is getting via serial port.
return coming;
} else {
return coming;
}
}
void handleWebsite() {
buildWebsite();
server.send(200,"text/html",webSite);
}
void handleXML() {
buildXML();
server.send(200,"text/xml",XML);
}
void setup() {
Serial.begin(9600);
WiFi.begin(ssid,password); //trying to connect the modem
while(WiFi.status() != WL_CONNECTED) {
delay(500);
}
WiFi.mode(WIFI_STA);
Serial.println("\n\n. . . BOOTING ESP8266 . . .\n");
Serial.print("DEVICE ID : ");
Serial.print(DEVICE_ID);
Serial.print("\n");
Serial.print("CONNECTED TO ACCESS POINT : ");
Serial.println(ssid);
Serial.flush();
Serial.println(WiFi.localIP());
//it is sending the IP to Arduino's port. So I can see the IP on Serial Monitor
Serial.flush();
server.on("/", handleWebsite);
//it is all about setting of server.
server.on("/xml",handleXML);
server.begin();
}
void loop() {
server.handleClient();
}
Please note that I have already changed the baud rate of the ESP8266 to 9600. I am using THIS ESP8266 Module.