2022-02-27 13:16:44 +01:00
# include <Adafruit_BMP280.h>
# include <ESP8266WiFi.h>
# include <WiFiClient.h>
# include <ESP8266WebServer.h>
# include "DHT.h"
# include <SPI.h>
2022-03-08 16:40:08 +01:00
# include <unistd.h>
2022-02-27 13:16:44 +01:00
2022-03-08 16:40:08 +01:00
# include "proj_conf.h"
2022-02-27 13:16:44 +01:00
2022-03-08 16:40:08 +01:00
# define LED 2 // On board LED
2022-02-27 13:16:44 +01:00
# define DHTTYPE DHT22 // DHT 11
2022-03-08 16:40:08 +01:00
uint8_t DHTPin = 12 ;
DHT dht ( DHTPin , DHTTYPE ) ;
const char * ntpServer = " pool.ntp.org " ;
const long gmtOffset_sec = 3600 ; // Replace with your GMT offset (seconds)
const int daylightOffset_sec = 0 ; // Replace with your daylight offset (seconds)
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0 ;
// constants won't change :
float time_till_update = 10 ;
2022-02-27 13:16:44 +01:00
// define device I2C address: 0x76 or 0x77 (0x77 is library default address)
2022-03-08 16:40:08 +01:00
# define BMP280_I2C_ADDRESS 0x76
2022-02-27 13:16:44 +01:00
// initialize Adafruit BMP280 library
2022-03-08 16:40:08 +01:00
Adafruit_BMP280 bmp280 ;
2022-02-27 13:16:44 +01:00
float humidity , temperature , temperature_2 , pressure ;
2022-03-08 16:40:08 +01:00
int currZambretti = 26 ;
ESP8266WebServer server ( 80 ) ; // Server on port 80
2022-02-27 13:16:44 +01:00
const char MAIN_page [ ] PROGMEM = R " =====(
< ! doctype html >
< html >
< head >
< title > Weather < / title >
2022-03-08 16:40:08 +01:00
< h1 style = " text-align:center; color:red; " > Some Weather < / h1 >
2022-02-27 13:16:44 +01:00
< h3 style = " text-align:center; " > NodeMCU Data Logger < / h3 >
< style >
canvas {
- moz - user - select : none ;
- webkit - user - select : none ;
- ms - user - select : none ;
}
/* Data Table Styling*/
# dataTable {
font - family : sans - serif ;
border - collapse : collapse ;
width : 100 % ;
text - align : center ;
}
# dataTable td, #dataTable th {
border : 1 px solid # ddd ;
padding : 8 px ;
}
# dataTable tr:nth-child(even){background-color: #f2f2f2;}
# dataTable tr:hover {background-color: #ddd;}
# dataTable th {
padding - top : 12 px ;
padding - bottom : 12 px ;
text - align : center ;
background - color : # 050505 ;
color : white ;
}
< / style >
< / head >
< body >
< div >
< table id = " dataTable " >
< tr >
< th > Time < / th >
< th > Temperature ( & deg ; C ) < / th >
< th > Temperature 2 ( & deg ; C ) < / th >
< th > Humidity ( % ) < / th >
< th > Pressure ( hPa ) < / th >
2022-03-08 16:40:08 +01:00
< th > Zambretti < / th >
< th > next update in ( m ) < / th >
2022-02-27 13:16:44 +01:00
< / tr >
< / table >
< / div >
< br >
< br >
< script >
2022-03-08 16:40:08 +01:00
var z_forecast = new Array ( " Settled fine " , " Fine weather " , " Becoming fine " , " Fine, becoming less settled " , " Fine, possible showers " , " Fairly fine, improving " , " Fairly fine, possible showers early " , " Fairly fine, showery later " , " Showery early, improving " , " Changeable, mending " , " Fairly fine, showers likely " , " Rather unsettled clearing later " , " Unsettled, probably improving " , " Showery, bright intervals " , " Showery, becoming less settled " , " Changeable, some rain " , " Unsettled, short fine intervals " , " Unsettled, rain later " , " Unsettled, some rain " , " Mostly very unsettled " , " Occasional rain, worsening " , " Rain at times, very unsettled " , " Rain at frequent intervals " , " Rain, very unsettled " , " Stormy, may improve " , " Stormy, much rain " , " NaN " ) ;
2022-02-27 13:16:44 +01:00
var Tvalues = [ ] ;
var Hvalues = [ ] ;
var timeStamp = [ ] ;
var T2value = [ ] ;
var Pvalue = [ ] ;
2022-03-08 16:40:08 +01:00
var Zvalue = [ ] ;
var dTvalue = [ ] ;
2022-02-27 13:16:44 +01:00
setInterval ( function ( ) {
// Call a function repetatively with 5 Second interval
getData ( ) ;
2022-03-08 16:40:08 +01:00
} , 60000 ) ; //5000mSeconds update rate
2022-02-27 13:16:44 +01:00
function getData ( ) {
var xhttp = new XMLHttpRequest ( ) ;
xhttp . onreadystatechange = function ( ) {
if ( this . readyState = = 4 & & this . status = = 200 ) {
//Push the data in array
var time = new Date ( ) . toLocaleTimeString ( ) ;
var txt = this . responseText ;
var obj = JSON . parse ( txt ) ;
Tvalues . push ( obj . Temperature ) ;
Hvalues . push ( obj . Humidity ) ;
T2value . push ( obj . Temperature_2 ) ;
Pvalue . push ( obj . Pressure ) ;
2022-03-08 16:40:08 +01:00
Zvalue . push ( obj . forcast_num ) ;
dTvalue . push ( obj . time_till_update ) ;
2022-02-27 13:16:44 +01:00
timeStamp . push ( time ) ;
if ( Tvalues . length > 10 ) {
Tvalues . pop ( ) ;
Hvalues . pop ( ) ;
timeStamp . pop ( ) ;
T2value . pop ( ) ;
Pvalue . pop ( ) ;
2022-03-08 16:40:08 +01:00
Zvalue . pop ( ) ;
dTvalue . pop ( ) ;
2022-02-27 13:16:44 +01:00
document . getElementById ( " dataTable " ) . deleteRow ( 10 ) ;
}
//Update Data Table
var table = document . getElementById ( " dataTable " ) ;
var row = table . insertRow ( 1 ) ; //Add after headings
var cell1 = row . insertCell ( 0 ) ;
var cell2 = row . insertCell ( 1 ) ;
var cell3 = row . insertCell ( 2 ) ;
var cell4 = row . insertCell ( 3 ) ;
var cell5 = row . insertCell ( 4 ) ;
2022-03-08 16:40:08 +01:00
var cell6 = row . insertCell ( 5 ) ;
var cell7 = row . insertCell ( 6 ) ;
2022-02-27 13:16:44 +01:00
cell1 . innerHTML = time ;
cell2 . innerHTML = obj . Temperature ;
cell3 . innerHTML = obj . Temperature_2 ;
cell4 . innerHTML = obj . Humidity ;
cell5 . innerHTML = obj . Pressure ;
2022-03-08 16:40:08 +01:00
cell6 . innerHTML = obj . forcast_num + " | " + z_forecast [ obj . forcast_num ] ;
cell7 . innerHTML = obj . time_till_update ;
2022-02-27 13:16:44 +01:00
}
} ;
xhttp . open ( " GET " , " readData " , true ) ; //Handle readData server on ESP8266
xhttp . send ( ) ;
}
< / script >
< / body >
< / html >
) = = = = = " ;
2022-03-08 16:40:08 +01:00
void handleRoot ( )
{
String s = MAIN_page ; // Read HTML contents
server . send ( 200 , " text/html " , s ) ; // Send web page
2022-02-27 13:16:44 +01:00
}
2022-03-08 16:40:08 +01:00
void readData ( )
{
String data = " { \" Temperature \" : \" " + String ( temperature )
+ " \" , \" Humidity \" : \" " + String ( humidity )
+ " \" , \" Temperature_2 \" : \" " + String ( temperature_2 )
+ " \" , \" Pressure \" : \" " + String ( pressure )
+ " \" , \" forcast_num \" : " + String ( currZambretti )
+ " , \" time_till_update \" : " + String ( time_till_update ) + " } " ;
digitalWrite ( LED , ! digitalRead ( LED ) ) ; // Toggle LED on data request ajax
server . send ( 200 , " text/plane " , data ) ; // Send ADC value, temperature and humidity JSON to client ajax request
delay ( 2000 ) ;
temperature = ( dht . readTemperature ( ) ) ;
humidity = dht . readHumidity ( ) ;
// read temperature and pressure from BMP280 sensor
temperature_2 = ( bmp280 . readTemperature ( ) ) ; // get temperature
pressure = ( bmp280 . readPressure ( ) / 100 ) ; // get pressure
Serial . println ( " T1: " + String ( temperature )
+ " T2: " + String ( temperature_2 )
+ " H: " + String ( humidity )
+ " P: " + String ( pressure )
+ " Z: " + String ( currZambretti )
+ " dT: " + String ( time_till_update ) ) ;
2022-02-27 13:16:44 +01:00
}
2022-03-08 16:40:08 +01:00
void setup ( )
2022-02-27 13:16:44 +01:00
{
Serial . begin ( 115200 ) ;
Serial . println ( ) ;
pinMode ( DHTPin , INPUT ) ;
dht . begin ( ) ;
// initialize the BMP280 sensor
2022-03-08 16:40:08 +01:00
// Wire.begin(D1, D2); // set I2C pins [SDA = D2, SCL = D1], default clock is 100kHz
// Wire.begin(4, 0);
2022-02-27 13:16:44 +01:00
Wire . begin ( ) ;
2022-03-08 16:40:08 +01:00
while ( ! bmp280 . begin ( BMP280_I2C_ADDRESS ) )
{
2022-02-27 13:16:44 +01:00
Serial . println ( " BPM280 put " ) ;
delay ( 1000 ) ;
}
2022-03-08 16:40:08 +01:00
WiFi . begin ( ssid , password ) ; // Connect to your WiFi router
2022-02-27 13:16:44 +01:00
Serial . println ( " " ) ;
2022-03-08 16:40:08 +01:00
// Onboard LED port Direction output
pinMode ( LED , OUTPUT ) ;
2022-02-27 13:16:44 +01:00
// Wait for connection
2022-03-08 16:40:08 +01:00
while ( WiFi . status ( ) ! = WL_CONNECTED )
{
2022-02-27 13:16:44 +01:00
delay ( 500 ) ;
Serial . print ( " . " ) ;
}
2022-03-08 16:40:08 +01:00
// If connection successful show IP address in serial monitor
2022-02-27 13:16:44 +01:00
Serial . println ( " " ) ;
Serial . print ( " Connected to " ) ;
Serial . println ( ssid ) ;
Serial . print ( " IP address: " ) ;
2022-03-08 16:40:08 +01:00
Serial . println ( WiFi . localIP ( ) ) ; // IP address assigned to your ESP
server . on ( " / " , handleRoot ) ; // Which routine to handle at root location. This is display page
server . on ( " /readData " , readData ) ; // This page is called by java Script AJAX
server . begin ( ) ; // Start server
configTime ( gmtOffset_sec , daylightOffset_sec , ntpServer ) ;
2022-02-27 13:16:44 +01:00
Serial . println ( " HTTP server started " ) ;
}
2022-03-08 16:40:08 +01:00
void loop ( void )
{
server . handleClient ( ) ; // Handle client requests
unsigned long currentMillis = millis ( ) ;
time_till_update = ( ( interval - ( currentMillis - previousMillis ) ) / 60000.0 ) ;
if ( currentMillis - previousMillis > = interval )
{
// save the last time you blinked the LED
previousMillis = currentMillis ;
zembretti_number_calc ( ) ;
}
2022-02-27 13:16:44 +01:00
}
2022-03-08 16:40:08 +01:00
/////////////////////////////////////////
// WEATHER PREDICTION
/////////////////////////////////////////
int rise_options [ ] = { 25 , 25 , 25 , 24 , 24 , 19 , 16 , 12 , 11 , 9 , 8 , 6 , 5 , 2 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 } ;
int steady_options [ ] = { 25 , 25 , 25 , 25 , 25 , 25 , 23 , 23 , 22 , 18 , 15 , 13 , 10 , 4 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 } ;
int fall_options [ ] = { 25 , 25 , 25 , 25 , 25 , 25 , 25 , 25 , 23 , 23 , 21 , 20 , 17 , 14 , 7 , 3 , 1 , 1 , 1 , 0 , 0 , 0 } ;
float prev_pressure = 0 ;
void zembretti_number_calc ( ) {
Serial . println ( " Calc new Zembretti " ) ;
float curr_pressure = ( bmp280 . readPressure ( ) / 100 ) ; // get pressure
time_t rawtime ;
struct tm * timeinfo ;
time ( & rawtime ) ;
timeinfo = localtime ( & rawtime ) ;
int mon = timeinfo - > tm_mon ;
float pressureRange = ( maxAvgPressure - minAvgPressure ) ;
float calculus = ( float ) curr_pressure ;
int isRising = 0 ;
// calc if pressure is rising or not, default is equal
if ( curr_pressure > prev_pressure )
isRising = 1 ;
else if ( prev_pressure > curr_pressure )
isRising = - 1 ;
if ( isNorthern ) {
// no wind data so ignore calculation for it
if ( mon > = 4 & & mon < = 9 ) { // if Summer
if ( isRising = = 1 ) {
calculus + = ( 7 / 100 ) * pressureRange ;
} else if ( isRising = = - 1 ) {
calculus - = ( 7 / 100 ) * pressureRange ;
}
}
} else {
// no wind data so ignore calculation for it
if ( mon < 4 | | mon > 9 ) { // if Summer
if ( isRising = = 1 ) {
calculus + = ( 7 / 100 ) * pressureRange ;
} else if ( isRising = = - 1 ) {
calculus - = ( 7 / 100 ) * pressureRange ;
}
}
}
calculus = ( curr_pressure - minAvgPressure ) / ( pressureRange / 22 ) ;
prev_pressure = curr_pressure ;
// non expectet values
if ( calculus < 0 ) {
currZambretti = 26 ;
return ;
}
if ( calculus > = 22 ) {
currZambretti = 26 ;
return ;
}
if ( isRising > 0 )
currZambretti = rise_options [ ( int ) calculus ] ;
else if ( isRising < 0 )
currZambretti = fall_options [ ( int ) calculus ] ;
else
currZambretti = steady_options [ ( int ) calculus ] ;
return ;
}