บอร์ด ESP32LoRa-Part-1
ก่อนอื่นต้องขออภัยคุณลูกค้าผู้ให้การสนับสนุนบอร์ดรุ่นนี้ ที่คู่มือรวมเล่มออกมาหลังจากจัดจำหน่ายบอร์ดไปหมดแล้ว คงเหลือไว้สำหรับดูเล่นและไว้ซ้อมมือบอร์ดเดียว
บอร์ดนี้ถูกออกแบบมาเพื่อตอบโจทย์หลายอย่างด้วยกันและความต้องการให้ประหยัดที่สุดที่มีประสิทธิภาพมากที่สุด
องค์ประกอบและความสามารถของบอร์ด
- MCU : ESP32-Doit 30 pins
- Input :
- I2C
- RS485
- UART
- ADC 4 channel
- Output : 4 x Relay (NO+NC) , Coil 4 Vdc, Load 220 Vac 10A max
- RTC : Onboard DS
- ADS1115 ขยายการเชื่อมต่อ
- Power Supply : 12 Vdc
- Coomunication : WiFI, LoRa
- Programming : Arduino IDE
การประยุกต์ใช้งาน สามารถใช้ได้กับ สมาร์ทฟาร์ม สมาร์ทโฮม บอร์ดหลักสามารถควบคุมอุปกรณ์ได้ 4 ตัวและสามารถเชื่อมต่อควบคุม RS485 Relay ได้ตามความต้องการ
- ตัวอย่างเซนเซอร์ที่แนะนำใช้งาน
- I2C , AM2315 , LCD
- RS485 , SHT20(XYMD01) , XYMD02 , Soil moisture, Soil NPK sensor , Power meter
- UART , PZEM
- ADC , pH , EC analog meter, DHT11, DHT21
สำหรับการเชื่อมต่อขาเราจะนำมาแสดงไว้เฉพาะส่วนสำคัญๆ ครับ
ไลบรารีที่จำเป็นสำหรับการใช้งานบอร์ดนี้ให้เต็มประสิทธิภาพ
- Converter ตามลิงก์นี้
- Arduino Json ตามตัวอย่างด้านล่าง
- ModbusMaster ตามลิงก์นี้
- MosbusRTU ตามลิงก์นี้
- LiquidCrytsal_I2C จาก Arduino IDE
- LoRa ตามลิงก์นี้
- PZEM จาก Arduino IDE หรือ ลิงก์นี้
- SoftwareSerial จาก Arduino IDE
- ESP32SoftwareSerial ตามลิงก์นี้
- HardwareSerial จากการติดตั้ง ESP32 หรือตามลิงก์นี้
- Arduino จากการติดตั้ง Arduino IDE เริ่มต้น
- SPI จากการติดตั้ง ESP32 หรือตามลิงก์นี้
- Ticker จากการติดตั้ง ESP32 หรือตามลิงก์นี้
- WiFi จากการติดตั้ง ESP32 หรือตามลิงก์นี้
โดยบางไลบรารี สามารถติดตั้งจาก Arduino IDE ได้เลย
และขอเน้นว่าให้ตั้งค่าบอร์ดเป็น Version 1.0.6 ครับ มิฉะนั้นจะมีปัญหาบางประการเช่น รุ่นของ LoRa , I2C
สำหรับโค้ดรวมของโปรแกรมตามนี้เลยครับ มันจะยาวหน่อย แต่ในโค้ดเดียวนี้มันทำงานได้ครบทุกอย่างตามที่ออกแบบไว้ และจะมาขยายความกันทีละส่วน
///////////////////////////////////////////// // DEFINE ///////////////////////////////////////////// #define VERSION "3.0" // เพื่อการตรวจเชค OTA ///////////////////////////////////////////// ///////////////////////////////////////////// extern "C" { #include "freertos/FreeRTOS.h" // มีปัญหากับ esp8266 #include "freertos/timers.h" } // CONFIG #include <ArduinoJson.h> #ifdef ESP32 #include <SPIFFS.h> #else #include <FS.h> #endif // เลือก ไลบรารีสำหรับ WIFI #ifdef ESP32 #include <WiFi.h> #include <WiFiMulti.h> #else #include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #define ARDUINO_EVENT_WIFI_STA_GOT_IP WIFI_EVENT_STAMODE_GOT_IP #define ARDUINO_EVENT_WIFI_STA_DISCONNECTED WIFI_EVENT_STAMODE_DISCONNECTED #endif // เตรียมการสำหรับ OTA ระหว่าง ESP32 กับ ESP8266 #ifdef ESP32 #include <Update.h> #else #include <ESP8266httpUpdate.h> #endif #include <SoftwareSerial.h> // https://github.com/PaulStoffregen/SoftwareSerial #include <Convert.h> #include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster #include <ModbusRtu.h> #include <HardwareSerial.h> #include <Arduino.h> //// สำหรับการเชื่อมต่อ SPI LoRa #include <SPI.h> // include libraries #include <Ticker.h> #include <LoRa.h> #include <Wire.h> //// #include "define.h" // สำหรับเรียกไฟล์ define.h ในโฟลเดอร์เดียวกัน #include <math.h> #include <ArduinoJson.h> #include <Arduino_JSON.h> //============== ///====== สำหรับการสื่อสาร RS485 ขั้วสีแดง #define RX_PIN 16 //Serial Receive pin 16 #define TX_PIN 17 //Serial Transmit pin 17 #define MAX485_RE_NEG 15 //LED #define RS485Transmit HIGH #define RS485Receive LOW #define LED 0 float temp, pH ; //========== XYMD02 = RS485 สำหรับอ่าน XYMD02 และ SHT20 HardwareSerial RTU_Serial(2); // 1 Modbus master(0, RTU_Serial, MAX485_RE_NEG); // this is master and RS-232 or USB-FTDI modbus_t telegram[4]; bool restart; uint16_t au16data[8]; float humidity; float temperature; uint8_t RTU_Slave_ID; uint8_t RTU_NEW_Slave_ID; uint8_t Slave_ID; //====== SoftwareSerial RS485Serial(RX_PIN, TX_PIN); //Creation of class object Convert convert; //====== สำหรับการวัดไฟฟ้าด้วย PZEM #include <PZEM004Tv30.h> #if !defined(PZEM_RX_PIN) && !defined(PZEM_TX_PIN) #define PZEM_RX_PIN 4 #define PZEM_TX_PIN 5 #endif #if !defined(PZEM_SERIAL) #define PZEM_SERIAL Serial1 #endif #if defined(ESP32) /************************* ESP32 initialization --------------------- The ESP32 HW Serial interface can be routed to any GPIO pin Here we initialize the PZEM on Serial2 with RX/TX pins 16 and 17 */ PZEM004Tv30 pzem(PZEM_SERIAL, PZEM_RX_PIN, PZEM_TX_PIN); #elif defined(ESP8266) /************************* ESP8266 initialization --------------------- Not all Arduino boards come with multiple HW Serial ports. Serial2 is for example available on the Arduino MEGA 2560 but not Arduino Uno! The ESP32 HW Serial interface can be routed to any GPIO pin Here we initialize the PZEM on Serial2 with default pins */ PZEM004Tv30 pzem(Serial1); #else /************************* Arduino initialization --------------------- Not all Arduino boards come with multiple HW Serial ports. Serial2 is for example available on the Arduino MEGA 2560 but not Arduino Uno! The ESP32 HW Serial interface can be routed to any GPIO pin Here we initialize the PZEM on Serial2 with default pins */ PZEM004Tv30 pzem(PZEM_SERIAL); #endif // #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // //========= //====== //=================== #include <Adafruit_Sensor.h> #include <DHT.h> // กรณีนี้ต้องใช้คู่กันกับ DHT_U.h #include <DHT_U.h> // See guide for details on sensor wiring and usage: // https://learn.adafruit.com/dht/overview uint32_t delayMS; //=========== /* # This sample code is used to test the pH meter V1.0. # Editor : YouYou # Ver : 1.0 # Product: analog pH meter # SKU : SEN0161 */ //#define SensorPin A0 //pH meter Analog output to Arduino Analog Input 0 #define Offset -2.00 //deviation compensate #define LED 13 #define samplingInterval 20 #define printInterval 800 #define ArrayLenth 20 // 40 times of collection int pHArray[ArrayLenth]; //Store the average value of the sensor feedback int pHArrayIndex = 0; // #define Slave_ID1 1 // see dip swith if connect to Transpower #define BAND 915E6 //you can set band here directly,e.g. 868E6,915E6,433E6 // instantiate ModbusMaster object ModbusMaster modbus; // OTA WiFiClient otaClient; //=== Ticker _service_rtc; Ticker _service_sensor; Ticker _service_led; //Ticker _service_test_1; //Ticker _service_test_2; //Ticker _service_test_3; TwoWire I2C0 = TwoWire(0); adsGain_t m_gain; uint8_t m_bitShift; uint16_t m_dataRate; uint8_t Relay, gpio_in; uint16_t delayx, count_read; uint8_t i2c_address_adc; int16_t adc0, adc1, adc2, adc3; float volts0, volts1, volts2, volts3; uint8_t veri; uint8_t LED_State; uint32_t Interval_Time_Old[4]; uint16_t Interval[4]; uint32_t lastreading; char cstr[8]; byte global_second, global_minute, global_hour, global_dayOfWeek, global_dayOfMonth, global_month, global_year; //=== double res_dbl0; double res_dbl1; double res_dbl ; unsigned int counter = 0; String rssi = "RSSI --"; String packSize = "--"; String packet ; String RS485_Data[13]; //======สำหรับ WiFi ที่จะเชื่อมต่อ หากมาหลายตัวในบริเวณใกล้กัน const char* ssid = "Asenal2021_2G"; const char* password = "kb75699212"; const char* ssid1 = "Asenal2021_2G"; const char* password1 = "kb75699212"; const char* ssid2 = "Asenal2021_2G"; const char* password2 = "kb75699212"; //===== Server config , ID, Code //const char* host = "http://192.168.1.34"; const char* host = "myiotcity.com"; char* code = "123rr"; char* dID = "204"; //=== PM 2.5 float dustDensity = 35; String response = "0"; String response_c = "0"; String a ; //=== กด เพื่อ OTA int npress ; //== ตั้งค่ารอบเพื่อการ รีสตาร์ท int cnt = 7200; // every 24 hrs cycle = 12 second // //== ตัวแปรใช้งานทั่วไป float temp_0 = 0; float humid_0 = 0; float vHumidity = 0; float vTemperature = 0; float vPower = 0; float vVolt = 0; float iamp = 0; float vEnergy = 0; float v0, v1, v2, v3; float voltage; float current; float power; float energy; float frequency; float pHValue; float pf; String data0 ; // for data request ; String data1 ; String datasend ; String datasend1 ; String datasend2 ; String data2 ; String data3 , dataa3 ; String data4 , dataa4 ; String data5 , dataa5 ; String data6 , dataa6 ; String data7 ; String data8 ; String data9 ; String JSONSerial = ""; float jdata1, jdata2, jdata3, jdata4, jjdata3, jjdata4, jdata5, jdata6 ; float tempdiff = 0 ; float tempdiff_Max = 5; float humdiff = 0 ; /// === String sdata1 ; String sdata2 ; // standard String sdata3 ; String sdata4 ; String sdata5 ; String sdata6 ; String sdata7 ; String sdata8 ; String sdata11; String sdata12 ; String master_state ; String FlowLowStatus ; String ResetPinValue ; String MainPump ; String PumpA ; String PumpB ; String flowsensor ; String led1 = "00:00"; String led2 = "00:00"; String led3 = "1"; String Time1 ; String Time2 ; String R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 ; String RR1, RR2, RR3, RR4, RR5, RR6, RR7, RR8, RR9, RR10, R_OTA, RR_OTA ; String CommandR3Slave = "Off" ; // to control R3 on Nano String CommandR4Slave ; // to control R4 on board float data10 = 0; float data11 = 0; float data12 = 0; float data13 = 0; float data14 = 0; float data15 = 0; float data16 = 0; float data17 = 0; float data18 = 0; float data19 = 0; float data20 = 0; float EC ; float temperatureC = 0; float temperatureF = 0; float sensorValue = 0; float rainmm = 0; //int counter = 1; int i ; int sentcount = 0; String url ; int Relay1 = 12 ; int Relay2 = 2 ; int LoRa_counter = 0; // String iddevice = dID; String cccode = code; String ccode = code; long lastMillis = 100; /// === String sentpacket ; String str; char charBuf[100]; // Convent 32bit to float //------------------------------------------------ float HexTofloat(uint32_t x) { return (*(float*)&x); } uint32_t FloatTohex(float x) { return (*(uint32_t*)&x); } //------------------------------------------------ //== GPIO12 User Switch นับการกดเพื่อ OTA struct Button { const uint8_t PIN; uint32_t numberKeyPresses; bool pressed; }; Button button1 = {12, 0, false}; // GPIO12 void IRAM_ATTR isr() { button1.numberKeyPresses += 1; button1.pressed = true; npress = button1.numberKeyPresses; } ///////// void OTA_reset_setup() { pinMode(button1.PIN, INPUT_PULLUP); attachInterrupt(button1.PIN, isr, FALLING); } void OTA_SW_loop() { //RR_OTA = "0"; if (button1.pressed) { Serial.printf("Button SW1 has been pressed %u times\n", button1.numberKeyPresses); button1.pressed = false; //RR_OTA = "1"; } if (npress >= 10) { npress = 0; button1.numberKeyPresses = 0; Serial.println("Otrix-OTA: START"); char* ota_host = "otrixiot.com"; uint16_t ota_port = 80; char* ota_path = "/otaaa/sompoch/Dev32101.bin"; ota_run(ota_host, ota_port, ota_path); //Serial.println("Restarting with new firmware ... "); //restart = true; } } /// OTRIXOTA void Otrix_OTA() { if (RR_OTA == "1") { Serial.println("Otrix-OTA: START"); char* ota_host = "otrixiot.com"; uint16_t ota_port = 80; char* ota_path = "/otaaa/sompoch/Dev32101.bin"; ota_run(ota_host, ota_port, ota_path); //Serial.println("Restarting with new firmware ... "); //restart = true; } } ///////////////////////////////////////////// // OTA Over-The-Air ///////////////////////////////////////////// String ota_getHeaderValue(String header, String headerName) { return header.substring(strlen(headerName.c_str())); } void ota_run(char *ota_host, uint16_t ota_port, char *ota_path) { #ifdef ESP8266 ESPhttpUpdate.update(otaClient, ota_host, ota_port, ota_path); #else // ESP32 long contentLength = 0; bool isValidContentType = false; Serial.println("OTA: READY"); Serial.println("Connecting to: " + String(ota_host)); // Connect to S3 if (otaClient.connect(ota_host, ota_port)) { // Connection Succeed. // Fecthing the bin Serial.println("Fetching Bin: " + String(ota_path)); // Get the contents of the bin file otaClient.print(String("GET ") + ota_path + " HTTP/1.1\r\n" + "Host: " + ota_host + "\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n\r\n"); // Check what is being sent // Serial.print(String("GET ") + bin + " HTTP/1.1\r\n" + // "Host: " + host + "\r\n" + // "Cache-Control: no-cache\r\n" + // "Connection: close\r\n\r\n"); unsigned long timeout = millis(); while (otaClient.available() == 0) { if (millis() - timeout > 5000) { Serial.println("Client Timeout !"); otaClient.stop(); return; } } // Once the response is available, // check stuff /* Response Structure HTTP/1.1 200 OK x-amz-id-2: NVKxnU1aIQMmpGKhSwpCBh8y2JPbak18QLIfE+OiUDOos+7UftZKjtCFqrwsGOZRN5Zee0jpTd0= x-amz-request-id: 2D56B47560B764EC Date: Wed, 14 Jun 2017 03:33:59 GMT Last-Modified: Fri, 02 Jun 2017 14:50:11 GMT ETag: "d2afebbaaebc38cd669ce36727152af9" Accept-Ranges: bytes Content-Type: application/octet-stream Content-Length: 357280 Server: AmazonS3 {{BIN FILE CONTENTS}} */ while (otaClient.available()) { // read line till /n String line = otaClient.readStringUntil('\n'); // remove space, to check if the line is end of headers line.trim(); // if the the line is empty, // this is end of headers // break the while and feed the // remaining `client` to the // Update.writeStream(); if (!line.length()) { //headers ended break; // and get the OTA started } // Check if the HTTP Response is 200 // else break and Exit Update if (line.startsWith("HTTP/1.1")) { if (line.indexOf("200") < 0) { Serial.println("Got a non 200 status code from server. Exiting OTA Update."); break; } } // extract headers here // Start with content length if (line.startsWith("Content-Length: ")) { contentLength = atol((ota_getHeaderValue(line, "Content-Length: ")).c_str()); Serial.println("Got " + String(contentLength) + " bytes from server"); } // Next, the content type if (line.startsWith("Content-Type: ")) { String contentType = ota_getHeaderValue(line, "Content-Type: "); Serial.println("Got " + contentType + " payload."); if (contentType == "application/octet-stream") { isValidContentType = true; } } } } else { // Connect to S3 failed // May be try? // Probably a choppy network? Serial.println("Connection to " + String(host) + " failed. Please check your setup"); // retry?? // execOTA(); } // Check what is the contentLength and if content type is `application/octet-stream` Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType)); // check contentLength and content type if (contentLength && isValidContentType) { // Check if there is enough to OTA Update bool canBegin = Update.begin(contentLength); // If yes, begin if (canBegin) { Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!"); // No activity would appear on the Serial monitor // So be patient. This may take 2 - 5mins to complete size_t written = Update.writeStream(otaClient); if (written == contentLength) { Serial.println("Written : " + String(written) + " successfully"); } else { Serial.println("Written only : " + String(written) + "/" + String(contentLength) + ". Retry?" ); // retry?? // execOTA(); } if (Update.end()) { Serial.println("OTA done!"); if (Update.isFinished()) { Serial.println("Update successfully completed. Rebooting."); ESP.restart(); } else { Serial.println("Update not finished? Something went wrong!"); } } else { Serial.println("Error Occurred. Error #: " + String(Update.getError())); } } else { // not enough space to begin OTA // Understand the partitions and // space availability Serial.println("Not enough space to begin OTA"); otaClient.flush(); } } else { Serial.println("There was no content in the response"); otaClient.flush(); } #endif } ////////////////////////////////////////////////////////// void Aboutme() { Serial.println("File name : Mungmee-001-SMT-005-Dev-308-J6-OTA-RST-Test"); Serial.println("I2C-AM2315"); Serial.println("PZEM004T V3"); Serial.println("RS485-Soil Sensor"); Serial.println("RE485-XYMD02"); Serial.println("Timer 6,7,8 = Relay 6,7,8 "); } ///////////////////////////////////////////////////////// void setup_XYMD02() { delay(250); Serial.begin(115200); pinMode(LED, OUTPUT); pinMode(MAX485_RE_NEG, OUTPUT); digitalWrite( MAX485_RE_NEG, LOW );//RX RTU_Serial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); master.start(); master.setTimeOut( 1000 ); // if there is no answer in 2000 ms, roll over humidity = 0.00; temperature = 0.00; // this is utility donot delete , used for change slave id //RTU_Slave_ID = 1; //RTU_NEW_Slave_ID = 2; //Change_Slave_ID(RTU_Slave_ID, RTU_NEW_Slave_ID); } void setup_SMT005(void) { delay(200); pinMode(ESP32_LED, OUTPUT); pinMode(PIN_LED, OUTPUT); digitalWrite(PIN_LED, LOW); pinMode(RELAY1, OUTPUT); pinMode(RELAY2, OUTPUT); pinMode(RELAY3, OUTPUT); pinMode(RELAY4, OUTPUT); //test_relay(); delay(250); Wire.begin(SDA0, SCL0, 100000); //100000 I2C_Address_Scand(); Relay = 0; // DS3231 seconds, minutes, hours, day, date, month, year //set_time_ds1307(0, 20, 16, 1, 27, 3, 22); //LoRa_setup(); LoRa.setPins(RFM95_CS, RFM95_RST, RFM95_IRQ); // set CS, reset, IRQ pin if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz Serial.println("LoRa init failed. Check your connections."); while (true); // if failed, do nothing } delay(100); veri = LoRa.readRegister(0x42); // Semtech ID relating the silicon revision Serial.println(""); Serial.print(">> Registers RFM95 VERSION = "); Serial.println(veri); Serial.println(""); Serial.println(">> Dump - Registers RFM95 "); LoRa.dumpRegisters(Serial); delay(500); m_bitShift = 0; m_gain = GAIN_TWOTHIRDS; m_dataRate = RATE_ADS1115_128SPS; //RATE_ADS1115_8SPS; //RATE_ADS1115_128SPS; delay(20); Interval[0] = 1000; // ADS1115 Interval[1] = 1000; // RTC Interval[2] = 250; // LED count_read = 0; //_service_rtc.attach(1, service_rtc); // interval 1 sec //_service_sensor.attach(5, service_sensor); // interval 5 sec _service_led.attach(0.5, service_led); // interval 500 msec // _service_test_1.attach(1, service_test_1); // _service_test_2.attach(2, service_test_2); // _service_test_3.attach(3, service_test_3); } //=== void setup_LCD() { lcd.begin(); lcd.setCursor(0, 0); lcd.print("Samong IOT"); lcd.setCursor(0, 2); lcd.print("Samong Thailand"); } void LCD_energy() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Energy con."); lcd.setCursor(0, 1); lcd.print("Volt : Vac"); lcd.setCursor(0, 2); lcd.print("Current: A"); lcd.setCursor(10, 1); lcd.print(data7); lcd.setCursor(10, 2); lcd.print(data8); delay(2000); } void LCD_weather() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Farm Weather"); lcd.setCursor(0, 1); lcd.print("Temp'c : 'c"); lcd.setCursor(0, 2); lcd.print("Humid : %"); lcd.setCursor(10, 1); lcd.print(data3); lcd.setCursor(10, 2); lcd.print(data4); delay(2000); } void LCD_pH() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" pH-EC Status"); lcd.setCursor(0, 1); lcd.print("pH : "); lcd.setCursor(0, 2); lcd.print("EC : us/cm2"); lcd.setCursor(7, 1); lcd.print(pHValue); lcd.setCursor(7, 2); lcd.print(pHValue); delay(2000); } void LCD_Pump_Status() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Pump Status"); lcd.setCursor(0, 1); lcd.print("Main Pump : "); lcd.setCursor(0, 2); lcd.print("Pump A : "); lcd.setCursor(0, 3); lcd.print("Pump B : "); lcd.setCursor(13, 1); lcd.print(MainPump); lcd.setCursor(13, 2); lcd.print(flowsensor); lcd.setCursor(13, 3); lcd.print(PumpB); delay(2000); } void LCD_Time_Setting() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Time Setting"); lcd.setCursor(0, 1); lcd.print("Pump Start: "); lcd.setCursor(0, 2); lcd.print("Pump Stop : "); lcd.setCursor(0, 3); lcd.print("Pump A,B : same "); lcd.setCursor(12, 1); lcd.print(Time1); lcd.setCursor(12, 2); lcd.print(Time2); delay(2000); } void LCD_Control_Setting() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Control Value"); lcd.setCursor(0, 1); lcd.print("Value : High - Low"); lcd.setCursor(0, 2); lcd.print("pH : "); lcd.setCursor(0, 3); lcd.print("EC : "); lcd.setCursor(10, 2); lcd.print(led3); lcd.setCursor(10, 3); lcd.print(led1); delay(2000); } //=== void preTransmission() { digitalWrite(MAX485_RE_NEG, HIGH); //Switch to transmit data } void postTransmission() { digitalWrite(MAX485_RE_NEG, LOW); //Switch to receive data } //==== void logo() { } //////// void WiFisetup() { Serial.println(); Serial.print("Connecting to "); Serial.println(ssid1); WiFi.begin(ssid1, password1); delay(1500); if (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("Failed to connected ssdi1 and WiFi setup "); WiFi.begin(ssid2, password2); delay(1500); if (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("Failed to connected ssdi 2 and WiFi setup "); } else { ssid = ssid2; password = password2; } } else { ssid = ssid1; password = password1; Serial.println(""); Serial.println("WiFi connected OK"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } } //// void RS485_setup() { pinMode(MAX485_RE_NEG, OUTPUT); // Init in receive mode digitalWrite(MAX485_RE_NEG, LOW); // Modbus communication runs at 9600 baud // Serial.begin(9600, SERIAL_8N1); //RS485Serial.begin(9600); // , SERIAL_8N1, RX_PIN, TX_PIN); Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // serial can be no1 , no 2 8N1 modbus.begin(Slave_ID1, Serial2);// Serial2 // Callbacks allow us to configure the RS485 transceiver correctly modbus.preTransmission(preTransmission); modbus.postTransmission(postTransmission); } void Soil_Sensor_RS485_setup() { pinMode(MAX485_RE_NEG, OUTPUT); // Modbus communication runs at 9600 baud RS485Serial.begin(9600); // , SERIAL_8N1, RX_PIN, TX_PIN); } bool state = true; /// for gateway /// for gateway void WiFiForwardSetup() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); /* while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } */ Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void LoRa_setup() { delay(500); //Serial.begin(115200); Serial.println(""); Serial.println(" >> ESP32_RFM95_SX1276_LoRaReceiver"); LoRa.setPins(RFM95_CS, RFM95_RST, RFM95_IRQ); // set CS, reset, IRQ pin if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz Serial.println("LoRa init failed. Check your connections."); while (true); // if failed, do nothing } Serial.println(""); //Serial.println(">> Dump - Registers"); //LoRa.dumpRegisters(Serial); //Wire.begin(SDA0, SCL0, 100000); //I2C_Address_Scand(); //delay(2000); //set_time_ds1307(0, 1, 9, 5, 1, 11, 21); } void LoRa_Receive_loop() { // try to parse packet Serial.println("LoRa loop ... "); int packetSize = LoRa.parsePacket(); if (packetSize) { // received a packet Serial.print("Received packet '"); // read packet while (LoRa.available()) { Serial.print((char)LoRa.read()); } // print RSSI of packet Serial.print("' with RSSI "); Serial.println(LoRa.packetRssi()); } } void setup() { Aboutme(); OTA_reset_setup(); setup_XYMD02(); //delay(100000); setup_SMT005(); pH_setup(); WiFi.setAutoReconnect(true); WiFi.persistent(true); setup_LCD(); WiFiForwardSetup(); //LoRa.onReceive(cbk); //LoRa.receive(); } void loop() { Otrix_OTA(); // OTA Serial.println("======================================"); Serial.print("Version : "); Serial.println(VERSION); Serial.println("======================================"); counter = counter + 1; ESP32_BoardTest_loop(); SMT_loop(); Energy(); pH_loop(); XYMD02_loop(); //LoRa_setup(); delay(1000); if (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Failed to connected and will restart WiFi setup "); WiFi.disconnect(); //WiFi.begin(ssid, password); WiFiForwardSetup(); } Forward_loop(); //Serial.println("Start SerRead loop ... "); LCD_display(); LCD_pH(); LCD_energy(); LCD_weather(); LCD_pH(); read_master_status_FromServer(); LCD_Time_Setting(); LCD_Control_Setting(); Relay_Actuator(); LCD_Pump_Status(); //data1 = sdata11; //data2 = sdata12; OTA_SW_loop(); //LoRa_Receive_loop(); Restart_loop(); } // RS485 loop void RS485_loop1() { ///========================= // Toggle the coil at address 0x0002 (Manual Load Control) uint16_t result = modbus.writeSingleCoil(0x0002, state); state = !state; // Read 16 registers starting at 0x3100) result = modbus.readInputRegisters(0x3100, 16); if (result == modbus.ku8MBSuccess) { Serial.print("Vbatt: "); Serial.println(modbus.getResponseBuffer(0x04) / 100.0f); Serial.print("Vload: "); Serial.println(modbus.getResponseBuffer(0xC0) / 100.0f); Serial.print("Pload: "); Serial.println((modbus.getResponseBuffer(0x0D) + modbus.getResponseBuffer(0x0E) << 16) / 100.0f); } ///======= long currentMillis = millis(); if (currentMillis - lastMillis > 1000) { float result = modbus.readHoldingRegisters(0x01, 20); // 0x32 is ok for PM2230 from 10 will get 2 voltage // soil sensor from address 02 if (getResultMsg(&modbus, result)) { Serial.println(); float res_dbl = modbus.getResponseBuffer(1); float value = res_dbl; String res = "Voltage A : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data2 = String(res_dbl); res_dbl = value - modbus.getResponseBuffer(2) ; res = "Voltage B : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data3 = String(res_dbl); res_dbl = modbus.getResponseBuffer(3); res = "Voltage C : " + String(res_dbl) + " \r\n"; Serial.println(res); data4 = String(res_dbl); res_dbl = modbus.getResponseBuffer(4); res = "Frequency : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data5 = String(res_dbl); res_dbl = modbus.getResponseBuffer(5); res = "Hz : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data6 = String(res_dbl); res_dbl = modbus.getResponseBuffer(6) / 100; res = "Value 26 : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data7 = String(res_dbl); res_dbl = modbus.getResponseBuffer(7) / 100; res = "Power : " + String(res_dbl) + " watt\r\n"; Serial.println(res); data8 = String(res_dbl); res_dbl = modbus.getResponseBuffer(8); res = "Value 28 : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); //delay(2000); data9 = String(res_dbl); } lastMillis = currentMillis; } } bool getResultMsg(ModbusMaster *node, uint16_t result) { String tmpstr2 = "\r\n"; switch (result) { case node->ku8MBSuccess: return true; break; case node->ku8MBIllegalFunction: tmpstr2 += "Illegal Function"; break; case node->ku8MBIllegalDataAddress: tmpstr2 += "Illegal Data Address"; break; case node->ku8MBIllegalDataValue: tmpstr2 += "Illegal Data Value"; break; case node->ku8MBSlaveDeviceFailure: tmpstr2 += "Slave Device Failure"; break; case node->ku8MBInvalidSlaveID: tmpstr2 += "Invalid Slave ID"; break; case node->ku8MBInvalidFunction: tmpstr2 += "Invalid Function"; break; case node->ku8MBResponseTimedOut: tmpstr2 += "Response Timed Out"; break; case node->ku8MBInvalidCRC: tmpstr2 += "Invalid CRC"; break; default: tmpstr2 += "Unknown error: " + String(result); break; } Serial.println(tmpstr2); return false; } /////////////////////////////////// int value = 0; void Forward_loop() { ++value; Serial.print("connecting to server .... "); //Serial.println(host); // Use WiFiClient class to create TCP connections WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } // We now create a URI for the request String url = "/api/insertData?device_id=" + String(iddevice) + "&code=" + String(ccode) + "&data1=" + String(data7) + "&data2=" + String(data8) + "&data3=" + String(data3) + "&data4=" + String(data4) + "&data5=" + String(v0) + "&data6=" + String(pHValue) + "&data7=" + String(data7) + "&data8=" + String(data8) + "&data9=" + String(data9) + "&data10=" + String(data10) + "&data11=" + String(data11) + "&data12=" + String(22) + "&data13=" + String(13) + "&data14=" + String(14) + "&data15=" + String(15) + "&data16=" + String(16) + "&data17=" + String(17) + "&data18=" + String(18) + "&data19=" + String(19) + "&data20=" + String(20); // Serial.print("Requesting URL: "); // Serial.println(url); // This will send the request to the server client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); unsigned long timeout = millis(); while (client.available() == 0) { if (millis() - timeout > 5000) { Serial.println(">>> Client Timeout !"); client.stop(); return; } } // Read all the lines of the reply from server and print them to Serial while (client.available()) { String line = client.readStringUntil('\r'); //Serial.print(line); } Serial.println(); Serial.println("closing connection"); delay(1000); } //==== void RS485_loop2() { ///========================= preTransmission(); digitalWrite(RX_PIN, HIGH); ///======= long currentMillis = millis(); if (currentMillis - lastMillis > 1000) { uint8_t result = modbus.readHoldingRegisters(0x02, 2); // 0x32 is ok for PM2230 from 10 will get 2 voltage if (getResultMsg(&modbus, result)) { Serial.println(); float res_dbl = modbus.getResponseBuffer(0) / 10; float value = res_dbl; String res = "data11 Soil Humidity : " + String(res_dbl) + " %\r\n"; Serial.println(res); sdata11 = String(res_dbl); res_dbl = value - modbus.getResponseBuffer(1) / 10 ; res = "data12 Soil Temp : " + String(res_dbl) + " C\r\n"; Serial.println(res); sdata12 = String(res_dbl); } lastMillis = currentMillis; } } void PumpTrial() { Serial.println("Starting pump for 1 minutes ..."); //MainPumpRun(); //delay(1000); } void ResetSystem() { digitalRead(3); ResetPinValue = String(digitalRead(3)); if (ResetPinValue == "1") { PumpTrial(); } } void MainPumpRun() { //Relay_ON_OFF(RELAY8, ON); } void MainPumpStop() { //Relay_ON_OFF(RELAY8, OFF); } void RequestFlowLowStatus() { } //// read control ==== void read_master_status_FromServer() { Serial.print("Reading control command from Server ... connecting to "); //Serial.println(host); WiFiClient client; delay(1500); if (client.connect(host, 80)) { Serial.println("reconnecting..."); url = "/api/getRealyStatus/" + String(dID) + "/" + String(code) + "/" + "abZYrshRYR243askdSKSKSK5646dkfmTURDsand"; Serial.print("Requesting URL: "); //Serial.println(url); // comment to prevent hacker client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); delay(2000); String section = "header"; while (client.available()) { //Serial.println("Connection available "); String line = client.readStringUntil('\r'); //Serial.print(line); // we’ll parse the HTML body here if (section == "header") { // headers.. if (line == "\n") { // skips the empty space at the beginning section = "json"; } } else if (section == "json") { // print the good stuff section = "ignore"; String result = line.substring(1); // Parse JSON int size = result.length() + 1; char json[size]; result.toCharArray(json, size); StaticJsonDocument <2000> doc; //StaticJsonBuffer<2000> jsonBuffer; DeserializationError error = deserializeJson(doc, json); //JsonObject& json_parsed = jsonBuffer.parseObject(json); //if (!json_parsed.success()) // { // Serial.println("parseObject() failed"); // return; // } if (error) return; Serial.println("parseObject() OK ..."); //Serial.println(result); // show all json found //String led = json_parsed["led"][0]["status"]; String master_state = doc["result"]["masterStatus"]; String led1 = doc["result"]["relayStatus"]["data6_H"]; String led2 = doc["result"]["relayStatus"]["data6_L"]; String led3 = doc["result"]["relayStatus"]["data3_status"]; String FlowBypass = doc["result"]["relayStatus"]["data5_status"]; String RR1 = doc["result"]["relayStatus"]["data1_status"]; String RR2 = doc["result"]["relayStatus"]["data2_status"]; String RR3 = doc["result"]["relayStatus"]["data3_status"]; String RR4 = doc["result"]["relayStatus"]["data4_status"]; String RR5 = doc["result"]["relayStatus"]["data5_status"]; String RR6 = doc["result"]["relayStatus"]["data6_status"]; // Timer relay 6 in platform String RR7 = doc["result"]["relayStatus"]["data7_status"]; // Timer relay 7 in platform String RR8 = doc["result"]["relayStatus"]["data8_status"]; // Timer relay 8 in platform String RR9 = doc["result"]["relayStatus"]["data9_status"]; // Timer relay 9 in platform String RR10 = doc["result"]["relayStatus"]["data10_status"]; // Timer relay 10 in platform String R_OTA = doc["result"]["relayStatus"]["data10_status"]; // Timer relay 8 in platform R1 = RR1; R2 = RR2; R3 = RR3; R4 = RR4; R5 = RR5; R6 = RR6; R7 = RR7; R8 = RR8; R9 = RR9; R10 = RR10; RR_OTA = String(R_OTA); Serial.println("Relay : " + String(R1) + " " + String(R2) + " " + String(R3) + " " + String(R4) + " " + String(R5) + " " + String(R6) + " " + String(R7) + " " + String(R8) + " " + String(R9) + " " + String(R10)); // string led = json_parsed["table name""][array number]["value of field"] Serial.print("Relay 1 := "); Serial.println(led1); Serial.print("Master state = "); Serial.println(master_state); Serial.print("R8 for Relay : "); Serial.println(R8); Serial.print("RR_OTA1 : "); Serial.println(RR_OTA); Time1 = led1 ; Time2 = led2 ; /* if (R3 == "1") { Relay_ON_OFF(RELAY3, ON); } else { Relay_ON_OFF(RELAY3, OFF); } */ if (master_state == "0") { MainPumpStop(); MainPump = "Stop"; } else { // this loop master_state == "1 if (R7 == "1") { MainPumpRun(); MainPump = "Run" ; //delay(5000); /// check flow sensor //RequestFlowLowStatus(); if (FlowBypass == "1") { MainPumpRun(); Serial.println("Water Pump in By-pass Mode .. please take care ..."); FlowBypass = "By-Pass"; delay(1000); flowsensor = "--"; } else { if (FlowLowStatus == "1") { MainPumpRun(); flowsensor = "OK"; } else { MainPumpStop(); Serial.println("Flow Low pump will stop "); flowsensor = "NOK"; } FlowBypass = "Protecะed"; } } else { //Serial.println("Flow low stop pump check and reset the system ... "); flowsensor = "NOK"; MainPumpStop(); } } /* if (led1 = "0") { digitalWrite(13,LOW); digitalWrite(15,LOW); } else { digitalWrite(13,HIGH); digitalWrite(15,HIGH); } */ Serial.print("Pump Start : "); Serial.println(led1); Serial.print("Pump Stop : "); Serial.println(led2); Serial.print("Led3 : "); Serial.println(led3); Serial.print("Master Status : "); Serial.println(master_state); Serial.print("Timer Relay R5 : "); Serial.println(R5); Serial.print("By-Pass Status : "); Serial.println(FlowBypass); Serial.println("Relay : " + String(R1) + " " + String(R2) + " " + String(R3) + " " + String(R4) + " " + String(R5) + " " + String(R6) + " " + String(R7) + " " + String(R8) + " " + String(R9) + " " + String(R10)); RR_OTA = String(R_OTA); Serial.print("RR_OTA2 : "); Serial.println(RR_OTA); // delay(1000); //LCD_Pump_Status(); } // if found json } // end while client available } // end if host connected else { // if you couldn't make a connection: ///Serial.println("connection failed read server 1"); } } void LCD_display() { } void PumpARun() // run Pump A 10 min { if (EC <= 1000) { //digitalWrite(RELAY8,HIGH); //Relay_ON_OFF(RELAY7, ON); Serial.println("Pump A Run"); } else { //digitalWrite(RELAY8,LOW); //Relay_ON_OFF(RELAY7, OFF); Serial.println("Pump A Stop"); } } void PumpBRun() // open water valve 12 Vdc { //digitalWrite(Relay2,HIGH); //Relay_ON_OFF(RELAY8, ON); Serial.println("Pump B Run"); } /************************************************************** Function Name : loop Description : Input : Return : **************************************************************/ void SMT_loop() { service_rtc(); //service_sensor(); // only AM2315 } void service_rtc() { String str1 = ""; ds1307_display_Time(); str1 = ""; if (global_hour < 10) { str1 = "0"; } str1 += String(global_hour) + " : "; if (global_minute < 10) { str1 += "0"; } str1 += String(global_minute) + " : "; if (global_second < 10) { str1 += "0"; } str1 += String(global_second); str1 = ""; str1 = "Temp1 : "; str1 += String(data3) + " .C"; // temp str1 = ""; str1 = "Hum1 : "; str1 += String(data4) + " %"; // humidity str1 = ""; str1 = "Temp2 : "; str1 += String(data5) + " .C"; // temp str1 = ""; str1 = "Hum2 : "; str1 += String(data6) + " %"; // humidity str1 = ""; str1 = "Volt : "; str1 += String(data7) + " V"; // volt str1 = ""; str1 = "Amp : "; str1 += String(data8) + " A"; // current } /************************************************************** Function Name : service_sensor Description : Input : Return : **************************************************************/ void service_sensor() { count_read++; if (!AM2315_ReadData()) { Serial.println("Failed to read data from AM2315"); } Serial.print(" >> Count-Read : "); Serial.print(count_read); Serial.print(" >> Temp *C: "); Serial.print(temp); Serial.print(" >> Hum %: "); Serial.println(humidity); data1 = String(temp); data2 = String(humidity); } /************************************************************** Function Name : service_led Description : Input : Return : **************************************************************/ void service_led() { digitalWrite(ESP32_LED, !digitalRead(ESP32_LED)); } /************************************************************** Function Name : AM2315_ReadData Description : Input : Return : **************************************************************/ uint8_t AM2315_ReadData() { uint8_t reply[10]; // Wake up the sensor Wire.beginTransmission(AM2315_I2CADDR); delay(10); Wire.endTransmission(); delay(5); // OK lets ready! Wire.beginTransmission(AM2315_I2CADDR); Wire.write(AM2315_READREG); Wire.write(0x00); // start at address 0x0 Wire.write(4); // request 4 bytes data Wire.endTransmission(); delay(10); // add delay between request and actual read! Wire.requestFrom(AM2315_I2CADDR, 8); for (uint8_t i = 0; i < 8; i++) { reply[i] = Wire.read(); } if (reply[0] != AM2315_READREG) return false; if (reply[1] != 4) return false; // bytes req'd humidity = reply[2]; humidity *= 256; humidity += reply[3]; humidity /= 10; // Serial.print("H"); Serial.println(humidity); temp = reply[4] & 0x7F; temp *= 256; temp += reply[5]; temp /= 10; // Serial.print("T"); Serial.println(temp); // change sign if (reply[4] >> 7) temp = -temp; return true; } ////================ ///================= ////================ void ESP32_Board_setup() { delay(100); Serial.begin(115200); pinMode(PIN_LED, OUTPUT); digitalWrite(PIN_LED, LOW); test_relay(); delay(250); test_relay(); delay(250); Wire.begin(SDA0, SCL0, 100000); // 100000 I2C_Address_Scand(); delay(1000); LoRa.setPins(RFM95_CS, RFM95_RST, RFM95_IRQ); // set CS, reset, IRQ pin if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz Serial.println("LoRa init failed. Check your connections."); while (true); // if failed, do nothing } delay(100); veri = LoRa.readRegister(0x42); // Semtech ID relating the silicon revision Serial.println(""); Serial.print(">> Registers RFM95 VERSION = "); Serial.println(veri); Serial.println(""); Serial.println(">> Dump - Registers RFM95 "); LoRa.dumpRegisters(Serial); delay(500); m_bitShift = 0; m_gain = GAIN_TWOTHIRDS; // m_dataRate = RATE_ADS1115_128SPS; //RATE_ADS1115_8SPS; //RATE_ADS1115_128SPS; delay(100); Interval[0] = 1000; // ADS1115 Interval[1] = 1000; // RTC Interval[2] = 250; // LED } ////========= void ESP32_BoardTest_loop() { //test_rtc(); //test_ads1115(); delay(2); if (millis() - Interval_Time_Old[0] >= Interval[0])//ADC ADS1115 { Interval_Time_Old[0] = millis(); test_ads1115(); } if (millis() - Interval_Time_Old[1] >= Interval[1])//RTC { Interval_Time_Old[1] = millis(); test_rtc(); } if (millis() - Interval_Time_Old[2] >= Interval[2])//LED { Interval_Time_Old[2] = millis(); if (LED_State) { LED_State = 0; digitalWrite(PIN_LED, LOW); } else { LED_State = 1; digitalWrite(PIN_LED, HIGH); } } } //############################################################# //################### ADC ADS1115 ########################### //############################################################# /******************************************************************** Function Name : test_ads1115 Description : ********************************************************************/ void test_ads1115() { float volts[4]; volts[0] = 0.00; volts[1] = 0.00; volts[2] = 0.00; volts[3] = 0.00; volts[0] = read_voltage_adc(0);//0-3 volts[1] = read_voltage_adc(1);//0-3 volts[2] = read_voltage_adc(2);//0-3 volts[3] = read_voltage_adc(3);//0-3 Serial.print(" >> ADC CH0 = "); Serial.print(volts[0], 3); Serial.println(" V "); Serial.print(" >> ADC CH1 = "); Serial.print(volts[1], 3); Serial.println(" V "); Serial.print(" >> ADC CH2 = "); Serial.print(volts[2], 3); Serial.println(" V "); Serial.print(" >> ADC CH3 = "); Serial.print(volts[3], 3); Serial.println(" V "); Serial.println(""); //delay(100); v0 = volts[0]; v1 = volts[1]; v2 = volts[2]; v3 = volts[3]; } /******************************************************************** Function Name : test_rtc Description : ********************************************************************/ void test_rtc() { Serial.println("========================================================"); Serial.print(" CLOCK : "); ds1307_display_Time(); Serial.println("========================================================"); //delay(850); } /******************************************************************** Function Name : read_voltage_adc Description : ********************************************************************/ float read_voltage_adc(uint8_t ch) { float f = 0.0; int16_t adc; adc = ReadADC_SingleEnded(ch); f = computeVolts(adc); return (f - 0.007);//adj offset } /******************************************************************** Function Name : ReadADC_SingleEnded Description : ********************************************************************/ int16_t ReadADC_SingleEnded(uint8_t channel) { if (channel > 3) { return 0; } // Start with default values uint16_t config = ADS1X15_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val) ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val) ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) ADS1X15_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) ADS1X15_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default) // Set PGA/voltage range config |= m_gain; // Set data rate config |= m_dataRate; // Set single-ended input channel switch (channel) { case (0): config |= ADS1X15_REG_CONFIG_MUX_SINGLE_0; break; case (1): config |= ADS1X15_REG_CONFIG_MUX_SINGLE_1; break; case (2): config |= ADS1X15_REG_CONFIG_MUX_SINGLE_2; break; case (3): config |= ADS1X15_REG_CONFIG_MUX_SINGLE_3; break; } // Set 'start single-conversion' bit config |= ADS1X15_REG_CONFIG_OS_SINGLE; // Write config register to the ADC ADS1115_Write_Reg(ADS1X15_REG_POINTER_CONFIG, config); // Wait for the conversion to complete while (!conversionComplete()) ; // Read the conversion results return getLastConversionResults(); } /******************************************************************** Function Name : computeVolts Description : ********************************************************************/ float computeVolts(int16_t counts) { // see data sheet Table 3 float fsRange; switch (m_gain) { case GAIN_TWOTHIRDS: fsRange = 6.144f; break; case GAIN_ONE: fsRange = 4.096f; break; case GAIN_TWO: fsRange = 2.048f; break; case GAIN_FOUR: fsRange = 1.024f; break; case GAIN_EIGHT: fsRange = 0.512f; break; case GAIN_SIXTEEN: fsRange = 0.256f; break; default: fsRange = 0.0f; } return counts * (fsRange / (32768 >> m_bitShift)); } /******************************************************************** Function Name : getLastConversionResults Description : ********************************************************************/ int16_t getLastConversionResults() { // Read the conversion results uint16_t res = ADS1115_Read_Reg(ADS1X15_REG_POINTER_CONVERT) >> m_bitShift; if (m_bitShift == 0) { return (int16_t)res; } else { // Shift 12-bit results right 4 bits for the ADS1015, // making sure we keep the sign bit intact if (res > 0x07FF) { // negative number - extend the sign to 16th bit res |= 0xF000; } return (int16_t)res; } } /******************************************************************** Function Name : conversionComplete Description : ********************************************************************/ uint8_t conversionComplete() { return (ADS1115_Read_Reg(ADS1X15_REG_POINTER_CONFIG) & 0x8000) != 0; } /************************************************************** Function Name : ADS1115_Write_Reg Description : Input : Return : **************************************************************/ void ADS1115_Write_Reg(uint8_t reg, uint16_t value) { uint8_t temp[4]; temp[0] = reg; temp[1] = value >> 8; temp[2] = value & 0xFF; Wire.beginTransmission(ADS1115_I2C_ADDRESS); Wire.write(temp[0]); Wire.write(temp[1]); Wire.write(temp[2]); Wire.endTransmission(); } /************************************************************** Function Name : ADS1115_Read_Reg Description : Input : Return : **************************************************************/ uint16_t ADS1115_Read_Reg(uint8_t reg) { uint8_t temp[4]; temp[0] = reg; Wire.beginTransmission(ADS1115_I2C_ADDRESS); Wire.write(temp[0]); Wire.endTransmission(); Wire.requestFrom(ADS1115_I2C_ADDRESS, 2); delayMicroseconds(10); temp[0] = Wire.read(); temp[1] = Wire.read(); Wire.endTransmission(); return ((temp[0] << 8) | temp[1]); } //############################################################# //###################### DS1307 ############################ //############################################################# /******************************************************************** Function Name : decToBcd Description : ********************************************************************/ byte decToBcd(byte val) { return ( (val / 10 * 16) + (val % 10) ); } /******************************************************************** Function Name : bcdToDec Description : ********************************************************************/ byte bcdToDec(byte val) { return ( (val / 16 * 10) + (val % 16) ); } /******************************************************************** Function Name : set_time_ds1307 Description : ********************************************************************/ void set_time_ds1307( byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) { // sets time and date data to DS1307 Wire.beginTransmission(ADDRESS_DS1307); Wire.write(0); // set next input to start at the seconds register Wire.write(decToBcd(second)); // set seconds Wire.write(decToBcd(minute)); // set minutes Wire.write(decToBcd(hour)); // set hours Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday) Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31) Wire.write(decToBcd(month)); // set month Wire.write(decToBcd(year)); // set year (0 to 99) Wire.endTransmission(); } /******************************************************************** Function Name : read_time_ds1307 Description : ********************************************************************/ void read_time_ds1307( byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(ADDRESS_DS1307); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(ADDRESS_DS1307, 7); // request seven bytes of data from DS3231 starting from register 00h *second = bcdToDec(Wire.read() & 0x7f); *minute = bcdToDec(Wire.read()); *hour = bcdToDec(Wire.read() & 0x3f); *dayOfWeek = bcdToDec(Wire.read()); *dayOfMonth = bcdToDec(Wire.read()); *month = bcdToDec(Wire.read()); *year = bcdToDec(Wire.read()); } /************************************************************** Function Name : ds1307_display_Time Description : Input : Return : **************************************************************/ /******************************************************************** Function Name : ds1307_display_Time Description : ********************************************************************/ void ds1307_display_Time() { byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // retrieve data from DS1307 read_time_ds1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // send it to the serial monitor Serial.print(hour, DEC); // convert the byte variable to a decimal number when displayed Serial.print(":"); if (minute < 10) { Serial.print("0"); } Serial.print(minute, DEC); Serial.print(":"); if (second < 10) { Serial.print("0"); } Serial.print(second, DEC); Serial.print(" "); Serial.print(dayOfMonth, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/"); Serial.println(year, DEC); Serial.print(" Day of week: "); Serial.print(" : "); switch (dayOfWeek) { case 1: Serial.println("Sunday"); break; case 2: Serial.println("Monday"); break; case 3: Serial.println("Tuesday"); break; case 4: Serial.println("Wednesday"); break; case 5: Serial.println("Thursday"); break; case 6: Serial.println("Friday"); break; case 7: Serial.println("Saturday"); break; } } //############################################################# //#################### MCP23017 ############################## //############################################################# /************************************************************** Function Name : test_read_mcp23017 Description : Input : Return : **************************************************************/ /************************************************************** Function Name : test_off_relay Description : Input : Return : **************************************************************/ void test_off_relay() { } /************************************************************** Function Name : test_on_relay Description : Input : Return : **************************************************************/ void test_on_relay() { } /******************************************************************** Function Name : test_relay Description : ********************************************************************/ void test_relay() { uint16_t del = 250; pinMode(RELAY1, OUTPUT); pinMode(RELAY2, OUTPUT); pinMode(RELAY3, OUTPUT); pinMode(RELAY4, OUTPUT); digitalWrite(RELAY1, LOW); digitalWrite(RELAY2, LOW); digitalWrite(RELAY3, LOW); digitalWrite(RELAY4, LOW); digitalWrite(RELAY1, HIGH); delay(del); digitalWrite(RELAY2, HIGH); delay(del); digitalWrite(RELAY3, HIGH); delay(del); digitalWrite(RELAY4, HIGH); delay(del); digitalWrite(RELAY1, LOW); delay(del); digitalWrite(RELAY2, LOW); delay(del); digitalWrite(RELAY3, LOW); delay(del); digitalWrite(RELAY4, LOW); delay(del); } /************************************************************** Function Name : Relay_ON_OFF Description : Input : Return : **************************************************************/ /************************************************************** Function Name : INIT_MCP23017 Description : Input : Return : **************************************************************/ /************************************************************** Function Name : Read_GPIO_MCP23017 Description : Input : Return : **************************************************************/ /************************************************************** Function Name : Write_MCP23017 Description : Input : Return : **************************************************************/ /************************************************************** Function Name : Show_1_OLED Description : Input : Return : **************************************************************/ /************************************************************** Function Name : Show_2_OLED Description : Input : Return : **************************************************************/ /************************************************************** Function Name : drawLines Description : Input : Return : // Adapted from Adafruit_SSD1306 **************************************************************/ /************************************************************** Function Name : drawRect Description : Input : Return : // Adapted from Adafruit_SSD1306 **************************************************************/ /************************************************************** Function Name : fillRect Description : Input : Return : // Adapted from Adafruit_SSD1306 **************************************************************/ /************************************************************** Function Name : drawCircle Description : Input : Return : // Adapted from Adafruit_SSD1306 **************************************************************/ /************************************************************** Function Name : printBuffer Description : Input : Return : **************************************************************/ void printBuffer(void) { // Initialize the log buffer // allocate memory to store 8 lines of text and 30 chars per line. // Some test data const char* test[] = { "Hello", "World" , "----", "Show off", "how", "the log buffer", "is", "working.", "Even", "scrolling is", "working" }; for (uint8_t i = 0; i < 11; i++) { delay(500); } } /************************************************************** Function Name : I2C_Address_Scan Description : Input : Return : **************************************************************/ void I2C_Address_Scand(void) { uint8_t count, i; Serial.println(); Serial.println(); Serial.println("------------------------------------------------"); count = 0; Serial.println ("i2c scanner. scanning ..."); Wire.begin(); for (i = 8; i < 120; i++) { Wire.beginTransmission (i); if (Wire.endTransmission () == 0) { Serial.print ("found address: "); Serial.print (i, DEC); Serial.print (" (0x"); Serial.print (i, HEX); Serial.println (")"); count++; delay(10); } } Serial.println ("done."); Serial.print ("found "); Serial.print (count, DEC); Serial.println (" device(s)."); } //*************************************************************************************** //*************************************************************************************** //*************************************************************************************** //*********************************************************************** //*********************************************************************** void Relay_Actuator() { digitalWrite(RELAY1, HIGH); digitalWrite(RELAY2, HIGH); digitalWrite(RELAY3, HIGH); digitalWrite(RELAY4, HIGH); } void Energy() { // Print the custom address of the PZEM Serial.print("PZEM Custom Address:"); Serial.println(pzem.readAddress(), HEX); //Read the data from the sensor float voltage = pzem.voltage(); float current = pzem.current(); float power = pzem.power(); float energy = pzem.energy(); float frequency = pzem.frequency(); float pf = pzem.pf(); // Check if the data is valid if (isnan(voltage)) { Serial.println("Error reading voltage"); } else if (isnan(current)) { Serial.println("Error reading current"); } else if (isnan(power)) { Serial.println("Error reading power"); } else if (isnan(energy)) { Serial.println("Error reading energy"); } else if (isnan(frequency)) { Serial.println("Error reading frequency"); } else if (isnan(pf)) { Serial.println("Error reading power factor"); } else { // Print the values to the Serial console Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V"); Serial.print("Current: "); Serial.print(current); Serial.println("A"); Serial.print("Power: "); Serial.print(power); Serial.println("W"); Serial.print("Energy: "); Serial.print(energy, 3); Serial.println("kWh"); Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println("Hz"); Serial.print("PF: "); Serial.println(pf); } data7 = String(voltage); data8 = String(current); data9 = String(power); data10 = energy; data11 = frequency; data12 = pf; Serial.println(); } void test_convert() { int dec = 50; String hexa = "131"; //Conversion from binary to decimal Serial.print("A converted to decimal: "); Serial.println(convert.hexaToDecimal(hexa)); int deci = convert.hexaToDecimal(hexa); String bin = String(convert.decimalToBinary(deci)); Serial.print("A = "); Serial.println(bin); } /* void test_convert() { Serial.begin(9600); int dec = 50; //Conversion de decimal a binario Serial.print("50 converted to binary: "); Serial.println(convert.decimalToBinary(dec)); //Conversion de decimal a hexadecimal Serial.print("50 converted to hexadecimal: "); Serial.println(convert.decimalToHexa(dec)); //Conversion de decimal a octal Serial.print("50 converted to octal: "); Serial.println(convert.decimalToOctal(dec)); String hex = "292"; //Conversion from hexadecimal to decimal Serial.print("292 converted to decimal: "); Serial.println(convert.hexaToDecimal(hex)); String bin = "11001111"; //Conversion from binary to decimal Serial.print("11001111 converted to decimal: "); Serial.println(convert.binaryToDecimal(bin)); String oct = "515"; //Conversion from octal to decimal Serial.print("515 converted to decimal: "); Serial.println(convert.octalToDecimal(oct)); } */ void XYMD02_loop() { Read_DATA_SHT20_XYMD02(1);//Modbus ID //Read_Hardware_Parameter_SHT20_XYMD02(1);//Modbus ID data3 = dataa3; data4 = dataa4; jjdata3 = jdata3; jjdata4 = jdata4; delay(1000); Read_DATA_SHT20_XYMD02(3);//Modbus ID data5 = dataa5; data6 = dataa6; delay(1000); //Read_Hardware_Parameter_SHT20_XYMD02(2);//Modbus ID tempdiff = jjdata3 - jdata5; humdiff = jjdata4 - jdata6; Serial.println(" Temp diff = " + String(tempdiff)); Serial.println(" Humid diff = " + String(humdiff)); if (tempdiff < tempdiff_Max ) { Run_evap(); } else { Run_fan(); } } void Run_evap() { //Relay_ON_OFF(RELAY1, ON); //Relay_ON_OFF(RELAY2, ON); } void Run_fan() { //Relay_ON_OFF(RELAY1, ON); //Relay_ON_OFF(RELAY1, OFF); } /************************************************************** Function Name : Change_Slave_ID Description : Input : Return : **************************************************************/ void Change_Slave_ID(uint8_t Slave_ID, uint8_t NEW_Slave_ID) { uint8_t loop_poll; au16data[5] = NEW_Slave_ID; telegram[1].u8id = Slave_ID; // slave addrss telegram[1].u8fct = 6; // function code telegram[1].u16RegAdd = 257; // start address in slave telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read telegram[1].au16reg = au16data + 5; // pointer to a memory array in the Arduino master.query( telegram[1] ); // send query (only once) delay(5); loop_poll = 1; while (loop_poll) { master.poll(); // check incoming messages delay(2); if (master.getState() == COM_IDLE) { loop_poll = 0; if (master.getLastError() != 0)//ERROR { Serial.print(" ERROR Read >> "); Serial.println(master.getLastError()); } else { Serial.println("............ Write NEW Slave ID OK "); Serial.println("............ Please Restart Sensor "); } } } delay(20); } /************************************************************** Function Name : Read_DATA_SHT20_XYMD02 Description : Input : Return : **************************************************************/ void Read_DATA_SHT20_XYMD02(uint8_t Slave_ID)// { uint8_t loop_poll; telegram[2].u8id = Slave_ID; // slave address Read telegram[2].u8fct = 4; // function code (this one is registers read) telegram[2].u16RegAdd = 0; //257;//1 for MD02 ; // start address in slave // 0 for SHT20 telegram[2].u16CoilsNo = 2; // number of elements (coils or registers) to read telegram[2].au16reg = au16data; // pointer to a memory array in the Arduino master.query( telegram[2] ); // send query (only once) loop_poll = 1; delay(5); while (loop_poll) { master.poll(); // check incoming messages delay(2); if (master.getState() == COM_IDLE) { loop_poll = 0; if (master.getLastError() != 0)//ERROR { Serial.print(" ERROR Read >> "); Serial.println(master.getLastError()); } else { // Serial.println("************ READ *************");//debug // Serial.println(au16data[0], DEC);//debug // Serial.println(au16data[1], DEC);//debug temperature = float(au16data[0]) / 10; humidity = float(au16data[1]) / 10; jdata3 = temperature; jdata4 = humidity; jdata5 = temperature; jdata6 = humidity; dataa3 = String(temperature); dataa4 = String(humidity); dataa5 = String(temperature); dataa6 = String(humidity); Serial.println("---------------------------------------------------"); Serial.print(" Temperature(#" + String(Slave_ID) + ") = "); Serial.print(temperature); Serial.println(" *C"); Serial.print(" Humidity(#" + String(Slave_ID) + ") = "); Serial.print(humidity); Serial.println(" %"); //Serial.println("---------------------------------------------------"); } } } delay(20); } /************************************************************** Function Name : Read_Hardware_Parameter_SHT20_XYMD02 Description : Input : Return : **************************************************************/ void Read_Hardware_Parameter_SHT20_XYMD02(uint8_t Slave_ID) { uint8_t loop_poll; telegram[3].u8id = Slave_ID; // slave address Read telegram[3].u8fct = 3; // function code (this one is registers read) telegram[3].u16RegAdd = 257; // start address in slave telegram[3].u16CoilsNo = 2; // number of elements (coils or registers) to read telegram[3].au16reg = au16data; // pointer to a memory array in the Arduino master.query( telegram[3] ); // send query (only once) loop_poll = 1; delay(5); while (loop_poll) { master.poll(); // check incoming messages delay(2); if (master.getState() == COM_IDLE) { loop_poll = 0; if (master.getLastError() != 0)//ERROR { Serial.print(" ERROR Read >> "); Serial.println(master.getLastError()); } else { //Serial.println("************ READ *************");//debug //Serial.println(au16data[0], DEC);//debug //Serial.println(au16data[1], DEC);//debug //Serial.println("---------------------------------------------------"); Serial.print(" Modbus Slave ID = "); Serial.println(au16data[0], DEC); Serial.print(" Baud Rate = "); Serial.println(au16data[1], DEC); Serial.println("---------------------------------------------------"); } } } delay(20); } void Restart_loop() { Serial.println(cnt); // แสดงค่าตัวเลขแต่ละรอบ // เมื่อรันครบ 10 รอบ (10วินาที) ให้สั่ง reset if (cnt == 0) { Serial.println("Reset.."); ESP.restart(); // คำสั่งรีเซ็ต ESP } cnt--; // ลดค่าตัวแปร cnt ไปรอบละ 1 หน่วย delay(1000); // รอ 1 วินาที } void pH_setup(void) { //pinMode(LED,OUTPUT); //Serial.begin(115200); Serial.println("pH meter experiment!"); //Test the serial monitor } void pH_loop(void) { static unsigned long samplingTime = millis(); static unsigned long printTime = millis(); static float pH_voltage; v0 = read_voltage_adc(0);//0-3 //pHArray[pHArrayIndex++]=v0; //if(pHArrayIndex==ArrayLenth)pHArrayIndex=0; //pH_voltage = avergearray(pHArray, ArrayLenth); pHValue = 3.5 * v0 + Offset; //voltage+Offset; //samplingTime=millis(); Serial.print("Voltage:"); Serial.print(pH_voltage, 2); Serial.print(" pH value: "); Serial.print(pHValue, 2); data5 = String(pHValue); } double avergearray(int* arr, int number) { int i; int max, min; double avg; long amount = 0; if (number <= 0) { Serial.println("Error number for the array to avraging!/n"); return 0; } if (number < 5) { //less than 5, calculated directly statistics for (i = 0; i < number; i++) { amount += arr[i]; } avg = amount / number; return avg; } else { if (arr[0] < arr[1]) { min = arr[0]; max = arr[1]; } else { min = arr[1]; max = arr[0]; } for (i = 2; i < number; i++) { if (arr[i] < min) { amount += min; //arr<min min = arr[i]; } else { if (arr[i] > max) { amount += max; //arr>max max = arr[i]; } else { amount += arr[i]; //min<=arr<=max } }//if }//for avg = (double)amount / (number - 2); }//if return avg; } //**************************************************************************** //**************************************************************************** //**************************************************************************** //****************************************************************************
ส่วนที่ 1 Include & Define
sdasda
///////////////////////////////////////////// // DEFINE ///////////////////////////////////////////// #define VERSION "3.0" // เพื่อการตรวจเชค OTA ///////////////////////////////////////////// ///////////////////////////////////////////// extern "C" { #include "freertos/FreeRTOS.h" // มีปัญหากับ esp8266 #include "freertos/timers.h" } // CONFIG #include <ArduinoJson.h> #ifdef ESP32 #include <SPIFFS.h> #else #include <FS.h> #endif // เลือก ไลบรารีสำหรับ WIFI #ifdef ESP32 #include <WiFi.h> #include <WiFiMulti.h> #else #include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #define ARDUINO_EVENT_WIFI_STA_GOT_IP WIFI_EVENT_STAMODE_GOT_IP #define ARDUINO_EVENT_WIFI_STA_DISCONNECTED WIFI_EVENT_STAMODE_DISCONNECTED #endif // เตรียมการสำหรับ OTA ระหว่าง ESP32 กับ ESP8266 #ifdef ESP32 #include <Update.h> #else #include <ESP8266httpUpdate.h> #endif #include <SoftwareSerial.h> // https://github.com/PaulStoffregen/SoftwareSerial #include <Convert.h> #include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster #include <ModbusRtu.h> #include <HardwareSerial.h> #include <Arduino.h> //// สำหรับการเชื่อมต่อ SPI LoRa #include <SPI.h> // include libraries #include <Ticker.h> #include <LoRa.h> #include <Wire.h> //// #include "define.h" // สำหรับเรียกไฟล์ define.h ในโฟลเดอร์เดียวกัน #include <math.h> #include <ArduinoJson.h> #include <Arduino_JSON.h> //============== ///====== สำหรับการสื่อสาร RS485 ขั้วสีแดง #define RX_PIN 16 //Serial Receive pin 16 #define TX_PIN 17 //Serial Transmit pin 17 #define MAX485_RE_NEG 15 //LED #define RS485Transmit HIGH #define RS485Receive LOW #define LED 0 float temp, pH ; //========== XYMD02 = RS485 สำหรับอ่าน XYMD02 และ SHT20 HardwareSerial RTU_Serial(2); // 1 Modbus master(0, RTU_Serial, MAX485_RE_NEG); // this is master and RS-232 or USB-FTDI modbus_t telegram[4]; bool restart; uint16_t au16data[8]; float humidity; float temperature; uint8_t RTU_Slave_ID; uint8_t RTU_NEW_Slave_ID; uint8_t Slave_ID; //====== SoftwareSerial RS485Serial(RX_PIN, TX_PIN); //Creation of class object Convert convert; //====== สำหรับการวัดไฟฟ้าด้วย PZEM #include <PZEM004Tv30.h> #if !defined(PZEM_RX_PIN) && !defined(PZEM_TX_PIN) #define PZEM_RX_PIN 4 #define PZEM_TX_PIN 5 #endif #if !defined(PZEM_SERIAL) #define PZEM_SERIAL Serial1 #endif #if defined(ESP32) /************************* ESP32 initialization --------------------- The ESP32 HW Serial interface can be routed to any GPIO pin Here we initialize the PZEM on Serial2 with RX/TX pins 16 and 17 */ PZEM004Tv30 pzem(PZEM_SERIAL, PZEM_RX_PIN, PZEM_TX_PIN); #elif defined(ESP8266) /************************* ESP8266 initialization --------------------- Not all Arduino boards come with multiple HW Serial ports. Serial2 is for example available on the Arduino MEGA 2560 but not Arduino Uno! The ESP32 HW Serial interface can be routed to any GPIO pin Here we initialize the PZEM on Serial2 with default pins */ PZEM004Tv30 pzem(Serial1); #else /************************* Arduino initialization --------------------- Not all Arduino boards come with multiple HW Serial ports. Serial2 is for example available on the Arduino MEGA 2560 but not Arduino Uno! The ESP32 HW Serial interface can be routed to any GPIO pin Here we initialize the PZEM on Serial2 with default pins */ PZEM004Tv30 pzem(PZEM_SERIAL); #endif // #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // //========= //====== //=================== #include <Adafruit_Sensor.h> #include <DHT.h> // กรณีนี้ต้องใช้คู่กันกับ DHT_U.h #include <DHT_U.h> // See guide for details on sensor wiring and usage: // https://learn.adafruit.com/dht/overview uint32_t delayMS; //=========== /* # This sample code is used to test the pH meter V1.0. # Editor : YouYou # Ver : 1.0 # Product: analog pH meter # SKU : SEN0161 */ //#define SensorPin A0 //pH meter Analog output to Arduino Analog Input 0 #define Offset -2.00 //deviation compensate #define LED 13 #define samplingInterval 20 #define printInterval 800 #define ArrayLenth 20 // 40 times of collection int pHArray[ArrayLenth]; //Store the average value of the sensor feedback int pHArrayIndex = 0; // #define Slave_ID1 1 // see dip swith if connect to Transpower #define BAND 915E6 //you can set band here directly,e.g. 868E6,915E6,433E6 // instantiate ModbusMaster object ModbusMaster modbus; // OTA WiFiClient otaClient; //=== Ticker _service_rtc; Ticker _service_sensor; Ticker _service_led; //Ticker _service_test_1; //Ticker _service_test_2; //Ticker _service_test_3; TwoWire I2C0 = TwoWire(0);
ส่วนที่ 2 Variable
dfgdfg
adsGain_t m_gain; uint8_t m_bitShift; uint16_t m_dataRate; uint8_t Relay, gpio_in; uint16_t delayx, count_read; uint8_t i2c_address_adc; int16_t adc0, adc1, adc2, adc3; float volts0, volts1, volts2, volts3; uint8_t veri; uint8_t LED_State; uint32_t Interval_Time_Old[4]; uint16_t Interval[4]; uint32_t lastreading; char cstr[8]; byte global_second, global_minute, global_hour, global_dayOfWeek, global_dayOfMonth, global_month, global_year; //=== double res_dbl0; double res_dbl1; double res_dbl ; unsigned int counter = 0; String rssi = "RSSI --"; String packSize = "--"; String packet ; String RS485_Data[13]; //======สำหรับ WiFi ที่จะเชื่อมต่อ หากมาหลายตัวในบริเวณใกล้กัน const char* ssid = "Asenal2021_2G"; const char* password = "kb75699212"; const char* ssid1 = "Asenal2021_2G"; const char* password1 = "kb75699212"; const char* ssid2 = "Asenal2021_2G"; const char* password2 = "kb75699212"; //===== Server config , ID, Code //const char* host = "http://192.168.1.34"; const char* host = "myiotcity.com"; char* code = "123rr"; char* dID = "204"; //=== PM 2.5 float dustDensity = 35; String response = "0"; String response_c = "0"; String a ; //=== กด เพื่อ OTA int npress ; //== ตั้งค่ารอบเพื่อการ รีสตาร์ท int cnt = 7200; // every 24 hrs cycle = 12 second // //== ตัวแปรใช้งานทั่วไป float temp_0 = 0; float humid_0 = 0; float vHumidity = 0; float vTemperature = 0; float vPower = 0; float vVolt = 0; float iamp = 0; float vEnergy = 0; float v0, v1, v2, v3; float voltage; float current; float power; float energy; float frequency; float pHValue; float pf; String data0 ; // for data request ; String data1 ; String datasend ; String datasend1 ; String datasend2 ; String data2 ; String data3 , dataa3 ; String data4 , dataa4 ; String data5 , dataa5 ; String data6 , dataa6 ; String data7 ; String data8 ; String data9 ; String JSONSerial = ""; float jdata1, jdata2, jdata3, jdata4, jjdata3, jjdata4, jdata5, jdata6 ; float tempdiff = 0 ; float tempdiff_Max = 5; float humdiff = 0 ; /// === String sdata1 ; String sdata2 ; // standard String sdata3 ; String sdata4 ; String sdata5 ; String sdata6 ; String sdata7 ; String sdata8 ; String sdata11; String sdata12 ; String master_state ; String FlowLowStatus ; String ResetPinValue ; String MainPump ; String PumpA ; String PumpB ; String flowsensor ; String led1 = "00:00"; String led2 = "00:00"; String led3 = "1"; String Time1 ; String Time2 ; String R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 ; String RR1, RR2, RR3, RR4, RR5, RR6, RR7, RR8, RR9, RR10, R_OTA, RR_OTA ; String CommandR3Slave = "Off" ; // to control R3 on Nano String CommandR4Slave ; // to control R4 on board float data10 = 0; float data11 = 0; float data12 = 0; float data13 = 0; float data14 = 0; float data15 = 0; float data16 = 0; float data17 = 0; float data18 = 0; float data19 = 0; float data20 = 0; float EC ; float temperatureC = 0; float temperatureF = 0; float sensorValue = 0; float rainmm = 0; //int counter = 1; int i ; int sentcount = 0; String url ; int Relay1 = 12 ; int Relay2 = 2 ; int LoRa_counter = 0; // String iddevice = dID; String cccode = code; String ccode = code; long lastMillis = 100; /// === String sentpacket ; String str; char charBuf[100];