Smart LoRa Board – Heltec Esp32 + Nano

สวัสดีครับ  ขอแนะนำน้องใหม่ของเราวันนี้  SMT-001-Ver 2021
รุ่นนี้เป็นการต่อยอดจากรุ่นก่อน  โดยมีการเปลี่ยนโฉม ปรับลดดังนี้
เปลี่ยนจาก Wemos D1R1  เป็น   Heltec LoRa esp32 –> เพื่อวัดใจคนอยากได้การส่งจากฟาร์มแบบไกลๆ ห่างจากบ้านราวซักกิโลเมตร  ให้ส่งมาหา Gateway LoRa-WiFi  แล้วส่งไปยัง Server อีกที
นอกจากนี้  หากมี WiFi ใกล้ๆ ก็เลือกที่จะส่งเป็น WiFi กันได้เลย ก็ดัดแปลงโค้ดกันเล็กน้อย
มาดูองค์ประกอบบนบอร์ดกันดีกว่า

  • Heltec LoRa esp32  ตามที่กล่าวแล้ว
  • Arduino Nano  ที่เอาไว้วัดพวก Analog ต่างๆ รวมทั้งวัด I2C
  • Port I2C ที่จะวิ่งเข้า Nao
  • Port I2C สำรองที่ต่อเข้า Heltec LoRa 32
  • IO-RS485 ที่ต่อเข้ายัง   heltec LoRa
  • Terminal Vac-220
  • Terminal 12 Vdc -> สำหรับการรับไฟฟ้าจาก Solar Cell
  • Relay 4 ชุด  ลดลงจากเดิม 2 ตัว  ทั้งนี้เพื่อให้เหบือ IO สำหรับการใช้งาน Interrupt  ซึ่งหากใครจะไม่ใช้ และเอาไปต่อขับ Relay ก็ยังใช้การได้เต็มที่เช่นเดิม


ผลการทดสอบเป็นไปได้ด้วยดี  พร้อมทดสอบโค่ดทั้ง 2 Mode ได้ผลดีเยี่ยม
มาลองดูโค้ดกัน  นี่เอาแบบยังไม่ปรับปรุงงกันเลย เอาแค่ work ก่อน

/*
  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>
//=========
#include <WiFi.h>
//======
#define RXX 17
#define TXX 13
#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     = "xxxxxxxxal2019_2.4G";
const char* password = "kbxxxxxxx12";
//const char* ssid     = "dlink_DWR-932C_0C4E";
//const char* password = "gkyVD35784";
//const char* ssid     = "AndroidAP-J7";
//const char* password = "braw5645";
//const char* ssid     = "true_home2G_F78";
//const char* password = "96104427";
const char* host = "otrixiot.com";
float temp_0 = 0;
float humid_0 = 0;
float vHumidity = 0;
float vTemperature = 0;
//=======================
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 data10=33;
float data11=33;
float data12=33;
float data13=33;
float data14=33;
float data15=33;
float data16=33;
float data17=33;
float data18=33;
float data19=33;
float data20=33;
/// ===
//float temp_0 = 0;
//float humid_0 = 0;
//float vHumidity = 0;
//float vTemperature = 0;
String data1="xxx";
String iddevice = "xxx";
String cccode = "xxxxxx";
String ccode = "xxxxxxx";
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);
}
//------------------------------------------------
//===
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 AM2301_setup() {
  Serial.begin(9600);
  // Initialize device.
  dht.begin();
  Serial.println("DHTxx Unified Sensor Example");
  // Print temperature sensor details.
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" *C");
  Serial.println("------------------------------------");
  // Print humidity sensor details.
  dht.humidity().getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println("%");
  Serial.println("------------------------------------");
  // Set delay between sensor readings based on sensor details.
  delayMS = sensor.min_delay / 1000;
}
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);
}
/// 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()
{
    Serial.begin(115200);
    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()
{
  //WIFI Kit series V1 not support Vext control
  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();
  //AM2301_setup();
  Serial2.begin(9600, SERIAL_8N1,17,13); // สำคัญเลย กำหนด Serial ที่ 3 ของบอร์ด
  //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 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);
  //AM2301_loop();
  /*
  data2 = "22.22";
  data3 = "33.33";
  data4 = "44.44";
  data5 = "55.55";
  data6 = "66.66";
  data7 = "77.77";
   */
  Forward_loop();
  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
}
// RS485 loop
void RS485_loop1()
{
  long currentMillis = millis();
  if (currentMillis - lastMillis > 1000)
  {
    float result = modbus.readHoldingRegisters(0x11,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 AM2301_loop() {
  // Delay between measurements.
  /*
  delay(delayMS);
  // Get temperature event and print its value.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    Serial.print("Temperature AM2301 : ");
    Serial.print(event.temperature);
    Serial.println(" *C");
    temp_0 = event.temperature;
    data6 = String(temp_0);
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    Serial.print("Humidity AM2301 : ");
    Serial.print(event.relative_humidity);
    Serial.println("%");
    humid_0 = event.relative_humidity;
    data7 =String(humid_0);
  }
  */
}
void serial_loop()
{
Serial.println("Please wait Serial..");
  while (a == "") {
    Serial2.print("Input1"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = Serial2.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
  }
  Serial.print(" Answer1 ");Serial.println(a);
  data8 = String(a);
  delay(1000);
  a="";
  while (a == "") {
    Serial2.print("Input2"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = Serial2.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
  }
  Serial.print(" Answer2 ");Serial.println(a);
  data9=String(a);
  a="";
  while (a == "") {
    Serial2.print("Input3"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = Serial2.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
  }
  Serial.print(" Answer3 ");Serial.println(a);
  data6=String(a);
  a="";
  while (a == "") {
    Serial2.print("Input4"); // ส่งหัวข้อคำถาม ว่า Question1 ไปยัง Arduino
    a = Serial2.readString();  // อ่าน Serial และนำไปเก็บในตัวแปร A
    delay(100);
    Serial.print(".");
  }
  Serial.print(" Answer4 ");Serial.println(a);
  data7 = String(a);
}
int value = 0;
void Forward_loop()
{
    delay(5000);
//    scanSensor_Box_Temperature();
    //data1 = vTemperature;
    ++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(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("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);
    data1="0";
    data2="0";
    data3="0";
    data4="0";
    data5="0";
    data6="0";
}
//====
//====
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);
}

อาจจะมีโค้ดเซนเซอร์แถมลงไปเยอะหน่อยนะครับ  ก็ทะยอยเอาออกหากไม่ใช้
มาดูฝั่ง Nano  ก็เดิมๆ สำหรับการมาต่อ Series

#include <EEPROM.h>
#include <SoftwareSerial.h>
SoftwareSerial chat(5, 4); // RX 11 , TX 10
////////  AM2302
#include <math.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>  // กรณีนี้ต้องใช้คู่กันกับ  DHT_U.h
#include <DHT_U.h>
#define DHTPIN 10 // Pin which is connected to the DHT sensor.
// Uncomment the type of sensor in use:
//#define DHTTYPE           DHT11     // DHT 11
#define DHTTYPE           DHT22     // DHT 22 (AM2302)
//#define DHTTYPE           DHT21     // DHT 21 (AM2301)
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;
////////
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 temperatureC = 0;
float temperatureF = 0;
int counter = 1;
int sentcount = 0;
//////////////////////////////
void AM2302_setup() {
  dht.begin();
  Serial.println("DHTxx Unified Sensor Example");
  // Print temperature sensor details.
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" *C");
  Serial.println("------------------------------------");
  // Print humidity sensor details.
  dht.humidity().getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println("%");
  Serial.println("------------------------------------");
  // Set delay between sensor readings based on sensor details.
  delayMS = sensor.min_delay / 1000;
}
void setup()  {
  Serial.begin(9600);
  chat.begin(9600);
}
void loop() {
  AM2302_loop();
  input1_loop();
  //input2_loop();
  if (chat.readString()){
     // chat.print(1);
     if(chat.readString()== "Input1"){ //มีการถามคำถาม Question1 ส่งข้อมูลตัวแปร a ออกไป
      chat.print(String(sensorValue));
     }
     if(chat.readString()== "Input2"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     chat.print(String(rainmm));
     }
     if(chat.readString()== "Input3"){ //มีการถามคำถาม Question1 ส่งข้อมูลตัวแปร a ออกไป
      chat.print(String(data3));
     }
     if(chat.readString()== "Input4"){ //มีการถามคำถาม Question2 ส่งข้อมูลตัวแปร b ออกไป
     chat.print(String(data4));
     }
     Serial.print("Send = ");
     Serial.println(i);
  }
  i++;
  delay(1000);
}
void input1_loop() {
  // read the value from the sensor:
  sensorValue = analogRead(A0);
  //Serial.print(" Analog read := ");Serial.println(sensorValue);
  if (sensorValue > 580) {
    rainmm = 80.437-0.0977*sensorValue;
  }
  else {
    if (sensorValue > 509) {
      rainmm = 443.6-0.717*sensorValue;
    }
    else
    {
      if (sensorValue > 466) {
        rainmm = 903.74-1.6059*sensorValue;
      }
      else{
      rainmm = 770.06-1.3314*sensorValue;
      }
    }
  }
  delay(1000);
  //answer=String(255);
  Serial.print("A0 signal : ");Serial.println(sensorValue);
  Serial.print("Rain mm : ");Serial.println(rainmm);
}
void input2_loop() {
  // read the value from the sensor:
  sensorValue = analogRead(A0);
  //Serial.print(" Analog read := ");Serial.println(sensorValue);
  if (sensorValue > 580) {
    rainmm = 80.437-0.0977*sensorValue;
  }
  else {
    if (sensorValue > 509) {
      rainmm = 443.6-0.717*sensorValue;
    }
    else
    {
      if (sensorValue > 466) {
        rainmm = 903.74-1.6059*sensorValue;
      }
      else{
      rainmm = 770.06-1.3314*sensorValue;
      }
    }
  }
  delay(1000);
  //answer=String(255);
}
void AM2302_loop() {
  // Delay between measurements.
  delay(delayMS);
  // Get temperature event and print its value.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    Serial.print("Temperature: ");
    Serial.print(event.temperature);
    Serial.println(" *C");
    temp_0 = event.temperature;
    data3 = temp_0;
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    Serial.print("Humidity: ");
    Serial.print(event.relative_humidity);
    Serial.println("%");
    humid_0 = event.relative_humidity;
    data4 = humid_0;
  }
}

Nano ก็เช่นกัน  มีของแถมให้เยอะเลย