Assistance with Environmental Web Server w/ non-Web server related functionality

KO4OEH
Posts: 3
Joined: Sun Oct 22, 2023 3:26 pm

Assistance with Environmental Web Server w/ non-Web server related functionality

Postby KO4OEH » Sun Oct 22, 2023 7:13 pm

Pretty new to playing around with development boards in general, including the ESP32. This code for my environmental Web Server, which consists of BME280 and three MQ Sensors works just fine (I have borrowed heavily from other online examples to get this working):

Code: Select all

#include <MQUnifiedsensor.h>
#include <Wire.h>
#include <NTPClient.h>
#include <Time.h>
#include <WiFi.h>
#include <WebServer.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1014.5)
#define board "ESP32"
#define Voltage_Resolution 3.3
#define pin 34 //Analog input 0 of your ESP32
#define pin2 35 //Analog input 1 of your ESP32
#define pin3 32 //Analog input 2 of ESP32
#define type "MQ-135" //MQ135
#define type2 "MQ-2" //MQ2
#define type3 "MQ-4" //MQ4
#define ADC_Bit_Resolution 12 // For ESP32
#define RatioMQ135CleanAir (3.6) //RS / R0 = 3.6 ppm
#define RatioMQ2CleanAir (9.83) //RS / R0 = 9.83 ppm 
#define RatioMQ4CleanAir (4.4) //RS / R0 = 60 ppm   

MQUnifiedsensor MQ135(board, Voltage_Resolution, ADC_Bit_Resolution, pin, type);
MQUnifiedsensor MQ2(board, Voltage_Resolution, ADC_Bit_Resolution, pin2, type2);
MQUnifiedsensor MQ4(board, Voltage_Resolution, ADC_Bit_Resolution, pin3, type3);

Adafruit_BME280 bme;

float temperature, fahrenheit, humidity, pressure, altitude, altfeet, CO2, H2, Smoke;
String formattedTime;
String Date;
int Day;
int Month;
int Year;

/*Put your SSID & Password*/
const char* ssid = "BellDOTnet";  // Enter SSID here
const char* password = "D3lt@H3x01";  //Enter Password here

WebServer server(80);    

WiFiUDP ntpUDP;

//NTP Client
NTPClient timeClient(ntpUDP, "us.pool.ntp.org", -18000, 18000);
unsigned long epochTime = timeClient.getEpochTime();
struct tm *ptm = gmtime ((time_t *)&epochTime);
 
void setup() {
  Serial.begin(115200);
  delay(100);
  
  bme.begin(0x76);   // 0x76 is the default address of the I2C chip

  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();

  MQ135.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ135.setA(110.47); MQ135.setB(-2.862); // Configure the equation to to calculate CO2 concentration

  MQ135.init();  

  Serial.print("Calibrating please wait.");
  float calcR0 = 0;
  for(int i = 1; i<=10; i ++)
  {
    MQ135.update(); // Update data, the arduino will read the voltage from the analog pin
    calcR0 += MQ135.calibrate(RatioMQ135CleanAir);
    Serial.print(".");
  }
  MQ135.setR0(calcR0/10);
  Serial.println("  done!.");

  MQ2.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ2.setA(987.99); MQ2.setB(-2.162); // Configure the equation to to calculate LPG concentration

  MQ2.init(); 

  Serial.print("Calibrating please wait.");
  for(int i = 1; i<=10; i ++)
  {
    MQ2.update(); // Update data, the arduino will read the voltage from the analog pin
    calcR0 += MQ2.calibrate(RatioMQ2CleanAir);
    Serial.print(".");
  }
  MQ2.setR0(calcR0/10);
  Serial.println("  done!.");

  MQ4.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ4.setA(30000000); MQ4.setB(-8.308);

  MQ4.init();

  Serial.print("Calibrating please wait.");
  for(int i = 1; i<=10; i ++)
  {
    MQ4.update(); // Update data, the arduino will read the voltage from the analog pin
    calcR0 += MQ4.calibrate(RatioMQ4CleanAir);
    Serial.print(".");
  }
  MQ4.setR0(calcR0/10);
  Serial.println("  done!.");
}

void loop() {

  server.handleClient();

}

void handle_OnConnect() {

  timeClient.update();

   unsigned long epochTime = timeClient.getEpochTime();
   String formattedTime = timeClient.getFormattedTime();

  struct tm *ptm = gmtime ((time_t *)&epochTime);

  int monthDay= ptm->tm_mday;
  int currentMonth = ptm->tm_mon+1;
  int currentYear = ptm->tm_year+1900;
 
  formattedTime = timeClient.getFormattedTime(); 
  Date = String(currentYear) + "-" + String(currentMonth) + "-" + String(monthDay);

  temperature = bme.readTemperature();
  fahrenheit = (temperature * 9/5) + 32;
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0F;
  altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
  altfeet = (altitude * 3.281);

  MQ135.setA(110.47); MQ135.setB(-2.862); // Configure the equation to calculate CO2 concentration value
  float CO2 = MQ135.readSensor(); // Sensor will read PPM concentration using the model, a and b values set previously or from the setup

  MQ2.setA(987.99); MQ2.setB(-2.162); //Configure the equation to calculate Smoke concentration value
  float H2 = MQ2.readSensor(); // Sensor will read the PPM concentration using the model, a and b values set previously or from the setup

  MQ4.setA(30000000); MQ4.setB(-8.308); // Configure the equation to to calculate CH4 concentration
  float Smoke = MQ4.readSensor(); // Sensor will read PPM concentration using the model, a and b values set previously or from the setup

  MQ135.update();
  MQ2.update();
  MQ4.update();

  server.send(200, "text/html", SendHTML(temperature,fahrenheit,humidity,pressure,altitude,altfeet,CO2,H2,Smoke,formattedTime,Date)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(float temperature, float fahrenheit, float humidity, float pressure, float altitude, float altfeet, float CO2, float H2, float Smoke, 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 +="</head>\n";
  ptr +="<body>\n";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>Garage Environmental Monitoring</h1>\n";
  ptr +="<p>Temperature: ";
  ptr +=temperature;
  ptr +="&deg;C</p>";
  ptr +="<p>Temperature: ";
  ptr +=fahrenheit;
  ptr +="&deg;F</p>";
  ptr +="<p>Humidity: ";
  ptr +=humidity;
  ptr +="%</p>";
  ptr +="<p>Pressure: ";
  ptr +=pressure;
  ptr +="hPa</p>";
  ptr +="<p>Altitude: ";
  ptr +=altitude;
  ptr +="m</p>";
  ptr +="<p>Altitude: ";
  ptr +=altfeet;
  ptr +="ft</p>";
  ptr +="<p>CO2 Level: ";
  ptr +=CO2 + 416;
  ptr +="ppm</p>";
  ptr +="<p>H2 Level: ";
  ptr +=H2;
  ptr +="ppm</p>";
  ptr +="<p>Smoke Level: ";
  ptr +=Smoke;
  ptr +="ppm</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;
}
What I want is to add is another functionality that really has nothing to do with displaying on the Web server. I want to be able to measure the readings from the MQ Sensors and compare them to a const threshold value and depending on those states have certain LEDs light up and buzzer to sound. Here is the code I have so far along with the errors I get back when trying to compile it:

Code: Select all

#include <MQUnifiedsensor.h>
#include <Wire.h>
#include <NTPClient.h>
#include <Time.h>
#include <WiFi.h>
#include <WebServer.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1014.5)
#define placa "ESP32"
#define Voltage_Resolution 3.3
#define pin 34 //Analog input 0 of ESP32
#define pin2 35 //Analog input 1 of ESP32
#define pin3 32 //Analog input 2 of ESP32
#define type "MQ-135" //MQ135
#define type2 "MQ-2" //MQ2
#define type3 "MQ-4" //MQ4
#define ADC_Bit_Resolution 12 // For ESP32
#define RatioMQ135CleanAir (3.6)  //RS / R0 = 3.6 ppm
#define RatioMQ2CleanAir (9.83) //RS / R0 = 9.83 ppm 
#define RatioMQ4CleanAir (4.4) //RS / R0 = 60 ppm 
#define buzzer 13
#define redLED 12
#define greenLED 14
#define blueLED 27
#define yellowLED 26  

MQUnifiedsensor MQ135(placa, Voltage_Resolution, ADC_Bit_Resolution, pin, type);
MQUnifiedsensor MQ2(placa, Voltage_Resolution, ADC_Bit_Resolution, pin2, type2);
MQUnifiedsensor MQ4(placa, Voltage_Resolution, ADC_Bit_Resolution, pin3, type3);

Adafruit_BME280 bme;

float temperature, fahrenheit, humidity, pressure, altitude, altfeet, CO2, H2, Smoke;
String formattedTime;
String Date;
int Day;
int Month;
int Year;

int sensorThres = 420;

/*Put your SSID & Password*/
const char* ssid = "BellDOTnet";  // Enter SSID here
const char* password = "D3lt@H3x01";  //Enter Password here

WebServer server(80);    

WiFiUDP ntpUDP;

//NTP Client
NTPClient timeClient(ntpUDP, "us.pool.ntp.org", -18000, 18000);
unsigned long epochTime = timeClient.getEpochTime();
struct tm *ptm = gmtime ((time_t *)&epochTime);
 
void setup() {
  Serial.begin(115200);
  delay(100);
  
  bme.begin(0x76);   // 0x76 is the default address of the I2C chip

  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();

  MQ135.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ135.setA(110.47); MQ135.setB(-2.862); // Configure the equation to to calculate CO2 concentration

  MQ135.init();

  Serial.print("Calibrating please wait.");
  float calcR0 = 0;
  for(int i = 1; i<=10; i ++)
  {
    MQ135.update(); // Update data, the arduino will read the voltage from the analog pin
    calcR0 += MQ135.calibrate(RatioMQ135CleanAir);
    Serial.print(".");
  }
  MQ135.setR0(calcR0/10);
  Serial.println("  done!.");

  MQ2.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ2.setA(987.99); MQ2.setB(-2.162); // Configure the equation to to calculate LPG concentration

  MQ2.init(); 

  Serial.print("Calibrating please wait.");
 
  for(int i = 1; i<=10; i ++)
  {
    MQ2.update(); // Update data, the arduino will read the voltage from the analog pin
    calcR0 += MQ2.calibrate(RatioMQ2CleanAir);
    Serial.print(".");
  }
  MQ2.setR0(calcR0/10);
  Serial.println("  done!.");

  //Set math model to calculate the PPM concentration and the value of constants
  MQ4.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ4.setA(30000000); MQ4.setB(-8.308);

  MQ4.init(); 

  Serial.print("Calibrating please wait.");

  for(int i = 1; i<=10; i ++)
  {
    MQ4.update(); // Update data, the arduino will read the voltage from the analog pin
    calcR0 += MQ4.calibrate(RatioMQ4CleanAir);
    Serial.print(".");
  }
  MQ4.setR0(calcR0/10);
  Serial.println("  done!.");

  pinMode(buzzer, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(blueLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);

}

void loop() {

  server.handleClient();

}

void handle_OnConnect() {

  timeClient.update();

  unsigned long epochTime = timeClient.getEpochTime();
  String formattedTime = timeClient.getFormattedTime();

  struct tm *ptm = gmtime ((time_t *)&epochTime);

  int monthDay= ptm->tm_mday;
  int currentMonth = ptm->tm_mon+1;
  int currentYear = ptm->tm_year+1900;
 
  formattedTime = timeClient.getFormattedTime(); 
  Date = String(currentYear) + "-" + String(currentMonth) + "-" + String(monthDay);

  temperature = bme.readTemperature();
  fahrenheit = (temperature * 9/5) + 32;
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0F;
  altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
  altfeet = (altitude * 3.281);

  MQ135.setA(110.47); MQ135.setB(-2.862); // Configure the equation to calculate CO2 concentration value
  float CO2 = MQ135.readSensor(); // Sensor will read PPM concentration using the model, a and b values set previously or from the setup

  MQ2.setA(987.99); MQ2.setB(-2.162); //Configure the equation to calculate Smoke concentration value
  float H2 = MQ2.readSensor(); // Sensor will read the PPM concentration using the model, a and b values set previously or from the setup

  MQ4.setA(30000000); MQ4.setB(-8.308); // Configure the equation to to calculate CH4 concentration
  float Smoke = MQ4.readSensor(); // Sensor will read PPM concentration using the model, a and b values set previously or from the setup

  MQ135.update();
  MQ2.update();
  MQ4.update();

    if (CO2 >= sensorThres && H2 < sensorThres && Smoke < sensorThres)
    {                                                                        // CO2 Alarm
    digitalWrite(redLED, HIGH);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, LOW);
    digitalWrite(yellowLED, LOW);
    tone(buzzer, 1000, 1000);
    }

    else if (CO2 < sensorThres && H2 >= sensorThres && Smoke < sensorThres)
    {                                                                        // H2 Alarm
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, HIGH);
    digitalWrite(yellowLED, LOW);
    tone(buzzer, 2000, 2000);
    }

  else if (CO2 < sensorThres && H2 < sensorThres && Smoke >= sensorThres)
    {                                                                        // Smoke Alarm
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, LOW);
    digitalWrite(yellowLED, HIGH);
    tone(buzzer, 4000, 4000);
    }

  else if (CO2 >= sensorThres && H2 >= sensorThres && Smoke < sensorThres)
    {                                                                        // CO2 & H2 Alarm
    digitalWrite(redLED, HIGH);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, HIGH);
    digitalWrite(yellowLED, LOW);
    tone(buzzer, 1000, 1000);
    tone(buzzer, 2000, 2000);
    }

  else if (CO2 >= sensorThres && H2 < sensorThres && Smoke >= sensorThres)
    {                                                                        // CO2 & Smoke Alarm
    digitalWrite(redLED, HIGH);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, LOW); 
    digitalWrite(yellowLED, HIGH);
    tone(buzzer, 1000, 1000);
    tone(buzzer, 4000, 4000);
    }

  else if (CO2 < sensorThres && H2 >= sensorThres && Smoke >= sensorThres)
    {                                                                       // H2, Smoke Alarm
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, HIGH);
    digitalWrite(yellowLED, HIGH);
    tone(buzzer, 2000, 2000);
    tone(buzzer, 4000, 4000);
    }

  else if (CO2 >= sensorThres && H2 >= sensorThres && Smoke >= sensorThres)
    {                                                                      // CO2, H2, Smoke Alarm
    digitalWrite(redLED, HIGH);
    digitalWrite(greenLED, LOW);
    digitalWrite(blueLED, HIGH);
    digitalWrite(yellowLED, HIGH);
    tone(buzzer, 1000, 1000);
    tone(buzzer, 2000, 2000);
    tone(buzzer, 4000, 4000);
    }

  else
    {                                                                     // NO ALARM/STABLE STATE
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, HIGH);
    digitalWrite(blueLED, LOW);
    digitalWrite(yellowLED, LOW);
    noTone(buzzer);
    }

  server.send(200, "text/html", SendHTML(temperature,fahrenheit,humidity,pressure,altitude,altfeet,CO2,H2,Smoke,formattedTime,Date)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(float temperature, float fahrenheit, float humidity, float pressure, float altitude, float altfeet, float CO2, float H2, float Smoke, 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 +="</head>\n";
  ptr +="<body>\n";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>Garage Environmental Monitoring</h1>\n";
  ptr +="<p>Temperature: ";
  ptr +=temperature;
  ptr +="&deg;C</p>";
  ptr +="<p>Temperature: ";
  ptr +=fahrenheit;
  ptr +="&deg;F</p>";
  ptr +="<p>Humidity: ";
  ptr +=humidity;
  ptr +="%</p>";
  ptr +="<p>Pressure: ";
  ptr +=pressure;
  ptr +="hPa</p>";
  ptr +="<p>Altitude: ";
  ptr +=altitude;
  ptr +="m</p>";
  ptr +="<p>Altitude: ";
  ptr +=altfeet;
  ptr +="ft</p>";
  ptr +="<p>CO2 Level: ";
  ptr +=CO2 + 416;
  ptr +="ppm</p>";
  ptr +="<p>H2 Level: ";
  ptr +=H2;
  ptr +="ppm</p>";
  ptr +="<p>Smoke Level: ";
  ptr +=Smoke;
  ptr +="ppm</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 the main error I keep getting back:

Z:\Documents\Arduino\BME280_ESP32_WebSrvr_MQUnifiedSensors_copy_20231021104757\BME280_ESP32_WebSrvr_MQUnifiedSensors_copy_20231021104757.ino: In function 'void setup()':
Z:\Documents\Arduino\BME280_ESP32_WebSrvr_MQUnifiedSensors_copy_20231021104757\BME280_ESP32_WebSrvr_MQUnifiedSensors_copy_20231021104757.ino:78:18: error: 'handle_OnConnect' was not declared in this scope
server.on("/", handle_OnConnect);
^~~~~~~~~~~~~~~~
Z:\Documents\Arduino\BME280_ESP32_WebSrvr_MQUnifiedSensors_copy_20231021104757\BME280_ESP32_WebSrvr_MQUnifiedSensors_copy_20231021104757.ino:79:21: error: 'handle_NotFound' was not declared in this scope
server.onNotFound(handle_NotFound);

Seems like I only get those errors AFTER adding LED logic.

MicroController
Posts: 1707
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Assistance with Environmental Web Server w/ non-Web server related functionality

Postby MicroController » Mon Oct 23, 2023 7:52 am

Move the handle_OnConnect() and handle_NotFound() functions up to before the setup() function; or use a 'forward declaration' by inserting

Code: Select all

void handle_OnConnect();
void handle_NotFound();
somewhere before void setup() { ... }.

This is needed because the compiler needs to see (at least) a declaration of a function before it is used/referenced.

KO4OEH
Posts: 3
Joined: Sun Oct 22, 2023 3:26 pm

Updated: Re: Assistance with Environmental Web Server w/ non-Web server related functionality

Postby KO4OEH » Tue Oct 24, 2023 1:58 pm

Update: nvmd below. Figured out I needed to define CO2, H2 and Smoke in the loop part of the script for it to work right. :)



Thanks! That did indeed get it to compile. Now another issue has raised its head. My else if statements don't appear to be activating my lights and buzzer as expected. However, I've since added a motion sensor with else and if logic, as well, and that does work (basically just outputs 'Motion is detected/not detected' to the Web server based on whether motion sensor has changed from low to high), and that does work. Any idea what gives there on leds and buzzer? Basically the same code as posted previously (second block of code). I would post updated code but I am not at home currently. My green LED does stay lit, but when introducing smoke, I see the value of Smoke go way above the threshold value but still no yellow LED or buzzer.

Who is online

Users browsing this forum: No registered users and 131 guests