I have some strange issues going on with my project, including multiple reboots before the Web server loads, with Stack Smashing Protect errors. *See full code and errors below. Be warned I'm not a coder and just fiddle with these for fun and to learn a bit when I can.
I can get the Webserver to start if I temporarily pull the 3v3 wire off the BME688 (it stays powered on, I'm guessing due to SCL/SDA? BME688 and ENS160 are wired to one I2C bus. Microcontroller is a LOLIN D32. Full code and logs below:
#include <Arduino.h>
#include <Wire.h>
#include "SparkFun_ENS160.h"
#include <WiFi.h>
#include <WebServer.h>
#include <NTPClient.h>
#include <Time.h>
#include <Secrets.h>
#include <WiFiUdp.h>
#include <bme68xLibrary.h>
//define WiFi Network name and password with secrets.h
const char* ssid = SECRET_SSID;
const char* password = SECRET_PASS;
//Int and Float values to be used for Webserver later
int AQI, VOCs, CO2;
String formattedTime;
String Date;
int Day;
int Month;
int Year;
//declare Webserver and ntpUPD
WebServer server(80);
WiFiUDP ntpUDP;
//NTP Client and initializing time
int gtmOffset = -5;
NTPClient timeClient(ntpUDP, "pool.ntp.org", gtmOffset*60*60, 60000);
//Week Days
String weekDays[7]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
//declare ENS160 sensor and entStatus, as well as float relative humidity and temp in Celcius values for later use
SparkFun_ENS160 myENS;
bool printedCompensation = false;
int ensStatus;
float rh;
float tempC;
float tempF;
float gasR;
float press;
float pressMillis;
//declare and initalize BME688
#define I2C_ADDR 0x76
Bme68x bme;
void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.println("Connecting to ");
Serial.println(ssid);
//connect to your local wi-fi network
WiFi.begin(ssid, password);
//check wi-fi is connected to wi-fi network
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
server.on("/", handle_OnConnect);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP server started");
timeClient.begin();
// Initialize I2C operation
bme.begin(I2C_ADDR, Wire);
if(bme.checkStatus())
{
if (bme.checkStatus() == BME68X_ERROR)
{
Serial.println("Sensor error:" + bme.statusString());
return;
}
else if (bme.checkStatus() == BME68X_WARNING)
{
Serial.println("Sensor Warning:" + bme.statusString());
}
}
/* Set the default configuration for temperature, pressure and humidity */
bme.setTPH();
/* Set the heater configuration to 320 deg C for 150ms for Forced mode */
bme.setHeaterProf(320, 150);
//initialize ENS sensor
if( !myENS.begin() )
{
Serial.println("Could not communicate with the ENS160, check wiring.");
while(1);
}
Serial.println("Example 6 Burn In Time for the ENS160.");
// Reset the indoor air quality sensor's settings.
if( myENS.setOperatingMode(SFE_ENS160_RESET) )
Serial.println("Ready.");
delay(100);
// Device needs to be set to idle to apply any settings.
// myENS.setOperatingMode(SFE_ENS160_IDLE);
// Set to standard operation
// Others include SFE_ENS160_DEEP_SLEEP and SFE_ENS160_IDLE
myENS.setOperatingMode(SFE_ENS160_STANDARD);
// There are four values here:
// 0 - Operating ok: Standard Operation
// 1 - Warm-up: occurs for 3 minutes after power-on.
// 2 - Initial Start-up: Occurs for the first hour of operation.
// and only once in sensor's lifetime.
// 3 - No Valid Output
Serial.println("Waiting for the device to warm up, this will take ~3 minutes.");
Serial.println("Gas Sensor Status Flag (0 - Standard, 1 - Warm up, 2 - Initial Start Up): ");
while(true)
{
ensStatus = myENS.getFlags();
if((ensStatus == 2) | (ensStatus == 0))
{
Serial.println("ENS160 is warmed up!");
break;
}
if(ensStatus == 3)
{
Serial.println("Invalid Ouput...Freezing.");
while(1);
}
Serial.print(".");
delay(250);
}
Serial.println();
}
void loop() {
server.handleClient();
}
void handle_OnConnect() {
timeClient.update();
String formattedTime = timeClient.getFormattedTime();
time_t epochTime = timeClient.getEpochTime();
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
int currentSecond = timeClient.getSeconds();
String weekDay = weekDays[timeClient.getDay()];
//Get a time structure
struct tm *ptm = gmtime ((time_t *)&epochTime);
int monthDay = ptm->tm_mday;
int currentMonth = ptm->tm_mon+1;
String currentMonthName = months[currentMonth-1];
int currentYear = ptm->tm_year+1900;
formattedTime = timeClient.getFormattedTime();
Date = String(currentMonth) + "-" + String(monthDay) + "-" + String(currentYear);
//get BME688 data and send it to ENS prior to getting measurements
bme68xData data;
bme.setOpMode(BME68X_FORCED_MODE);
delayMicroseconds(bme.getMeasDur());
if (bme.fetchData())
{
bme.getData(data);
}
rh = (data.humidity);
tempC = (data.temperature);
tempF = (((data.temperature)*1.8)+32);
gasR = (data.gas_resistance);
press = (data.pressure);
pressMillis = ((data.pressure)/100);
Serial.print("Relative Humidity (%): ");
Serial.println(rh);
Serial.print("Temperature (Celsius): ");
Serial.println(tempC);
delay(100);
// Give values to Air Quality Sensor.
myENS.setTempCompensationCelsius(tempC);
myENS.setRHCompensationFloat(rh);
delay(500);
if (myENS.checkDataStatus()) {
if (printedCompensation == false) {
printedCompensation = true;
delay(500);
}
}
int AQI = myENS.getAQI();
int VOCs = myENS.getTVOC();
int CO2 = myENS.getECO2();
server.send(200, "text/html", SendHTML(AQI,VOCs,CO2,rh,tempC,tempF,gasR,press,pressMillis,formattedTime,Date));
}
void handle_NotFound(){
server.send(404, "text/plain", "Not found");
}
String SendHTML(int AQI, int VOCs, int CO2, float rh, float tempC, float tempF, float gasR, float press, float pressMillis, String TimeWeb, String DateWeb){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>Garage Environmental Monitoring</title>\n";
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr += "<script>\n";
ptr += "setInterval(loadDoc,1000);\n";
ptr += "function loadDoc() {\n";
ptr += "var xhttp = new XMLHttpRequest();\n";
ptr += "xhttp.onreadystatechange = function() {\n";
ptr += "if (this.readyState == 4 && this.status == 200) {\n";
ptr += "document.body.innerHTML =this.responseText}\n";
ptr += "};\n";
ptr += "xhttp.open(\"GET\", \"/\", true);\n";
ptr += "xhttp.send();\n";
ptr += "}\n";
ptr += "</script>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>Garage ESP32 Air Quality</h1>\n";
ptr +="<h2>Monitoring System</h2>\n";
ptr +="<p>Air Quality(1-5): ";
ptr +=AQI;
ptr +="</p>";
ptr +="<p>Total Volatile Organic Compounds: ";
ptr +=VOCs;
ptr +=" ppb</p>";
ptr +="<p>CO2 Concentration: ";
ptr +=CO2;
ptr +=" ppm</p>";
ptr +="<p>Humidity: ";
ptr +=rh;
ptr +=" %</p>";
ptr +="<p>Temp (Celcius): ";
ptr +=tempC;
ptr +=" °C</p>";
ptr +="<p>Temp (Fahrenheit): ";
ptr +=tempF;
ptr +=" °F</p>";
ptr +="<p>Pressure: ";
ptr +=press;
ptr +=" Pa</p>";
ptr +="<p>Pressure: ";
ptr +=pressMillis;
ptr +=" mb</p>";
ptr +="<p>Gas Resistance: ";
ptr +=gasR;
ptr +="</p>";
ptr +="<p>Time: ";
ptr +=(String)TimeWeb;
ptr +="</p>";
ptr +="<p>Date: ";
ptr +=(String)DateWeb;
ptr +="</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Here is serial output during reboot events I mentioned:
12:36:44.119 -> Ready.
12:36:44.213 -> Waiting for the device to warm up, this will take ~3 minutes.
12:36:44.259 -> Gas Sensor Status Flag (0 - Standard, 1 - Warm up, 2 - Initial Start Up):
12:36:44.259 -> ENS160 is warmed up!
12:36:44.259 ->
12:37:04.108 -> Relative Humidity (%): 1.96
12:37:04.108 -> Temperature (Celsius): ovf
12:37:05.188 ->
12:37:05.188 -> Stack smashing protect failure!
12:37:05.188 ->
12:37:05.188 ->
12:37:05.188 -> Backtrace: 0x40082825:0x3ffb1f20 0x4008c5b5:0x3ffb1f40 0x40082836:0x3ffb1f60 0x400ddbd9:0x3ffb1f80 0x400d2d4d:0x3ffb1fc0 0x400d31fa:0x3ffb2010 0x0034352b:0x3ffb2110 |<-CORRUPTED
12:37:05.188 ->
12:37:05.188 ->