ต้องการทำ ESP32 LAT LONG TO MODBUS

สวัสดีครับ ตอนนี้ผมใช้ ESP32 อ่านค่าจาก GPS NEO-M8N แสดงผลบนหน้าจอ 16*2 อยู่ครับ
ค่าที่่แสดงตอนนี้ มีค่า LAT LONG และ COG ผมต้องการให้ค่า 3 อย่างนี้
ส่งไปยังอุปกรณ์ HMI ผ่าน MODBUS RS485 ผมต้องเขียนโค้ดยังไงครับ ต้องให้ตัว ESP เป็น Slave ใช่ไหมครับ
พึ่งได้ทดลองทำ Modbus ครับ ตอนนี้พึ่งซื้อ MAX485 TO TTL ที่มี RE DE กับ ตัวที่ไม่มี RE DE ครับ

ขอบคุณครับ

สวัสดีครับ! จากที่คุณต้องการให้ ESP32 อ่านค่าจาก GPS NEO-M8N แล้วส่งค่า LAT, LONG, และ COG ไปยังอุปกรณ์ HMI ผ่าน Modbus RS485 คุณต้องกำหนดให้ ESP32 เป็น Slave ในเครือข่าย Modbus RTU ครับ


:small_blue_diamond: อุปกรณ์ที่ต้องใช้:

  1. ESP32
  2. โมดูล GPS NEO-M8N
  3. โมดูล MAX485 to TTL (ตัวที่มี RE/DE จะควบคุมการส่ง/รับได้ง่ายกว่า)
  4. อุปกรณ์ HMI ที่รองรับ Modbus RTU (RS485)

:small_blue_diamond: การตั้งค่าอุปกรณ์:

  • ESP32 ต้องทำหน้าที่เป็น Modbus Slave
  • HMI ทำหน้าที่เป็น Modbus Master
  • ใช้ RS485 เป็นโปรโตคอลสื่อสาร
  • ใช้ไลบรารี ModbusRTU ของ ESP32

:small_blue_diamond: วิธีเชื่อมต่อ MAX485 กับ ESP32

MAX485 ESP32
VCC 3.3V หรือ 5V
GND GND
RO (Receive Out) RX (GPIO16 ตัวอย่าง)
DI (Data In) TX (GPIO17 ตัวอย่าง)
RE (Receive Enable) GPIO4 (ตั้งค่า LOW เพื่อรับข้อมูล)
DE (Driver Enable) GPIO4 (ตั้งค่า HIGH เพื่อส่งข้อมูล)
A ไปที่ A ของ HMI
B ไปที่ B ของ HMI

หมายเหตุ:

  • ขา RE/DE ต้องเชื่อมด้วยกันและใช้ GPIO ควบคุมการรับ/ส่ง
  • ปกติ RE = LOW (รับข้อมูล) และ DE = HIGH (ส่งข้อมูล)

:small_blue_diamond: ตัวอย่างโค้ด ESP32 เป็น Modbus RTU Slave (ใช้ไลบรารี ModbusRTU.h)

ติดตั้งไลบรารี ModbusRTU ก่อน โดยไปที่ Arduino IDE → Library Manager และค้นหา ModbusRTU จาก emelianov แล้วติดตั้ง

#include <ModbusRTU.h>
#include <HardwareSerial.h>

// กำหนดขา RX, TX และขาที่ใช้ควบคุม MAX485
#define RXD2 16
#define TXD2 17
#define RE_DE 4  // ใช้ขานี้ควบคุมโหมดส่ง/รับ

HardwareSerial rs485(2);  // ใช้ Serial2
ModbusRTU modbus;         // สร้างออบเจกต์ Modbus

// ตัวแปรเก็บค่าจาก GPS
float latitude = 13.7563;  // ตัวอย่างค่าจาก GPS
float longitude = 100.5018;
float cog = 123.45;        // ค่า COG

// ฟังก์ชันให้ Master อ่านค่าจาก Register
bool ReadRegisters(Modbus::ResultCode event, uint16_t transactionId, void* data) {
    return true; // ใช้เมื่อ Master ต้องการอ่านค่า ไม่มีการเปลี่ยนแปลงค่า
}

void setup() {
    Serial.begin(115200);  // เปิด Serial Monitor
    rs485.begin(9600, SERIAL_8N1, RXD2, TXD2);  // เริ่มต้น RS485
    modbus.begin(&rs485, RE_DE);  // เริ่ม Modbus RTU และใช้ RE_DE ควบคุมโหมด

    modbus.slave(1);  // กำหนด ESP32 เป็น Slave ID = 1

    // กำหนดค่าลงใน Holding Registers (เริ่มจากที่อยู่ 0)
    modbus.addHreg(0, (uint16_t)(latitude * 10000));  // คูณ 10000 เพื่อแปลง float เป็น int
    modbus.addHreg(1, (uint16_t)(longitude * 10000));
    modbus.addHreg(2, (uint16_t)(cog * 10));  // คูณ 10 เพื่อเพิ่มความละเอียดของ COG
}

void loop() {
    modbus.task();  // ดำเนินการ Modbus

    // อัปเดตค่าจาก GPS (จำลองค่าตัวอย่าง)
    modbus.Hreg(0, (uint16_t)(latitude * 10000));  
    modbus.Hreg(1, (uint16_t)(longitude * 10000));
    modbus.Hreg(2, (uint16_t)(cog * 10));

    delay(1000);
}

:small_blue_diamond: วิธีตั้งค่า HMI ให้รับค่าจาก ESP32

ใน HMI คุณต้อง:

  1. ตั้งค่า Communication ProtocolModbus RTU
  2. ตั้งค่า Baudrate9600
  3. ตั้งค่า Device ID1
  4. ตั้งค่า Register Address ตามที่กำหนดใน ESP32:
  • ที่อยู่ 0 → Latitude (เก็บเป็น Int คูณ 10000)
  • ที่อยู่ 1 → Longitude (เก็บเป็น Int คูณ 10000)
  • ที่อยู่ 2 → COG (เก็บเป็น Int คูณ 10)
  1. ใช้ Data Type เป็น Unsigned INT16

:small_blue_diamond: อธิบายโค้ด:

  • ใช้ไลบรารี ModbusRTU ควบคุม Modbus RTU
  • ใช้ modbus.slave(1); เพื่อกำหนดให้ ESP32 เป็น Slave ID = 1
  • ใช้ modbus.addHreg() เพื่อกำหนด Holding Register สำหรับค่า GPS
  • ใช้ modbus.Hreg() อัปเดตค่าที่อ่านได้จาก GPS ไปยัง Modbus Register
  • ใช้ GPIO4 (RE_DE) ควบคุมทิศทางของ MAX485 (ส่งหรือรับ)

ถ่ายรูปการต่อมาดูด้วยยิ่งดีครับ