/* * V.O. Rui Santos Complete instructions at https://RandomNerdTutorials.com/esp32-plot-readings-charts-multiple/ rev paulfjujo ******** */ #define VERSION "2024-0601" // suppression message : // WebSocket client #2 EVT Data //Msg :1s12 //122 //12 //#define VERSION "2024-0531" //....OK // pour esp32-8DC994 08:3a:f2:8d:c9:94 BLEU // probleme sur slider value NON retournee //#define VERSION "2024-0224" // 5 charts + 4 instrument + 1 slider #define WithNTP //#define With_MCP //.... MCP HS suite à mauvaise manip!!! // 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 #3 //nota: //Connection sur reseau Smartphone Redminote 11 //Point d'acces Wifi_Mobile //Hot spot portable : //Appareils connectés : 2 // ASUS_CM6431 20:68:9d:04:2b:cf // esp32-5472F4 7c:9e:bd:54:72:f4 ROUGE acces page web 192.168.15.145 // mais avec ESP BLEU //Connection sur reseau Smartphone Redminote 11 //Point d'acces Wifi_Mobile //Hot spot portable : //Appareils connectés : 2 // ASUS_CM6431 20:68:9d:04:2b:cf // esp32-8DC994 08:3a:f2:8d:c9:94 BLEU acces page web avec 192.168.15.30 // COM11 #include #include // 23/02/2024 renommé ESPAsyncWebServer-master.h en #include // correctif en ligne 842 AsyncWebSocket.cpp #include #include #include #ifdef With_MCP #include #endif #include #include #include #include #include #include #include //#include // 192.168.0.111 // OK avec reseau PHONE Redminote11 const char* ssid = "Redmi Note 11"; const char* password = "k9m5jfurubn"; // Bad with WIFI freebox //const char* ssid ="ON_AIR2024"; //const char* password = "pfwasborn@LyonxRousse%1950FriscoEn1983"; #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]; byte mcp_PA=0; byte mcp_PB=0; unsigned int mcp_PAB=0; char MCP_Readchar[10]; #ifdef With_MCP #define MCP23017_ADDR 0x20 MCP23017 mcp = MCP23017(MCP23017_ADDR); #endif char Oled_Msg[64]; // up to 18 char en taille 1 int i,j,k; byte addr[8]; byte type_s; float temperatureC; 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 const int oneWireBus = 4; // GPIO DS18B20 OneWire ds(oneWireBus);// Setup a oneWire instance to communicate with OneWire devices (DS18B20) DallasTemperature sensors(&ds);// Pass our oneWire reference to Dallas Temperature sensor 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); // Address OWS DS18B20 repérée #3 (CRC= 0x40 ) DeviceAddress sensor1 = { 0x28,0xFF, 0xAA, 0x56, 0xC1, 0x38, 0x14, 0x01}; // Address OWS DS18B20 repérée #6 (CRC= 0xCD ) //DeviceAddress sensor2 = { 0x28,0xAA,0x0D,0x82,0x38,0x14,0x01,0xCD}: // 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 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); 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 = "ESP32_Bleu"; //IPAddress ip(192, 168, 0, 110); //IPAddress gateway(192, 168, 0, 254); //IPAddress subnet(255, 255,255, 0); //IPAddress dns(212,27,40,240); //optional void initWiFi() // Initialize WiFi { int i=0; delay(3000); // WiFi.mode(WIFI_AP_STA); WiFi.mode(WIFI_STA); // WiFi.config(ip, gateway, subnet, dns); Serial.println("\nConnecting"); Serial.print(" SSID: "); Serial.println(ssid); Serial.print(" PWD: "); Serial.println(password); WiFi.begin(ssid, password); delay(1000); 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(){ 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; 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: // suppression message 01/06/2024 // 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(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_Bleu_WROOM32_2x15pins_5_Charts_4_gauges_1slider_ version:"); Serial.println(VERSION); Serial.println(" Board type definition : DOIT ESP32 DEVKIT V1"); Serial.println(" ESP32 Vroom 32 2x15 pins (Bleu) sur COM 11 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("\r\n .. Fin de test I2C bus \r\n"); sensors.begin(); Serial.println(" Sensors begin\r\n"); Serial.printf(" Compteur=%5d\r\n",Cpt); //---- Pressure sensor BMP085 ---------------- // Initialisation bmp.begin(); delay(500); p = bmp.readPressure() / 100.0F; delay(500); Serial.printf(" Press.% 5.0f mBar \r\n",p); // if (BMPOK!=1) Serial.println("Problemo BMPOK bad!"); Serial.println(" Scan devices on OWS BUS "); for (i=0;i<3;i++) { Serial.printf(" i= %5d \r\n",i); OneWireScanner(); Serial.println(); delay(1000); } sensors.requestTemperatures(); delay(100); temperatureC = sensors.getTempCByIndex(0); if (temperatureC < -10.0) temperatureC= -9.99; Serial.printf(" DS18B20 =% 3.2f\r\n",temperatureC); #ifdef With_MCP // --- MCP23017 ---------------------- // https://github.com/blemasle/arduino-mcp23017 Serial.println(" MCP23017 at @0x20 "); mcp.init(); Serial.println(" Active le PORT A du MCP , en sorties"); // setGPIOAMode(0); mcp.portMode(MCP23017Port::A, 0); Serial.println(" Active le PORT B du MCP , en entrees"); mcp.portMode(MCP23017Port::B, 0b11111111); //Port B as input mcp.writeRegister(MCP23017Register::GPIO_A, 0x00); //Reset port A mcp.writeRegister(MCP23017Register::GPIO_B, 0x00); //Reset port B // GPIO_B reflects the reverse logic as the input pins state mcp.writeRegister(MCP23017Register::IPOL_B, 0xFF); #endif //----- DHT11 AM2302 Sensor ---------------- dht.setup(DHTPIN,DHTesp::DHT22); delay(1000); t = dht.getTemperature(); if (isnan(t)) snprintf(Tempchar,6,"%s\t"," ???"); else snprintf(Tempchar,6,"%3.2f\t",t); //------------------- h=dht.getHumidity(); if (isnan(h)) snprintf(Humidchar,6,"%s\t"," ???"); else snprintf(Humidchar,6,"%2.2f\t",h); Serial.print(F(" DHT11 Temp.: ")); Serial.println(Tempchar); Serial.print(F(" Humid : ")); Serial.println(Humidchar); //----------- OLED SSD1306 ---------------- // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F(" SSD1306 allocation failed")); delay(1000); } else Serial.println(F(" SSD1306 allocation OK")); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print(F(" Init WIFI ")); display.display(); delay(2000); // Pause for 2 seconds Serial.println("init Wifi"); initWiFi(); delay(2000); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print(F("IP Adresse ")); display.setCursor(0,8); // Start at top-left corner display.print( WiFi.localIP()); display.setCursor(0,16); display.print( WiFi.macAddress()); display.display(); delay(2000); Serial.print( " WiFi mac@ : "); Serial.println( WiFi.macAddress()); Serial.println(); initSPIFFS(); server.serveStatic("/", SPIFFS, "/"); // Web Server Root URL server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(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()); } 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(1500); } else //1 { if(Cpt %8==0) { #ifdef WithNTP getLocalTime(&timeinfo); Serial.print("Heure: "); Serial.print(&timeinfo, "%H"); Serial.print(":"); Serial.print(&timeinfo, "%M"); #endif } delay(1000); 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); // display.display(); 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(); if (isnan(t)) snprintf(Tempchar,6,"%s\t"," ???"); else snprintf(Tempchar,6,"%3.2f\t",t); Serial.print(F(",Temp: ")); Serial.print(Tempchar); sensors.requestTemperatures(); temperatureC = sensors.getTempCByIndex(0); if (temperatureC < -10.0) temperatureC= -10.0; Serial.printf(",DS18B20.0 =% 3.2f C ",temperatureC); Serial.printf(", Slider =%5d ", dutyCycle1); // affiche en alternance soit Temperature AM2302 , soit OWS DS18B20 sur la 4em ligne afficheur OLED 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 ")); 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(1000); ws.cleanupClients(); digitalWrite(LedOnBoard,HIGH); delay(100); digitalWrite(LedOnBoard,LOW); delay(100); } /* */