Heltec-MiniLoRa with PZEM-004T-V3
เดิมทีออกแบบ MiniLoRa มาเน้นใช้านเป็นเครื่องวัด RS485 จากระบบฟาร์ม แต่ก็มีคำถามเรื่องการใช้วัดไฟฟ้า ด้วย PZEM-004T V3 เลยต้องมาทบทวนกันหน่อยว่าจะต้องใช้ขาไหนบน บอร์ดนี้
สรุปจะให้ใช้ PZEM-oo4T RX, TX ที่ขา D9, D10 ของ Nano ซึ่ง บนบอร์ดนี้ Nano จะใช้ D5, D6 ต่อ Serial กับ Heltec ทางขา 17,13
#include <EEPROM.h> ///// Add on Aug 11 2020 #include <PZEM004Tv30.h> /* Use software serial for the PZEM * Pin 11 Rx (Connects to the Tx pin on the PZEM) * Pin 12 Tx (Connects to the Rx pin on the PZEM) */ #include <SoftwareSerial.h> SoftwareSerial chat(5, 6); // RX, TX to Heltec LoRa (5 , 6 ) //////// #include <SHT1x.h> #define dataPin A0 //A4 #define clockPin A1 //A5 SHT1x sht1x(dataPin, clockPin); /////// int relay1 = 8; #define FlowSwitch 11 int analogPin = A1; int val = 0; int pzemtime= 2000; //// PZEM004Tv30 pzem(10, 9); // 12,10 //// #include <math.h> uint32_t delayMS; //////// //// ph asset // const int analogPhPin = A0; //PH module pin P0 connected to analog pin A0 long phTot, temTot; float phAvg, temAvg; float pHValue; int x; float C = 25.85; // 25.85 Constant of straight line (Y = mx + C) float m = -6.8; // -6.8 Slope of straight line (Y = mx + C) /// int i; int sensorValue; float rainmm ; float dustDensity = 35; String response ="0"; String response_c = "0"; String a ; float temp_0 = 0; float tempF_0 = 0; float humid_0 = 0; float vHumidity = 0; float vTemperature = 0; String data1 ; String data2 ; // standard float data3 = 0; float data4 = 0; float data5 = 0; float data6 = 0; float data7 = 0; float data8 = 0; float data9 = 0; String sdata1 ; String sdata2 ; String sdata3 ; String sdata4 ; String sdata5 ; String sdata6 ; String sdata7 ; String sdata8 ; String FlowLowStatus ; float data18 = 0; float data19 = 0; float data20 = 0; float temperatureC = 0; float temperatureF = 0; int counter = 1; int sentcount = 0; float vPower=0; float vVolt=0; float iamp=0; float vEnergy=0; ////////////////////////////// void setup() { Serial.begin(9600); chat.begin(57600); pinMode(relay1, OUTPUT); // sets the pin as output pinMode(FlowSwitch,INPUT); // set as input flow switch } void loop() { sht1_loop(); FlowSwitchLow(); pH_loop(); chat.begin(57600); if (chat.readString()){ // chat.print(1); if(chat.readString()== "Input1"){ chat.print(String(data3)); } if(chat.readString()== "Input2"){ chat.print(String(data4)); } if(chat.readString()== "Input3"){ chat.print(String(data5)); } if(chat.readString()== "Input4"){ chat.print(String(data6)); } if(chat.readString()== "Input5"){ chat.print(String(data7)); } Serial.print("Sent done data no : "); Serial.println(i); } i++; pzemV3Loop(); } void sht1_loop() { float temp_c; // float temp_f; // float humidity; // temp_c = sht1x.readTemperatureC(); temp_f = sht1x.readTemperatureF(); humidity = sht1x.readHumidity(); data3 = temp_c; data4 = humidity; Serial.print("Temperature: "); Serial.print(temp_c, DEC); Serial.print("C / "); Serial.print(temp_f, DEC); Serial.print("F. Humidity: "); Serial.print(humidity); Serial.println("%"); if (temp_c < 27 ) { // //digitalWrite(relay3, HIGH); // } else { //digitalWrite(relay3, LOW); // } if (humidity < 55 ) { // //digitalWrite(relay4, HIGH); // } else { //digitalWrite(relay4, LOW); // } delay(100); } void pH_setup() { } void pH_loop() { phTot = 0; temTot = 0; phAvg = 0; temAvg = 0; //taking 10 sample and adding with 10 milli second delay for(x=0; x<10 ; x++) { phTot += analogRead(A0); temTot += analogRead(A1); delay(10); } float temAvg = temTot/10; float phAvg = temTot/10; // float temVoltage = temAvg * (5000.0 / 1023.0); //convert sensor reading into milli volt float phVoltage = phAvg * (5.0 / 1023.0); //convert sensor reading into milli volt // float Etemp = temVoltage*0.1; //convert milli volt to temperature degree Celsius pHValue = phVoltage*m+C; Serial.print("phVoltage = "); Serial.print(phVoltage); Serial.print(" "); Serial.print("pH="); Serial.println(pHValue); data5 = pHValue; if (pHValue < 7.5 ) { // //digitalWrite(relay1, HIGH); // } else { //digitalWrite(relay1, LOW); // } if (pHValue > 9.0 ) { // //digitalWrite(relay2, HIGH); // } else { //digitalWrite(relay2, LOW); // } delay(1000); } void FlowSwitchLow() { FlowLowStatus = String(digitalRead(FlowSwitch)); Serial.println("Flow Sensor :"+ FlowLowStatus); } void pzemV3Loop() { float vVolt = pzem.voltage(); if( !isnan(vVolt) ){ Serial.print("Voltage: "); Serial.print(vVolt); Serial.println("V"); } else { Serial.println("Error reading voltage"); } float iamp = pzem.current(); if( !isnan(iamp) ){ Serial.print("Current: "); Serial.print(iamp); Serial.println("A"); } else { Serial.println("Error reading current"); } float vEnergy = pzem.power(); if( !isnan(vEnergy) ){ Serial.print("Power: "); Serial.print(vEnergy); Serial.println("W"); } else { Serial.println("Error reading power"); } float energy = pzem.energy(); if( !isnan(energy) ){ Serial.print("Energy: "); Serial.print(energy,3); Serial.println("kWh"); } else { Serial.println("Error reading energy"); } float frequency = pzem.frequency(); if( !isnan(frequency) ){ Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println("Hz"); } else { Serial.println("Error reading frequency"); } float pf = pzem.pf(); if( !isnan(pf) ){ Serial.print("PF: "); Serial.println(pf); } else { Serial.println("Error reading power factor"); } data6 = vVolt; data7 = iamp; data8 = vEnergy; data9 = pf; Serial.println(); delay(2000); } void PumpARun() { digitalWrite(relay1,HIGH); Serial.println("Pump A Run "); } void RequestDataSet() { Serial.println("Please wait while Request dataset from Wemos .."); String b = ""; while (b == "") { chat.print("TempH"); // b = chat.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer for Temp High : = ");Serial.println(b); //data0 = String(b); delay(1000); b=""; while (b == "") { chat.print("HumidH"); // b = chat.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer for Humid High : = ");Serial.println(b); //data0 = String(b); delay(1000); b=""; a=""; }
และ Heltec Code ตามนี้เลยครับ
/* Code file name : MiniLoRa-Nano-Node-Dev-184...Trial Seria This is a simple example show the Heltec.LoRa sended data in OLED. The onboard OLED display is SSD1306 driver and I2C interface. In order to make the OLED correctly operation, you should output a high-low-high(1-0-1) signal by soft- ware to OLED's reset pin, the low-level signal at least 5ms. OLED pins to ESP32 GPIOs via this connecthin: OLED_SDA -- GPIO4 OLED_SCL -- GPIO15 OLED_RST -- GPIO16 by Aaron.Lee from HelTec AutoMation, ChengDu, China 成都惠利特自动化科技有限公司 www.heltec.cn this project also realess in GitHub: https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series */ #include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster /*! We're using a MAX485-compatible RS485 Transceiver. Rx/Tx is hooked up to the hardware serial port at 'Serial'. The Data Enable (DE) and Receiver Enable (RE) pins are hooked up as follows: */ #include <Arduino.h> #include <Wire.h> #include <math.h> #include <ArduinoJson.h> #define RXX 17 #define TXX 13 #include <Adafruit_Sensor.h> #include <DHT.h> // กรณีนี้ต้องใช้คู่กันกับ DHT_U.h #include <DHT_U.h> #define DHTPIN 2 // Pin which is connected to the DHT sensor. //#define DHTTYPE DHT22 // DHT 22 (AM2302) #define DHTTYPE DHT21 // DHT 21 (AM2301) // See guide for details on sensor wiring and usage: // https://learn.adafruit.com/dht/overview DHT_Unified dht(DHTPIN, DHTTYPE); uint32_t delayMS; #define MAX485_RE_NEG 25 //D4 RS485 has a enable/disable pin to transmit or receive data. Arduino Digital Pin 2 = Rx/Tx 'Enable'; High to Transmit, Low to Receive #define Slave_ID1 1 // see dip swith if connect to Transpower #define RX_PIN 22 //RX2 22 do not change #define TX_PIN 23 //TX2 23 do not change #include "heltec.h" #include "images.h" #define BAND 915E6 //you can set band here directly,e.g. 868E6,915E6,433E6 // instantiate ModbusMaster object ModbusMaster modbus; double res_dbl0; double res_dbl1; double res_dbl ; unsigned int counter = 0; String rssi = "RSSI --"; String packSize = "--"; String packet ; String datasend ; String datasend1 ; String datasend2 ; String data2 ; String data3 ; String data4 ; String data5 ; String data6 ; String data7 ; String data8 ; String data9 ; String a ; float temp_0 = 0; float humid_0 = 0; float vHumidity = 0; float vTemperature = 0; String data1="197"; String cccode = "67ujsevebdh5"; long lastMillis = 100; // Convent 32bit to float //------------------------------------------------ float HexTofloat(uint32_t x) { return (*(float*)&x); } uint32_t FloatTohex(float x) { return (*(uint32_t*)&x); } //------------------------------------------------ //=== void preTransmission() { digitalWrite(MAX485_RE_NEG, HIGH); //Switch to transmit data } void postTransmission() { digitalWrite(MAX485_RE_NEG, LOW); //Switch to receive data } //==== void logo() { Heltec.display->clear(); Heltec.display->drawXbm(0,5,logo_width,logo_height,logo_bits); Heltec.display->display(); } 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); Serial1.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // serial can be no1 , no 2 8N1 modbus.begin(Slave_ID1, Serial1); // Callbacks allow us to configure the RS485 transceiver correctly modbus.preTransmission(preTransmission); modbus.postTransmission(postTransmission); } void setup() { //WIFI Kit series V1 not support Vext control Heltec.begin(true /*DisplayEnable Enable*/, true /*Heltec.Heltec.Heltec.LoRa Disable*/, true /*Serial Enable*/, true /*PABOOST Enable*/, BAND /*long BAND*/); Heltec.display->init(); Heltec.display->flipScreenVertically(); Heltec.display->setFont(ArialMT_Plain_10); logo(); delay(1500); Heltec.display->clear(); Heltec.display->drawString(0, 0, "Heltec.LoRa Initial success!"); Heltec.display->display(); delay(1000); RS485_setup(); Serial2.begin(57600, SERIAL_8N1,17,13); // for SMT Smart LoRa Board use 13,17 } void loop() { /* RS485_loop(); datasend2 = String(res_dbl0)+","+String(res_dbl1)+","+String(45.00)+","+String(25.75)+","+String(100.05); datasend1 = String(cccode)+","+String(177)+","+String(res_dbl0)+","+String(res_dbl1); datasend = datasend1+","+datasend2; */ Heltec.display->clear(); Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); Heltec.display->setFont(ArialMT_Plain_10); Heltec.display->drawString(0, 0, "Samong IOT Data packet: "); Heltec.display->drawString(0, 10, String(counter)); Heltec.display->drawString(0,20, String(datasend1)); Heltec.display->drawString(0,30, String(datasend2)); Heltec.display->display(); counter=counter+1; // send packet LoRa.beginPacket(); /* * LoRa.setTxPower(txPower,RFOUT_pin); * txPower -- 0 ~ 20 * RFOUT_pin could be RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO * - RF_PACONFIG_PASELECT_PABOOST -- LoRa single output via PABOOST, maximum output 20dBm * - RF_PACONFIG_PASELECT_RFO -- LoRa single output via RFO_HF / RFO_LF, maximum output 14dBm */ /* LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST); LoRa.print(datasend); //LoRa.print(counter); LoRa.endPacket(); */ RS485_loop1(); delay(2000); /* data2 = "22.22"; data3 = "33.33"; data4 = "44.44"; data5 = "55.55"; data6 = "66.66"; data7 = "77.77"; */ datasend2 = String(data4)+","+String(data5)+","+String(data6)+","+String(data7); datasend1 = String(cccode)+","+String(data1)+","+String(data2)+","+String(data3); datasend = datasend1+","+datasend2; Serial.println(datasend); LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST); LoRa.print(datasend); //LoRa.print(counter); LoRa.endPacket(); LoRa.print(counter); delay(2000); // wait for a second serial_loop(); // remove comment if to connect serial } void RS485_loop1() { long currentMillis = millis(); if (currentMillis - lastMillis > 1000) { uint8_t result = modbus.readHoldingRegisters(2,5); // from 10 will get 2 voltage if (getResultMsg(&modbus, result)) { Serial.println(); res_dbl = modbus.getResponseBuffer(0); String res = "Voltage C : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data2 = String(res_dbl); res_dbl = modbus.getResponseBuffer(1); res = "Voltage B : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data3 = String(res_dbl); res_dbl = modbus.getResponseBuffer(2); res = "Value 23 : " + String(res_dbl) + " \r\n"; Serial.println(res); data4 = String(res_dbl); res_dbl = modbus.getResponseBuffer(3); res = "Value 24 : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data5 = String(res_dbl); res_dbl = modbus.getResponseBuffer(4); res = "Value 25 : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data6 = String(res_dbl); res_dbl = modbus.getResponseBuffer(5); uint32_t value = res_dbl; value = value << 16; value = value + res_dbl; float i = HexTofloat(value); res = "Value 26 : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); data7 = String(res_dbl); res_dbl = modbus.getResponseBuffer(6); res = "Power : " + String(res_dbl) + " watt\r\n"; Serial.println(res); data8 = String(res_dbl); res_dbl = modbus.getResponseBuffer(7); res = "Value 28 : " + String(res_dbl) + " Vac\r\n"; Serial.println(res); //delay(2000); data9 = String(res_dbl); Serial.print(" Hex to float : ");Serial.println(i); } 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; } void serial_loop() { Serial.println("Please wait Serial.."); while (a == "") { Serial2.print("Input1"); // a = Serial2.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer1 ");Serial.println(a); data3 = String(a); delay(1000); a=""; while (a == "") { Serial2.print("Input2"); // a = Serial2.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer2 ");Serial.println(a); data4=String(a); a=""; while (a == "") { Serial2.print("Input3"); // a = Serial2.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer3 ");Serial.println(a); data5=String(a); a=""; while (a == "") { Serial2.print("Input4"); // a = Serial2.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer4 ");Serial.println(a); data6 = String(a); a=""; while (a == "") { Serial2.print("Input5"); // a = Serial2.readString(); // delay(100); Serial.print("."); } Serial.print(" Answer5 ");Serial.println(a); data7 = String(a); } void Server_loop() { } void ReadServerControl() { }