/********** V.O. Rui Santos Complete instructions at https://RandomNerdTutorials.com/esp32-plot-readings-charts-multiple/ rev 2025 paulfjujo **********/ #define VERSION "2025-0530" // PB resolu : le choix de BOARD etait mauvais .. OK avec ESP32 Dev Module // test OK avec 2 sondes DS18B20 //#define VERSION "2025-0527" //... PB lecture sensor 1 (DS18B20 #3)????? avec ESP Wrover Kit (all versions) // suite remplacement Freebox V5 ADSL2 par Freebox Revolution sur Fibre Optique en Mars 2025 // 5 charts + 4 instrument + 1 slider cde PWM sur led bleue // ESP pastille Orange ID : ESP_5472F5 // SANS MCP connecté // PB DS18B20 non rafraichie ..si Ntpserver utilisé ?? // rajout 6em Graph : Y axis MCP23017 0 à 255 (lecture port B) // suite rajout image animé de durée reduite de 3sec à 2sec Data I2C OK // sans Graph MCP23017 // modif pause Loop de 2500 à 3000mS // Rajout d'une table contenant gauge DS18B20 + gauge pression + image + gif animé //#define VERSION "2022-0618" //last :19h18 // new script.js see RNTLAB forum // add recherche adresse OWS //#define VERSION "10-06-2022" // 1 seule sonde OWS #include #include // 23/02/2024 renommé ESPAsyncWebServer-master.h en #include // correctif en ligne 842 AsyncWebSocket.cpp #include #include #include #include #include #ifdef With_MCP #include #endif #include #include #include #include #include #define WithNTP //#define With_MCP // OK avec reseau PHONE Redminote11 //const char* ssid = "RedmiNote11"; //const char* password = "k9m5jfurubn"; // pwd > 8 chars //with WIFI freebox revolution const char* ssid = "Freebox-5CF3C9"; const char* password = "mxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxm"; // debut adresses : 192.168.1.2 jusqu'à 192.168.1.12 //passerelle 192.168.1.254 IPAddress ip(192,168,1,12); IPAddress gateway(192,168,1,254); IPAddress subnet(255,255,255,0); IPAddress dns(212,27,40,241); //optional #define OLED_ADDR 0x3C #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // OLED display height, in pixels #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3C // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 #define LOGO_HEIGHT 16 #define LOGO_WIDTH 16 #define paulfjujo_WIDTH 128 #define paulfjujo_HEIGHT 32 // Json Variable to Hold Sensor Readings JSONVar readings; // Timer variables unsigned long lastTime = 0; unsigned long timerDelay =10000; //10sec->60sec char BMPOK=0; char Presschar [10]; #ifdef With_MCP byte mcp_PA=0; byte mcp_PB=0; unsigned int mcp_PAB=0; char MCP_Readchar[10]; #define MCP23017_ADDR 0x22 MCP23017 mcp = MCP23017(MCP23017_ADDR); #endif char Oled_Msg[64]; // up to 18 char en taille 1 int i,j,k; byte type_s; float temperatureC; float temperatureC2; unsigned int Cpt=0; // 22-06 float p = 0.0; // BMP085 Pression float t = 0.0 ; // AM2302 temper float h = 0.0 ; // AM2302 Humid #define DHTTYPE DHT22 ; // DHT type (DHT11, DHT22) int DHTPIN = 5 ; // GPIO D5 <-- Broche du capteur AM2302 char Tempchar [10]; char Humidchar[10]; byte nDevices = 0; byte error=0; byte address=0; #define SCL 22 //ESP32 SCL I2C fil jaune --> SCL BMP085 #define SDA 21 //ESP32 SDA I2C fil vert --> SDA BMP085 const int LedRouge = 19; const int LedBleue = 15; const int LedVerte = 18; const int LedOnBoard = 2; //bleue String message =" "; String sliderValue1 = "0"; int dutyCycle1; char Duty_Slider[10]; #ifdef WithNTP // NTP server to request epoch time const char* ntpServer ="fr.pool.ntp.org"; struct tm timeinfo; // Variable to save current epoch time unsigned long epochTime; const long gmtOffset_sec = 7200; const int daylightOffset_sec = 0; // 0 heure d'ete 3600 heure d'hiver #endif // Création des objets // GPIO DS18B20 const int one_Wire_Bus= 4 ; OneWire ds(one_Wire_Bus);// Setup a oneWire instance to communicate with OneWire devices (DS18B20) DallasTemperature sensors(&ds);// Pass our oneWire reference to Dallas Temperature sensor int NumberOfDevices; //DeviceAddress sensor1= {0x28,0xAA,0x56,0xC1,0x38,0x14,0x01,0x40}; //DeviceAddress sensor2= {0x28,0xAA,0x0D,0x82,0x38,0x14,0x01,0xCD}; //DeviceAddress tempDeviceAddress; DeviceAddress MesSondesDS18B20[4]; Adafruit_BMP085 bmp; // connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL) DHTesp dht; // AM2302 DHT12 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); byte donnes[12]; byte addr[8]; // Address OWS DS18B20 repérée #3 (CRC= 0x40 ) //AA56C1381401 //byte AddrS1[8]= {0x28,0xAA,0x56,0xC1,0x38,0x14,0x01,0x40}; //byte AddrS2[8]= {0x28,0xAA,0x0D,0x82,0x38,0x14,0x01,0xCD}; void check_if_exist_I2C() { nDevices = 0; Serial.println(" "); for (address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX); switch (address) { case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: Serial.println(" MCP23017 2x8 Bits I/O"); // de base + 7 autres break; case 0x28: case 0x29: case 0x2A: // case etc .. Serial.println(" PCF8574 8bits I/O"); // de base + 7 autres break; case 0x37: Serial.println(" LCD 2119 2x16cars"); // de base + 7 autres break; case 0x38: case 0x39: case 0x3A: case 0x3B: // case etc .. Serial.println(" PCF8574A 8bits I/O"); // de base + 7 autres break; case 0x3C: Serial.println( " OLED SSD1306"); break; case 0x53: Serial.println(" ADXL345 board"); break; case 0x57: Serial.println(" EEPROM 512bytes"); break; case 0x68: Serial.println(" RTC DS3231"); break; case 0x77: Serial.println(" BMP 085 Pression"); break; default: Serial.println(" non reconnue"); break; } //switch nDevices++; } delay(20); } //for loop if (nDevices == 0) Serial.println("No I2C devices found"); else Serial.printf("Trouve %3d devices sur le Bus I2C\r\n",nDevices); error=0; delay(200); } //rev 18-06-2022 //Get Sensor Readings and return JSON object // 1 temperature -10 à +40 // 2 Compteur 0 à 999 // 3 Pression 980-1030 mbar // 4 temperature -10 +40 // 8 humidite 0 100% // 5 degres OWS -10 +40 // 6 MCP 0 à 1023 String getSensorReadings(){ sensors.requestTemperatures(); temperatureC = sensors.getTempCByIndex(0); /* * if(sensors.getAddress(tempDeviceAddress, 0)) { // Output the device ID Serial.print("Temperature for device: "); Serial.println(i,DEC); // Print the data temperatureC = sensors.getTempC(tempDeviceAddress); } // else // Serial.println("Problemo\r\n"); temperatureC=99.99; */ readings["DS18B20"] = String(temperatureC); readings["Cpt"] = String(Cpt); p = bmp.readPressure() / 100.0F; //mBar ou hPa readings["Pression"] = String(p); // t = dht.getTemperature(); readings["Temperature"] = String(t); h=dht.getHumidity(); readings["Humidity"] = String(h); #ifdef With_MCP readings["MCP23017"] = String(mcp_PB); #endif String jsonString = JSON.stringify(readings); //Serial.print("jsonString : "); // Serial.println(jsonString); return jsonString; } // Initialize SPIFFS void initSPIFFS() { if (!SPIFFS.begin()) { Serial.println("An error has occurred while mounting SPIFFS"); } else{ Serial.println("SPIFFS mounted successfully"); } } void get_network_info(){ if(WiFi.status() ==3) // WL_CONNECTED) { Serial.print("[*] Network information for "); // Serial.println(ssid); Serial.println("[+] BSSID : " + WiFi.BSSIDstr()); Serial.print("[+] Gateway IP : "); Serial.println(WiFi.gatewayIP()); Serial.print("[+] Subnet Mask : "); Serial.println(WiFi.subnetMask()); Serial.println((String)"[+] RSSI : " + WiFi.RSSI() + " dB"); Serial.print("[+] ESP32 IP : "); Serial.println(WiFi.localIP()); } } String hostname = "ESP_Orange"; // Create AsyncWebServer object on port 80 AsyncWebServer server(80); // Create an Event Source on /events AsyncEventSource events("/events"); // Create a WebSocket object AsyncWebSocket ws("/ws"); void initWiFi() // Initialize WiFi { int i=0; delay(1000); Serial.println("Reseau :"); Serial.print(" SSID: "); Serial.println(ssid); Serial.print(" PWD: "); Serial.println(password); WiFi.begin(ssid, password); // Serial.println("Config IP,Gate,DNS..."); // WiFi.config(ip, gateway, subnet, dns); Serial.println("Start WIFI_AP_STA"); WiFi.mode(WIFI_AP_STA); delay(500); Serial.print("Connecting to WiFi .."); while (WiFi.status() !=3) // WL_CONNECTED) { Serial.print('.'); i++; if (i%32==0) Serial.println("."); delay(1500); } Serial.println("."); Serial.println(WiFi.localIP()); get_network_info(); } void OneWireScanner() { // ds.reset_search(); if ( !ds.search(addr)) { Serial.println(" No more addresses."); Serial.println(); ds.reset_search(); return; } Serial.print(" ROM = "); for( i = 0; i < 8; i++) { Serial.write(' '); Serial.print("0x"); if (addr[i] < 0x10) Serial.write('0'); Serial.print(addr[i], HEX); if ( i != 7 ) { Serial.print(", "); } } if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return; } Serial.println(); // the first ROM byte indicates which chip switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); type_s = 0; break; default: Serial.println(" Device is not a DS18x20 family device."); return; } // Serial.println(); } #ifdef WithNTP void printLocalTime(){ int t=0; do { if(!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); t++; delay(1000); if (t>3) return; } else {break; } } while(t<4); if(t<3) { Serial.println(); Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); Serial.print("Day of week: "); Serial.println(&timeinfo, "%A"); Serial.print("Month: "); Serial.println(&timeinfo, "%B"); Serial.print("Day of Month: "); Serial.println(&timeinfo, "%d"); Serial.print("Year: "); Serial.println(&timeinfo, "%Y"); Serial.print("Hour: "); Serial.println(&timeinfo, "%H"); Serial.print("Minute: "); Serial.println(&timeinfo, "%M"); Serial.print("Second: "); Serial.println(&timeinfo, "%S"); Serial.println(); } } #endif void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) { AwsFrameInfo *info = (AwsFrameInfo*)arg; if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { data[len] = 0; message = (char*)data; // 01-11-2024 // Serial.print("Msg :"); Serial.println(message); if (message.indexOf("1s") >= 0) // pwmSlider1 { sliderValue1 = message.substring(2); dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 1023); // Serial.println(dutyCycle1); // Serial.println( sliderValue1); } } } void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { switch (type) { case WS_EVT_CONNECT: Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); break; case WS_EVT_DISCONNECT: Serial.printf("WebSocket client #%u disconnected\n", client->id()); break; case WS_EVT_DATA: // Serial.printf("WebSocket client #%u EVT Data\n", client->id()); handleWebSocketMessage(arg, data, len); break; case WS_EVT_PONG: case WS_EVT_ERROR: break; } } void initWebSocket() { ws.onEvent(onEvent); server.addHandler(&ws); } void setup() { // Serial port for debugging purposes delay(500); Serial.begin(115200); delay(2000); // some time to connect the Teraterm terminal ON pinMode(4, INPUT_PULLUP); //pinMode(5, INPUT_PULLUP); pinMode(LedBleue, OUTPUT); pinMode(LedRouge, OUTPUT); pinMode(LedVerte, OUTPUT); digitalWrite(LedRouge, 0); pinMode(LedOnBoard, OUTPUT); Serial.println(" PWM test sur led 15"); for (dutyCycle1=0;dutyCycle1<255;dutyCycle1=dutyCycle1+50) { analogWrite(LedBleue, dutyCycle1); delay(1000); } dutyCycle1=0; analogWrite(LedBleue, dutyCycle1); digitalWrite(LedOnBoard, 0); Serial.print(" ESP32_Orange_WROOM32_2x15pins_5_Charts_4_gauges_1slider_ version:"); Serial.println(VERSION); Serial.println(" Board type definition : ESP32 Dev Module"); Serial.println(" ESP32 ESPRESSIF wroom 32 2x15 pins (Orange) ESP_5472F5 sur COM 2 115200bds))"); Serial.println(" with DS18B20,BMP085,Cpt,AM2302 Temp,Humidity,OLED,PWM"); Serial.println(" Led Rouge sur D19 Led verte sur D18 Led Bleue sur D15"); Serial.println(" DHT11-AM2302 sur D5"); Serial.println(" Sonde temper.OWS DS18B20 #3 ID=AA56C1381401 sur D4 "); Serial.println(" I2C Bus sur D21(SDA) et D22(SCL)"); #ifdef With_MCP Serial.println(" BMP085 + OLED SSD1306 + MCP23017 sur le bus I2C"); #else Serial.println(" BMP085 + OLED SSD1306 sur le bus I2C"); #endif Serial.println("\r\nInit I2C1 bus"); Serial.println(" Recherche devices presents sur le bus I2C SCL=22 SDA=21"); Wire.begin(SDA,SCL); // pin on ESP32 delay(1000); check_if_exist_I2C(); Serial.println(".. Fin de test I2C bus \r\n"); sensors.begin(); Serial.println(" Sensors begin :"); // Grab a count of devices on the wire NumberOfDevices = sensors.getDeviceCount(); Serial.print("Locating devices..."); Serial.print("Found "); Serial.print(NumberOfDevices, DEC); Serial.println(" devices sur le bus OWS (D4)."); sensors.requestTemperatures(); j=0; do { OneWireScanner(); j++; }while(jsend(SPIFFS, "/index.html", "text/html"); }); delay(1000); // Request for the latest sensor readings server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){ String json = getSensorReadings(); request->send(200, "application/json", json); json = String(); }); server.on("/currentValue1", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "/text/plain", String(sliderValue1).c_str()); //25-02-2024 k=sliderValue1.length()+1; sliderValue1.toCharArray(Duty_Slider, k); dutyCycle1=atoi(Duty_Slider); // dutyCycle1= atoi(String(sliderValue1).c_str()); }); // new version 2023-1223 // First request will return 0 results unless you start scan from somewhere else (loop/setup) // Do not request more often than 3-5 seconds server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request) { String json = "["; int n = WiFi.scanComplete(); if(n == -2){ WiFi.scanNetworks(true); } else if(n){ for (int i = 0; i < n; ++i){ if(i) json += ","; json += "{"; json += "\"rssi\":"+String(WiFi.RSSI(i)); json += ",\"ssid\":\""+WiFi.SSID(i)+"\""; json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\""; json += ",\"channel\":"+String(WiFi.channel(i)); json += ",\"secure\":"+String(WiFi.encryptionType(i)); // json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false"); json += "}"; } WiFi.scanDelete(); if(WiFi.scanComplete() == -2) { WiFi.scanNetworks(true); } } json += "]"; request->send(200, "application/json", json); json = String(); }); events.onConnect([](AsyncEventSourceClient *client){ if(client->lastId()){ // Serial.printf("Client reconnected! Last msg ID : %u \n", client->lastId()); Serial.printf("Client reconnected! Last msg ID : %u %c%c", client->lastId(),13,10);// 01/11/2024 } client->send("hello!", NULL, millis(), 10000); }); server.addHandler(&events); display.clearDisplay(); #ifdef WithNTP // Init and get the time Serial.println(" Get and print time from ntpServer"); configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); printLocalTime(); #endif // Start server server.begin(); Serial.println("init Websocket"); initWebSocket(); } void loop() { if ((millis() - lastTime) > timerDelay) { // Send Events to the client with the Sensor Readings Every 10 seconds events.send("ping",NULL,millis()); events.send(getSensorReadings().c_str(),"new_readings" ,millis()); lastTime = millis(); delay(1000); } else //1 { #ifdef WithNTP if(Cpt %16==0) { getLocalTime(&timeinfo); Serial.print("Heure: "); Serial.print(&timeinfo, "%H"); Serial.print(":"); Serial.println(&timeinfo, "%M"); } #endif delay(500); Serial.printf(" Cpt= %5d ",Cpt); display.clearDisplay(); display.setCursor(0,0); display.print(F("Compteur ")); display.setCursor(70,0); snprintf(Oled_Msg,6,"% 5d",Cpt); display.print(Oled_Msg); // display.display(); // if (BMPOK==1) // { p = bmp.readPressure() / 100.0F; // } // else // { if (p>1100.0) p=999.99; if (p<940.0) p=999.99; // } Serial.printf(", BMP085 P.% 5.0f mBar ",p); display.setCursor(0,8); delay(50); display.print(F("BMP085 P. ")); display.setCursor(70,8); display.print(p); h=dht.getHumidity(); if (isnan(h)) snprintf(Humidchar,6,"%s\t"," ???"); else snprintf(Humidchar,6,"%2.2f\t",h); Serial.print(F(", Humid: ")); Serial.print(Humidchar); display.setCursor(0,16); delay(50); display.print(F("AM2302 Humi ")); display.setCursor(76,16); display.print(Humidchar); display.display(); t = dht.getTemperature(); delay(150); if (isnan(t)) snprintf(Tempchar,6,"%s\t"," ???"); else snprintf(Tempchar,6,"%3.2f\t",t); Serial.print(F(",Temp: ")); Serial.print(Tempchar); delay(150); sensors.requestTemperatures(); temperatureC = sensors.getTempCByIndex(0); if (temperatureC < -10.0) temperatureC= -10.0; Serial.printf(",DS.1 =% 3.2f C ",temperatureC); if (NumberOfDevices>1) { temperatureC2 = sensors.getTempCByIndex(1); Serial.printf(",DS.2 =% 3.2f C ",temperatureC2); } Serial.printf(", Slider =%5d ", dutyCycle1); // affiche en alternance sur la 4em ligne afficheur OLED // soit Temperature AM2302 , // soit OWS DS18B20 if ((Cpt %4)==0) { digitalWrite(LedRouge,HIGH); display.setCursor(0,24); delay(50); display.print(F("AM2302 Temp ")); display.setCursor(76,24); delay(50); display.print(Tempchar); } else //3 { digitalWrite(LedRouge,LOW); display.setCursor(0,24); delay(50); display.print(F("DS18B20 #1 ")); display.setCursor(76,24); delay(50); display.print(temperatureC); } delay(50); display.display(); #ifdef With_MCP mcp_PA= mcp.readPort(MCP23017Port::A); mcp_PB= mcp.readPort(MCP23017Port::B); mcp.writePort(MCP23017Port::A, i & 0x00FF); Serial.print(",MCP : 0x"); if(mcp_PA<16) Serial.print("0"); Serial.print(mcp_PA, HEX); Serial.print(",0x"); if(mcp_PB<16) Serial.print("0"); Serial.println(mcp_PB, HEX); #else //Serial.printf(", k=%5d",k); Serial.println("."); #endif // PWM led bleue (15) analogWrite(LedBleue, dutyCycle1); Cpt=Cpt+1.0; if (Cpt>999) Cpt=0; } //else 1 delay(750); ws.cleanupClients(); digitalWrite(LedOnBoard,HIGH); delay(100); digitalWrite(LedOnBoard,LOW); delay(100); } /* 24/05/2025* Sketch uses 841677 bytes (64%) of program storage space. Maximum is 1310720 bytes. Global variables use 41248 bytes (12%) of dynamic memory, leaving 286432 bytes for local variables. Maximum is 327680 bytes* * * */