Review Smart Board SMT-006-V1.0

วันนี้มาทำการทดสอบบอร์ด Smart Board SMT-006-V1.0 กันครับ
ซึ่งบอร์ดนี้ประกอบด้วยอุปกรณ์ตามรูป ดูกันไปก่อนนะครับ  จะทะยอยมาลงชื่ออุปกรณ์โดยละเอียดกันอีกครั้ง

การทดสอบจะต้องทำการลงโค้ดทั้ง 2 ด้าน คือ Heltec LoRa ESP32 กับ ATmega 2560-Pro


มาดูโค้ดแบบเต็มๆ กันเลย

/*
  Code file name : Rakkan-Cannabis-Heltec-WiFimode-master board
  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 <SoftwareSerial.h>
#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>
#include <Arduino_JSON.h>
//
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 20, 4
//
#include <SoftwareSerial.h>
// SoftwareSerial chat(22, 23); // RX, TX to Nano (5 , 4)
//=========
#include <WiFi.h>
//======
#define RXX 23
#define TXX 22
//===================
#include <Adafruit_Sensor.h>
#include <DHT.h>  // กรณีนี้ต้องใช้คู่กันกับ  DHT_U.h
#include <DHT_U.h>
#define DHTPIN  12 // 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 ;
//======
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";
const char* host = "xxxxxx.com";
//=====
//char* host = "xxxxxx.com";
char* code = "xxxxxxx";
char* dID = "xxx";
float dustDensity = 35;
String response ="0";
String response_c = "0";
String a ;
//
float temp_0 = 0;
float humid_0 = 0;
float vHumidity = 0;
float vTemperature = 0;
float vVolt;
float iamp;
float vEnergy;
String data0 ; // for data request ;
String data1 ;
String datasend ;
String datasend1 ;
String datasend2 ;
String data2 ;
String data3 ;
String data4 ;
String data5 ;
String data6 ;
String data7 ;
String data8 ;
String data9 ;
String JSONSerial = "";
String rx_byte ;
String Question ;
String Confirm ;
int Handrelease ;
int lockdone ;
// byte rx_byte = 0;
/// ===
String sdata1 ;
String sdata2 ; // standard
String sdata3 ;
String sdata4 ;
String sdata5 ;
String sdata6 ;
String sdata7 ;
String sdata8 ;
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,R11,R12 ;
String RR1,RR2,RR3,RR4,RR5,RR6,RR7,RR8 ;
String CommandR5Slave ;  // to control R3 on Nano
String CommandR6Slave ;  // to control R3 on Nano
String CommandR7Slave ; // to control R4 on board
String CommandR8Slave ;  // to control R3 on Nano
String CommandR9Slave ; // to control R4 on board
String CommandR10Slave ;  // to control R3 on Nano
String data10;
String data11;
String data12;
String data13;
String data14;
String data15;
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 nmax = 50;
int sentcount = 0;
int AA , AB , AC ;
String url ;
int Relay10 = 2 ;
int Relay11 = 12 ;
int Relay12 = 25 ;
int n , cycle ;
//
String iddevice = "xxx";
String cccode = "xxxxxxxxxxx";
String ccode = "xxxxxx";
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);
}
//------------------------------------------------
SoftwareSerial gtSerial(22, 23); // Arduino RX, Arduino TX
void setup() {
  Serial.begin(115200);    // serial / USB port
  gtSerial.begin(57600);  // software serial port
  WiFi.setAutoReconnect(true);
  WiFi.persistent(true);
  WiFisetup();
  setup_part2();
}
void setup_LCD()
{
}
void LCD_energy()
{
}
void LCD_weather()
{
}
void LCD_pH()
{
}
void LCD_Pump_Status()
{
}
void LCD_Time_Setting()
{
}
void LCD_Control_Setting()
{
}
//===
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 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);
  Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // serial can be no1 , no 2  8N1
  modbus.begin(Slave_ID1, Serial2);
  // Callbacks allow us to configure the RS485 transceiver correctly
  modbus.preTransmission(preTransmission);
  modbus.postTransmission(postTransmission);
}
bool state = true;
/// for gateway
/*
void LoRaData(){
  Heltec.display->clear();
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);
  Heltec.display->setFont(ArialMT_Plain_10);
  Heltec.display->drawString(0 , 15 , "Received "+ packSize + " bytes");
  Heltec.display->drawStringMaxWidth(0 , 26 , 128, packet);
  Heltec.display->drawString(0, 0, rssi);
  Heltec.display->display();
}
*/
/*
void cbk(int packetSize) {
  packet ="";
  packSize = String(packetSize,DEC);
  for (int i = 0; i < packetSize; i++) { packet += (char) LoRa.read(); }
  rssi = "RSSI " + String(LoRa.packetRssi(), DEC) ;
  LoRaData();
  //sentpacket =packet;
}
*/
/// for gateway
void WiFiForwardSetup()
{
    //WiFisetup();
    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 setup_part2()
{
  //WIFI Kit series V1 not support Vext control
  pinMode(Relay10,OUTPUT);
  pinMode(Relay11,OUTPUT);
  pinMode(Relay12,OUTPUT);
  setup_LCD();
  WiFiForwardSetup();
  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();
  //LoRa.onReceive(cbk);
  //LoRa.receive();
}
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-2021 ");
  Heltec.display->drawString(0, 10, "By SamongThailand ");
  Heltec.display->drawString(0,20, "Mob.0916982616 ");
  Heltec.display->drawString(0,30, "paipatamp@gmail.com");
  //Heltec.display->drawString(0,20, String(datasend2));
  //Heltec.display->drawString(0,30, String(datasend2));
  Heltec.display->display();
  counter=counter+1;
  // send packet
  // LoRa.beginPacket();
  Serial.println("Serial Read position ...");
  delay(2000);        // wait for a second
  Serial_read_loop(); // remove comment if to connect serial
/*
 * 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_loop2();
  delay(2000);
  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();
  /*
  datasend2 = String(data7)+","+String(80)+","+String(90)+","+String(data10);
  datasend1 = String(data3)+","+String(data4)+","+String(data5)+","+String(data6);
  datasend = datasend1+","+datasend2;
  Serial.println(datasend);
  */
  /*
  LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
  LoRa.print(datasend);
  //LoRa.print(counter);
  LoRa.endPacket();
  LoRa.print(counter);
  */
  read_master_status_FromServer();
  //data1 = "";
  //data2 = "";
  PumpARun();
  PumpBRun();
}
// 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
    // double
    // YD meter started from 10
    // addres 13 = Var หารด้วย 10000
    // addres 12 = current หารด้วย 10000
    // address 11 = voltage A or B
    // address 10 =  voltage - C
    // addres 14 = pf
    // 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;
}
///////////////////////////
void Serial_read_loop()
{
Serial.println("Please wait while Serial reading ..");
int n=0;
  a =="";
  while (a == "") {
    if (n>=nmax){
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d3"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    n=n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data received..");
    data1 = "0.0";
    n=0;
  }
  else
  {
    Serial.print(" data1 ext Temperature ");Serial.println(a);
    data1 = String(a);
    delay(1000);
    n=0;
  }
  a="";
  while (a == "") {
    if (n>=nmax){
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d4"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n=n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data received..");
    data2 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data2 ext Moisture ");Serial.println(a);
    data2=String(a);
    delay(1000);
    n=0;
  }
  a="";
  while (a == "") {
    if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d5"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n=n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data received..");
    data3 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data3 int temp ");Serial.println(a);
    data3=String(a);
    delay(1000);
    n=0;
  }
  a="";
  while (a == "") {
    if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d6"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n=n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data received..");
    data4="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data4 int moisture ");Serial.println(a);
    data4 = String(a);
    n=0;
  }
  a="";
  while (a == "") {
    if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d1"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n=n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data received..");
    FlowLowStatus = "0";
    MainPumpStop();
    n=0;
  }
  else
  {
    Serial.print(" data5 temp AM2315  ");Serial.println(a);
    FlowLowStatus =String(a);
    data5 = String(a);
    n=0;
  }
  a="";
  while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d2"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data received..");
    data6 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data6 moisture AM2315  ");Serial.println(a);
    data6=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d7"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data 7 received..");
    data7 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data7 Volt ");Serial.println(a);
    data7=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d8"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data 8 received..");
    data8 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data8 Amp  ");Serial.println(a);
    data8=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d9"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data 9 received..");
    data9 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 9 vPower  ");Serial.println(a);
    data9=String(a);
    n=0;
  }
  a="";
 while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
    gtSerial.print("d10"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
    n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data 10 received..");
    data10 ="0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 10 PF  ");Serial.println(a);
    data10=String(a);
    n=0;
  }
  a="";
  while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
      // gtSerial.print("R1On"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
      gtSerial.print(CommandR5Slave);
      a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
      delay(100);
      Serial.print(".");
      n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data R5 slave received..");
    data11 = "0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 11 R5 Command  ");Serial.println(a);
    data11=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
      gtSerial.print(CommandR6Slave);
      a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
      delay(100);
      Serial.print(".");
      n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data R6 slave received..");
    data12 = "0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 12 R6 Command  ");Serial.println(a);
    data12=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
      gtSerial.print(CommandR7Slave);
      a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
      delay(100);
      Serial.print(".");
      n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data R7 slave received..");
    data13 = "0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 13 R7 Command  ");Serial.println(a);
    data13=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
      gtSerial.print(CommandR8Slave);
      a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
      delay(100);
      Serial.print(".");
      n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data R8 received..");
    data14 = "0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 14 R8 Command  ");Serial.println(a);
    data14=String(a);
    n=0;
  }
  a="";
while (a == "") {
   if (n>=nmax)
    {
      Serial.println("No Serial device connected ...");
      delay(1000);
      a = "Exit";
    }
    else
    {
      gtSerial.print(CommandR9Slave);
      a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
      delay(100);
      Serial.print(".");
      n = n+1;
    }
  }
  if (a =="Exit")
  {
    Serial.println("No data R9 received..");
    data15 = "0.0";
    n=0;
  }
  else
  {
    Serial.print(" data 14 R9 Command  ");Serial.println(a);
    data15=String(a);
    n=0;
  }
  a="";
}
///////////////////////////////////
int value = 0;
void Forward_loop()
{
    ++value;
    //data1 = data1 ;
    //data2 = data2 ;
    Serial.print("connecting to ");
    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(data1) +"&data2="
   + String(data2)+"&data3=" +String(data3)+"&data4=" +String(data4)+"&data5=" +String(data5)
   +"&data6=" +String(data6)+"&data7=" +String(data7)+"&data8=" +String(80)+"&data9=" +String(90)
   +"&data10=" +String(data10)+"&data11=" +String(data11)+"&data12=" +String(data12)+"&data13=" +String(data13)
   +"&data14=" +String(data14)+"&data15=" +String(data15)+"&data16=" +String(data16)+"&data17=" +String(data17)
   +"&data18=" +String(data18)+"&data19=" +String(data19)+"&data20=" +String(data20);
    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(5000);
}
//====
void splint_string(char sz[]){  // สร้างฟังชันต์ชื่อ splint_string กำหนดตัวแปรนำเข้าชื่อ sz ชนิด char แบบอาเรย์
  char *p = sz;  // สร้างตัวแปรชื่อ p ชนิด Pointer มีค่าเท่ากับ sz
  char *str;  // สร้างตัวแปรชื่อ str ชนิด Pointer
  int counter = 0;  // สร้างตัวแปรชื่อ counter ชนิด int สำหรับทำการนับครั้งที่ตัด
  while ((str = strtok_r(p, ",", &p)) != NULL){  // วนทำลูป while ซ้ำ โดยเรียกฟังชันต์ strtok_r() โดยทำการตัดค่าใน p เมื่อเจอเครื่องหมาย','
   // Serial.print(counter + String(". "));  // แสดงผลจำนวนครั้งที่ตัด
   // Serial.println(str); // แสดงผลค่าที่ตัดได้
   counter++;
   if (counter ==1){ccode = str;}
   if (counter ==2){iddevice   = str;}
   if (counter ==3){data1 = str;}
   if (counter ==4){data2 = str;}
   if (counter ==5){data3 = str;}
   if (counter ==6){data4 = str;}
   if (counter ==7){data5 = str;}
   if (counter ==8){data6 = str;}
  }
  counter = 0;  // เคลียร์ค่าใน counter เป็น 0
}
void dataread_loop()
{
  //char charBuf[100];
  str = packet;
  str.toCharArray(charBuf, 100);  // คัดลอกอักขระของชุดอักขระไปยังตัวแปร charBuf
  splint_string(charBuf); // เรียกใช้งานฟังชั่น Splint String
  //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);
      //data11 = String(res_dbl);
      res_dbl = value - modbus.getResponseBuffer(1)/10 ;
      res = "data12 Soil Temp : " + String(res_dbl) + " C\r\n";
      Serial.println(res);
      //data12 = String(res_dbl);
    }
    lastMillis = currentMillis;
  }
}
void PumpTrial()
{
  Serial.println("Starting pump for 1 minutes ...");
  MainPumpRun();
  delay(2000);
}
void ResetSystem()
{
  digitalRead(3);
  ResetPinValue = String(digitalRead(3));
  if (ResetPinValue == "1")
  {
    PumpTrial();
  }
}
void MainPumpRun()
{
   digitalWrite(Relay10,HIGH);
}
void MainPumpStop()
{
   //digitalWrite(Relay2,LOW);
}
void RequestFlowLowStatus()
{
Serial.println("Please wait while Serial request ..");
  while (a == "") {
    gtSerial.print("FlowSensor"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = gtSerial.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
  }
  Serial.print(" Answer for Q1 : = ");Serial.println(a);
  data0 = String(a);
  delay(1000);
  a="";
}
////  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";
         // https://otrixiot.com/api/getRealyStatus/268/SuperSmartHeltec/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);
                  StaticJsonBuffer<2000> jsonBuffer;
                  JsonObject& json_parsed = jsonBuffer.parseObject(json);
                  if (!json_parsed.success())
                    {
                      Serial.println("parseObject() failed");
                      return;
                    }
                      Serial.println("parseObject() OK ...");
                      //Serial.println(result); // show all json found
                      //String led = json_parsed["led"][0]["status"];
                      String master_state = json_parsed["result"]["masterStatus"];
                      String led1 = json_parsed["result"]["relayStatus"]["data6_H"];
                      String led2 = json_parsed["result"]["relayStatus"]["data6_L"];
                      String led3 = json_parsed["result"]["relayStatus"]["data3_status"];
                      String FlowBypass = json_parsed["result"]["relayStatus"]["data5_status"];
                      String RR5 = json_parsed["result"]["relayStatus"]["data1_status"]; // data 3 ext
                      String RR6 = json_parsed["result"]["relayStatus"]["data2_status"]; // data 4 ext
                      String RR7 = json_parsed["result"]["relayStatus"]["data3_status"];  // data5 int
                      String RR8 = json_parsed["result"]["relayStatus"]["data4_status"]; // data6 int
                      String RR9 = json_parsed["result"]["relayStatus"]["data5_status"]; //
                      String RR10 = json_parsed["result"]["relayStatus"]["data6_status"]; // timer T6
                      String RR11 = json_parsed["result"]["relayStatus"]["data7_status"]; // tmer T7
                      String RR12 = json_parsed["result"]["relayStatus"]["data8_status"]; // timer T8
                      R5 = RR5;
                      R6 = RR10;
                      /*
                      Relay R6 ปั๊มน้ำ  และวาล์ว ตั้งให้เปิดปิดด้วย Timer T6  โดยสถานะส่งผ่าน RR10
                      */
                      R7 = RR5;
                      R8 = RR7; //
                      /*
                      Relay R8 พัดลมตัวหน้า ตั้งตาม RR7 ซึ่งเป็นสถานะของ data3 คือ อุณหภูมิภายใน ถ้าอยู่ใน range = On
                      ถ้าอยู่นอก range = Off สามารถจะตั้งให้ทำงานกลับกัน   คือหากร้อน ก็ เปิด
                      */
                      R9 = RR9 ;
                      /*
                      Relay R8 พัดลมตัวหลัง ตั้งตาม RR9 ซึ่งเป็นสถานะของ data5 คือ อุณหภูมิจาก Sensor AM2315 ถ้าอยู่ใน range = On
                      ถ้าอยู่นอก range = Off สามารถจะตั้งให้ทำงานกลับกัน   คือหากร้อน ก็ เปิด
                      */
                      Serial.println("Relay : "+String(R5)+" "+String(R6)+" "+String(R7)+" "+String(R8));
                      // 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("R5 for Fan ext Relay : ");Serial.println(R5);
                      Serial.print("R6 for Pump & Valve Relay : ");Serial.println(R6);
                      Serial.print("R7 for Spare Relay : ");Serial.println(R7);
                      Serial.print("R8 for Fan front Relay : ");Serial.println(R8);
                      Serial.print("R9 for Fan back Relay : ");Serial.println(R9);
                      Time1 = led1 ;
                      Time2 = led2 ;
                      CommandR5Slave = "R5"+String(R5) ;
                      CommandR6Slave = "R6"+String(R6) ;
                      CommandR7Slave = "R7"+String(R7) ;
                      CommandR8Slave = "R8"+String(R8) ;
                      CommandR9Slave = "R9"+String(R9) ;
                      Serial.print("Command R5 Slave : ");Serial.println(CommandR5Slave);
                      Serial.print("Command R6 Slave : ");Serial.println(CommandR6Slave);
                      Serial.print("Command R7 Slave : ");Serial.println(CommandR7Slave);
                      Serial.print("Command R8 Slave : ");Serial.println(CommandR8Slave);
                      Serial.print("Command R9 Slave : ");Serial.println(CommandR9Slave);
                      if (master_state == "0")
                      {
                        MainPumpStop();
                        MainPump = "Stop";
                      }
                      else
                      {
                        // this loop master_state == "1
                        if (R5 =="1")
                        {
                              MainPumpRun();
                              MainPump = "Run" ;
                              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);
                       //
                      lcd.clear();
                      lcd.setCursor(0,0);
                      lcd.print("   Pump Status");
                      lcd.setCursor(0,1);
                      lcd.print("Main Pump    :      ");
                      lcd.setCursor(0,2);
                      lcd.print("Flow Sensor  :      ");
                      lcd.setCursor(0,3);
                      lcd.print("Flow By-Pass :      ");
                      lcd.setCursor(14,1);
                      lcd.print(MainPump);
                      lcd.setCursor(14,2);
                      lcd.print(flowsensor);
                      lcd.setCursor(14,3);
                      lcd.print(FlowBypass);
                      delay(5000);
                      //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()
{
  LCD_energy();
  delay(2000);
  LCD_weather();
}
void PumpARun() // run Pump A 10 min
{
  if (EC <= 1000)
  {
  digitalWrite(Relay11,HIGH);
  Serial.println("Pump A Run");
  }
  else
  {
  digitalWrite(Relay11,LOW);
  Serial.println("Pump A Run");
  }
}
void PumpBRun() // open water valve 12 Vdc
{
  digitalWrite(Relay12,HIGH);
  Serial.println("Pump B Run");
}

และอีกฝั่งคือ Atmega

/*SMT-006 V1.0 - MCU - Mega 2560
 * RS485 - P3
 * PZEM - P27 or TTL
 * AM2315 - I2C - P39
 *
 * */
//==
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
//====== FOr Modbus ============
#include <Convert.h>
#include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster
#include <ModbusRtu.h>
#include <HardwareSerial.h>
//===============================
//===== RTC DS1307 on MEGA ======
#include <TimeLib.h>
#include <DS1307RTC.h>
//#include "RTClib.h"
//================================
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
#include "DHT.h"
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_AM2315.h>
// Temp-Mositure Sensor /// AM2315
// Connect RED of the AM2315 sensor to 5.0V
// Connect BLACK to Ground
// Connect WHITE to i2c clock
// Connect YELLOW to i2c data
///==== PZEM004TV30====
#include <PZEM004Tv30.h>
#if !defined(PZEM_RX_PIN) && !defined(PZEM_TX_PIN)
#define PZEM_RX_PIN 14
#define PZEM_TX_PIN 15
#endif
#if !defined(PZEM_SERIAL)
#define PZEM_SERIAL Serial3
#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
////////// Auto Manual Mode  ////////
int AutoMode = 0;
///// Set time for posting tp server ///
int New_post_time = 0;
int post_time = 0;
int Time_check = 0;
int post_duration = 2 ;  // posting interval every 2 minutes
int pzemtime= 1000;
int tempp = 0;
int AutoModePinValue ;
int ManualModePinValue ;
String Modeselect ;
String master_state;
String abc ;
String rx_byte ;
String rx_byte2 ;
String rx_byte3 ;
String R5Status,R6Status,R7Status,R8Status,R9Status,R10Status ;
int lockdone ;
int Handrelease ;
String OKCheck ;
String Reconfirm ;
int h, QA,QB,QC ,ha ;
int QACount, i ;
//float DataSet[20] = {0.0,11.1,22.2,33.3,44.4,55.5,66.6,77.7,88.8,99.9
//                     ,100.0,111.11,222.22,333.33,444.44,555.55,666.66
//                     ,777.77,888.88,999.99};
// byte rx_byte = 0;
// RTC DS-1307
// RTC_Millis rtc;
Adafruit_AM2315 am2315; // object AM2315 temp moisture sensor
///============ RS485 on Mega ==============
#define RX_PIN     16    //Serial Receive pin 16
#define TX_PIN     17    //Serial Transmit pin 17
#define MAX485_RE_NEG    49    //LED P54
#define RS485Transmit    HIGH
#define RS485Receive     LOW
#define  LED      0
float temp,pH ;
//========== XYMD02 =========
//#define  RXD      22
//#define  TXD      23
//#define  RS485DE  25
//#define  LED      0
Modbus      master(0, Serial2, MAX485_RE_NEG); // this is master and RS-232 or USB-FTDI
modbus_t    telegram[4];
uint16_t    au16data[8];
float   humidity;
float   temperature;
uint8_t  RTU_Slave_ID;
uint8_t  RTU_NEW_Slave_ID;
uint8_t Slave_ID;
//====== end of RS485 on MEGA ===============
/////////// Ethernet Shield //////////////////////////////////////
String data1_H;
String data2_H;
String data3_H;
String data4_H;
String data5_H;
/*
String data6_H;
String data7_H;
String data8_H;
String data9_H;
String data10_H;
*/
String data1_L;
String data2_L;
String data3_L;
String data4_L;
String data5_L;
/*
String data6_L;
String data7_L;
String data8_L;
String data9_L;
String data10_L;
*/
String data1_status;
String data2_status;
String data3_status;
String data4_status;
String data5_status;
/*
String data6_status;
String data7_status;
String data8_status;
String data9_status;
String data10_status;
*/
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip2(192, 168, 1, 176);  // set ip2 192,168,1,176  for Ethernet shield
// fill in your Domain Name Server address here:
IPAddress myDns(1, 1, 1, 1);
// initialize the library instance:
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
const char* host = "xxxxxx.com";
const char* code = "xxxxxx";
const char* dID = "xxxxx";
//// end ethernet shield /////
//// next LCD initial /////
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);
float LCDDisplayPeriod = 2000;
float LastLCDDisplay;
float ThisLCDDisplay;
//// energy meter setup ///
bool pzemrdy = false;
/// end PZEM ////
/// prepare host url  ////
String url;   // ใช้สำหรับ โปรแกรมส่วนการส่ง
int count = 0;
int httpPort = 80;
////
const int chipSelect = 4;
/// control panel condition ////
String panelstate   = "OFF";
float vHumidity = 0;
float vTemperature = 0;
float vTemperature1 = 0;
float vTemperature2 = 0;
float data1=59;
float data2=33;
String data3 , dataa3 ;
String data4 , dataa4 ;
float data5 ,data6,data7,data8,data9,data10,data11,data12 ;
float data13 ,data14,data15,data16,data17,data18,data19,data20;
float vPower=0;
float vVolt=0;
float iamp=0;
float vEnergy=0;
#define Relay1 4
#define Relay2 5
#define Relay3 6
#define Relay4 7
#define Relay5 8
#define Relay6 9
#define Relay7 10
#define Relay8 11
#define Relay9 12
//============== SHT20-XYMD02 ============
void setup_XYMD02()
{
  delay(250);
  pinMode(LED, OUTPUT);
  pinMode(MAX485_RE_NEG, OUTPUT);
  digitalWrite( MAX485_RE_NEG, LOW );//RX
  Serial2.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;
  //RTU_Slave_ID = 0;  // ใช้สำหรับการเปลี่ยน ID
  //RTU_NEW_Slave_ID = 1;
  //Change_Slave_ID(RTU_Slave_ID, RTU_NEW_Slave_ID);
}
//=============
void setup() {
  //initialize serial ports
  Serial.begin(9600);    // USB serial port 0
  Serial1.begin(57600);   // serial port 1
  RTC_setup();
  AM2315_setup();
  setup_XYMD02();
  pinMode(Relay1,OUTPUT);
  pinMode(Relay2,OUTPUT);
  pinMode(Relay3,OUTPUT);
  pinMode(Relay4,OUTPUT);
  pinMode(Relay5,OUTPUT);
  pinMode(Relay6,OUTPUT);
  pinMode(Relay7,OUTPUT);
  pinMode(Relay8,OUTPUT);
  pinMode(Relay9,OUTPUT);
  Test_Relay();
  setup_SerialCommunication();
  setup_NetworkConnection();
}
void setup_SerialCommunication()
{
// Open serial communications and wait for port to open:
   Serial1.begin(57600);
}
void setup_NetworkConnection()
{
  // give the ethernet module time to boot up:
  delay(1000);
  Ethernet.init(29);  // Mega2560
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac, ip2, myDns);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  EthernetClient Client;
}
void RTC_setup ()
{
    // Serial.begin(115200);
    // following line sets the RTC to the date & time this sketch was compiled
    // /// rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
void AM2315_setup()
{
  while (!Serial) {
    delay(10);
  }
  Serial.println("AM2315 Test!");
  if (! am2315.begin()) {
     Serial.println("Sensor not found, check wiring & pullups!");
     //while (1);
  }
}
// byte rx_byte = 0;        // stores received byte
void loop()
{
  RTC_DS1307_loop();
  AM2315_loop();
  XYMD02_loop2();
  PZEM_loop();
  Serial_Send();
  delay(1000);
  if(R5Status == "On" ){
    digitalWrite(Relay5,HIGH);
    //Serial.println("R5 On");
  }
  else
  {
    digitalWrite(Relay5,LOW);
    //Serial.println("R5 Off");
  }
  if(R6Status == "On" ){
    digitalWrite(Relay6,HIGH);
    Serial.println("R6 Pump & Valve On");
  }
  else
  {
    digitalWrite(Relay6,LOW);
    Serial.println("R6 Pump & Valve Off");
  }
  if(R7Status == "On" ){
    digitalWrite(Relay7,HIGH);
    //Serial.println("R7 On");
  }
  else
  {
    digitalWrite(Relay7,LOW);
    //Serial.println("R7 Off");
  }
  if(R8Status == "On" ){
    digitalWrite(Relay8,HIGH);
    Serial.println("R8 Fan front On");
  }
  else
  {
    digitalWrite(Relay8,LOW);
    Serial.println("R8 Fan front Off");
  }
  if(R9Status == "On" ){
    digitalWrite(Relay9,HIGH);
    Serial.println("R9 Fan back on");
  }
  else
  {
    digitalWrite(Relay9,LOW);
    Serial.println("R9 Fan back Off");
  }
  //readControlCommandFromServer();
  //saveSystemStatusToServer();
}
void Test_Relay()
{
    digitalWrite(Relay6,LOW);
    delay(500);
    digitalWrite(Relay8,LOW);
    delay(500);
    digitalWrite(Relay9,LOW);
    delay(500);
    digitalWrite(Relay6,HIGH);
    delay(500);
    digitalWrite(Relay8,HIGH);
    delay(500);
    digitalWrite(Relay9,HIGH);
    delay(500);
}
void Stop_All_Led()
{
    digitalWrite(Relay1,LOW);
    delay(500);
    digitalWrite(Relay2,LOW);
    delay(500);
    digitalWrite(Relay3,LOW);
    delay(500);
    digitalWrite(Relay4,LOW);
    delay(500);
    digitalWrite(Relay5,LOW);
    delay(500);
    digitalWrite(Relay6,LOW);
    delay(500);
    digitalWrite(Relay7,LOW);
    delay(500);
    digitalWrite(Relay8,LOW);
    delay(500);
    digitalWrite(Relay9,LOW);
    delay(500);
}
void Serial_Send()
{
  Serial1.begin(57600);
  if (Serial1.readString())
  {
     if(Serial1.readString()== "d1"){ //มีการถามคำถาม Question1 ส่งข้อมูลตัวแปร a ออกไป
      Serial1.print(String(data1));
     }
     if(Serial1.readString()== "d2"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     Serial1.print(String(data2));
     }
     if(Serial1.readString()== "d3"){ //มีการถามคำถาม Question1 ส่งข้อมูลตัวแปร a ออกไป
      Serial1.print(String(data3));
     }
     if(Serial1.readString()== "d4"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     Serial1.print(String(data4));
     }
     if(Serial1.readString()== "d5"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     Serial1.print(String(data5));
     }
     if(Serial1.readString()== "d6"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     Serial1.print(String(data6));
     }
     if(Serial1.readString()== "d7"){ //มีการถามคำถาม Question1 ส่งข้อมูลตัวแปร a ออกไป
      Serial1.print(String(data7));
     }
     if(Serial1.readString()== "d8"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     Serial1.print(String(data8));
     }
     if(Serial1.readString()== "d9"){ //มีการถามคำถาม Question1 ส่งข้อมูลตัวแปร a ออกไป
      Serial1.print(String(data9));
     }
     if(Serial1.readString()== "d10"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     Serial1.print(String(data10));
     }
     if(Serial1.readString()== "R51"){
     Serial1.print(String("1"));
     R5Status = "On";
     }
     if(Serial1.readString()== "R61"){
     Serial1.print(String("1"));
     R6Status = "On";
     }
     if(Serial1.readString()== "R71"){
     Serial1.print(String("1"));
     R7Status = "On";
     }
     if(Serial1.readString()== "R81"){
     Serial1.print(String("1"));
     R8Status = "On";
     }
     if(Serial1.readString()== "R91"){
     Serial1.print(String("1"));
     R9Status = "On";
     }
     if(Serial1.readString()== "R50"){
     Serial1.print(String("0"));
     R5Status = "OFF";
     }
     if(Serial1.readString()== "R60"){
     Serial1.print(String("0"));
     R6Status = "OFF";
     }
     if(Serial1.readString()== "R70"){
     Serial1.print(String("0"));
     R7Status = "OFF";
     }
     if(Serial1.readString()== "R80"){
     Serial1.print(String("0"));
     R8Status = "OFF";
     }
     if(Serial1.readString()== "R90"){
     Serial1.print(String("0"));
     R9Status = "OFF";
     }
     Serial.println("Sent data done ");
  }
}
//=======
void RTC_DS1307_loop() {
  tmElements_t tm;
  if (RTC.read(tm)) {
    Serial.print("Time = ");
    print2digits(tm.Hour);
    Serial.write(':');
    print2digits(tm.Minute);
    Serial.write(':');
    print2digits(tm.Second);
    Serial.print(", Date (D/M/Y) = ");
    Serial.print(tm.Day);
    Serial.write('/');
    Serial.print(tm.Month);
    Serial.write('/');
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.println();
  } else {
    if (RTC.chipPresent()) {
      Serial.println("The DS1307 is stopped.  Please run the SetTime");
      Serial.println("example to initialize the time and begin running.");
      Serial.println();
    } else {
      Serial.println("DS1307 read error!  Please check the circuitry.");
      Serial.println();
    }
    delay(9000);
  }
  delay(1000);
}
void AM2315_loop()
{
  float temperature, humidity;
  temperature = 25 ;
  humidity = 90 ;
  if (! am2315.readTemperatureAndHumidity(&temperature, &humidity)) {
    Serial.println("Failed to read data from AM2315");
    //return;
  }
  Serial.print("data1 Temp *C: "); Serial.println(temperature);
  Serial.print("data2 Hum %: "); Serial.println(humidity);
  delay(1000);
  data1 = 25; //temperature;
  data2 = 90 ; // humidity;
}
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}
void PZEM_loop() {
    // Print the custom address of the PZEM
    Serial.print("Custom Address:");
    Serial.println(pzem.readAddress(), HEX);
    float voltage = 220 ;
    float current = 3.5 ;
    float power = 750 ;;
    float energy= 300 ;
    float frequency = 50 ;
    float pf = 0.85 ;
    // Read the data from the sensor
    voltage = pzem.voltage();
    current = pzem.current();
    power = pzem.power();
    energy = pzem.energy();
    frequency = pzem.frequency();
    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);
    }
    Serial.println();
    data7 = 220 ; //voltage;
    data8 = 3.5 ; //current;
    data9 = 750 ; //power;
    data10 = 220 ; // energy;
    data11 = 50 ; //frequency;
    data12 = 0.9 ; //pf;
    Serial.println();
}
void readControlCommandFromServer()
{
  Serial.print("Read control command from Server ... connecting to ");
  Serial.println(host);
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  client.stop();
  delay(1000);
  //EthernetClient client;
  if (client.connect(host, 80))
  {
    Serial.println("reconnecting...");
    url = "/api/readLast/IOT_API_KEY_BY_ADMIN/267/SuperSmartBoard";
    Serial.print("Requesting URL: ");
    Serial.println(url);
    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);
        StaticJsonBuffer<1500> jsonBuffer;
        JsonObject& json_parsed = jsonBuffer.parseObject(json);
        if (!json_parsed.success())
        {
          Serial.println("parseObject() failed");
          return;
        }
        Serial.println("parseObject() OK ...");
        Serial.println(result); // show all json found
        //String led = json_parsed["led"][0]["status"];
        String master_state = json_parsed["result"]["deviceData"]["master_status"];
        String led1 = json_parsed["result"]["deviceData"]["data1"];
        String led2 = json_parsed["result"]["deviceData"]["data2"];
        String led3 = json_parsed["result"]["deviceData"]["data3"];
        // string led = json_parsed["table name""][array number]["value of field"]
        Serial.println("Read control led 1, 2, 3 ...");
        Serial.println(led1);
        Serial.println(led2);
        Serial.println(led3);
      } // 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");
  }
  client.stop();
  delay(1000);
}
// ==  end read control from server ===
void readControlCommandFromServer_2()
{
  Serial.print("Read control command from Server ... connecting to ");
  Serial.println(host);
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  client.stop();
  delay(1000);
  //EthernetClient client;
  if (client.connect(host, 80))
  {
    Serial.println("reconnecting...");
    //url = "/api/readLast/IOT_API_KEY_BY_ADMIN/98/dfwc93452v3t";
    url = "/api/readLast/IOT_API_KEY_BY_ADMIN/267/SuperSmartBoard";
    Serial.print("Requesting URL: ");
    Serial.println(url);
    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);
        StaticJsonBuffer<1700> jsonBuffer;
        JsonObject& json_parsed = jsonBuffer.parseObject(json);
        if (!json_parsed.success())
        {
          Serial.println("parseObject() failed");
          return;
        }
        Serial.println("parseObject() OK ...");
        Serial.println(result); // show all json found
        //String led = json_parsed["led"][0]["status"];
        String master_state = json_parsed["result"]["deviceData"]["master_status"];
        String led1 = json_parsed["result"]["deviceData"]["data1"];
        String led2 = json_parsed["result"]["deviceData"]["data2"];
        String led3 = json_parsed["result"]["deviceData"]["data3"];
        // string led = json_parsed["table name""][array number]["value of field"]
        Serial.println("Read control led 1, 2, 3 ...");
        Serial.println(led1);
        Serial.println(led2);
        Serial.println(led3);
      } // 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 2");
  }
  client.stop();
  delay(1000);
}
// ==  end read control from server ===
void saveSystemStatusToServer()
{
  /////  prepare variable of data for upload to server //////
  String url = "/api/insertData?device_id=" + String(dID) + "&code=" + String(code) + "&data1=" + String(data1) + "&data2="
               + String(data2) + "&data3=" + String(data3) + "&data4=" + String(data4) + "&data5=" + String(data5)
               + "&data6=" + String(data6) + "&data7=" + String(data7) + "&data8=" + String(data8) + "&data9=" + String(data9)
               + "&data10=" + String(data10) + "&data11=" + String(data11) + "&data12=" + String(data12) + "&data13=" + String(data13)
               + "&data14=" + String(data14) + "&data15=" + String(data15) + "&data16=" + String(data16) + "&data17=" + String(data17)
               + "&data18=" + String(data18) + "&data19=" + String(data19) + "&data20=" + String(data20);
  Serial.print("Resquesting URL: ");
  Serial.println(url);
  delay(1000);
  // if there's a successful connection:
  //EthernetClient client;
  delay(1000);
  /*if (millis() - lastConnectionTime > postingInterval)
    {
  */
  if (client.connect(host, 80))
  {
    Serial.println("Data submitting to server  ... waiting...");
    client.println(String("GET ") + url + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n\r\n");
    //client.println("Connection: close");
    Serial.println("Data saved completed..");
  }
  else
  {
    // if you couldn't make a connection:
    Serial.println("connection failed 2 ");
  }
  while (client.available())
  {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  /*
    }
  */
  client.stop();
  Serial.println("closing connection");
}
//=============
void XYMD02_loop2()
{
  //Read_DATA_SHT20_XYMD02(1);//Modbus ID
  //Read_Hardware_Parameter_SHT20_XYMD02(1);//Modbus ID
  data3= dataa3;
  data4= dataa4;
  data5= 30 ; // dataa3;
  data6= 90 ; // dataa4;
  delay(1000);
  //Read_DATA_SHT20_XYMD02(2);//Modbus ID
  //Read_Hardware_Parameter_SHT20_XYMD02(2);//Modbus ID
}
/**************************************************************
  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)//
{
  temperature   = 30 ; // dummy
  humidity      = 90 ; // dummy
  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    = 1;          //257;//1; // start address in slave
  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;
        dataa3 = String(temperature);
        dataa4 = String(humidity);
        data5 = temperature;
        data6 = humidity;
        Serial.println("---------------------------------------------------");
        Serial.print(" Temperature      =  ");
        Serial.print(temperature);
        Serial.println("  *C");
        Serial.print(" Humidity         =  ");
        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);
}

 
มาดูผลการทำงานกันครับ
 


หลักการทำงานของบอร์ด

  1. ATMega : ทำหน้าที่อ่าน input
    1. AM2315  I2C จาก  P39 ,
    2. PZEM (Serial3 จากพอร์ต  TTL, P44 ) ,
    3. SHT20-XYMD02  ทางพอร์ต  RS485
  2. Heltec LoRa
    1. ทำหน้าที่อ่านข้อมูลจาก ATmega ผ่านทาง Serial 1 – โดย  void Serial-read
    2. เชื่อมต่อกับ Internet
    3. เตรียมไว้สำหรับการอ่านค่าจาก LoRa Node
    4. นอกจากนี้จะอ่านค่าจาก  Server เพื่อส่งสถานะ downlink ไปควบคุมการทำงานของ Relay R10-12
    5. และยังสามารถส่งข้ามไปควบคุม  Relay ในระบบของ ATmega

วิจารณ์ผล

  1. ระบบทำงานได้ตามที่ต้องการ  สามารถตั้งค่าควบคุมได้จาก มือถือ  และ desktop โดยเป็นการตั้งค่าควบคุม  สูง ต่ำ และการตั้งรีเลย์
  2. การส่งผ่านด้วย Serial ตามโค้ดนี้จะใช้เวลา loop ละ 4-5 นาที  ซึ่งมีทั้งข้อดีและข้อเสีย  ข้อดีคือ  เป็นการหน่วงเวลาการทำงานไปโดยไม่ต้องใช้ milli  และ delay ส่วนข้อเสียคือ  ช้า
  3. แนวทางการปรับปรุงในข้อ 2 คือการพัฒนาการส่งด้วย  JSON format  รอติดตามผลกันต่อไป


25/Sep/2021