[Modbus]
Modbus86 Slave 能使 86Duino 模擬成 Modbus Slave 節點,在通道上接收指令並執行回呼函式。
範例
啟用 RS485 並使用 Modbus RTU 作為通訊方式的 Slave 裝置範例。
#include <Modbus86.h> ModbusSlave bus; ModbusSlaveNode node; uint32_t command = 0; uint32_t lasttime = 0; uint8_t read_holding_registers( uint8_t function, uint16_t address, uint16_t length) { for (int i = address; i < address + length; i++) { if (i == 16) node.writeHoldingRegister(i, command & 0xFFFF); else if (i == 17) node.writeHoldingRegister(i, (command >> 16) & 0xFFFF); } return MODBUS_SUCCESS; } uint8_t read_input_registers( uint8_t function, uint16_t address, uint16_t length) { int sensorPin = A2; if (address <= 2 && address + length > 2) node.writeInputRegister(2, analogRead(sensorPin)); return MODBUS_SUCCESS; } uint8_t write_multiple_registers( uint8_t function, uint16_t address, uint16_t length) { int i; for (i = address; i < address + length; i++) { if (i == 16) command = (command & 0xFFFF0000) | node.readHoldingRegister(i); else if (i == 17) command = (command & 0x0000FFFF) | (node.readHoldingRegister(i) << 16); } return MODBUS_SUCCESS; } uint8_t write_single_coil( uint8_t function, uint16_t address, uint16_t length) { uint16_t value; if (address == 0) { node.readCoil(address, 1, &value); if (value) digitalWrite(LED_BUILTIN, HIGH); else digitalWrite(LED_BUILTIN, LOW); } return MODBUS_SUCCESS; } void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial485.begin(115200); /* Modbus RTU Mode via RS485. */ bus.begin(MODBUS_RTU, Serial485); /* Slave node with ID 11. */ node.attach(11, bus); /* Set the callback function of Read Holding Registers (0x03). */ node.cbFunc[MODBUS_CB_READ_HOLDING_REGISTERS] = read_holding_registers; /* Set the callback function of Read Input Registers (0x04). */ node.cbFunc[MODBUS_CB_READ_INPUT_REGISTERS] = read_input_registers; /* Set the callback function of Write Single Coil (0x05). */ node.cbFunc[MODBUS_CB_WRITE_SINGLE_COIL] = write_single_coil; /* Set the callback function of Write Multiple Registers (0x10). */ node.cbFunc[MODBUS_CB_WRITE_MULTIPLE_REGISTERS] = write_multiple_registers; } void loop() { uint32_t now; node.poll(); now = millis(); if (now - lasttime > 500) { lasttime = now; Serial.print("commnad = "); Serial.println(command); } }
啟用 Ethernet 並使用 Modbus TCP 作為通訊方式的 Slave 裝置範例。
#include <Ethernet.h> #include <Modbus86.h> ModbusSlave bus; ModbusSlaveNode node; byte mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; IPAddress localIp(192,168,1,102); uint32_t command = 0; uint32_t lasttime = 0; uint8_t read_holding_registers( uint8_t function, uint16_t address, uint16_t length) { for (int i = address; i < address + length; i++) { if (i == 16) node.writeHoldingRegister(i, command & 0xFFFF); else if (i == 17) node.writeHoldingRegister(i, (command >> 16) & 0xFFFF); } return MODBUS_SUCCESS; } uint8_t read_input_registers( uint8_t function, uint16_t address, uint16_t length) { int sensorPin = A2; if (address <= 2 && address + length > 2) node.writeInputRegister(2, analogRead(sensorPin)); return MODBUS_SUCCESS; } uint8_t write_multiple_registers( uint8_t function, uint16_t address, uint16_t length) { int i; for (i = address; i < address + length; i++) { if (i == 16) command = (command & 0xFFFF0000) | node.readHoldingRegister(i); else if (i == 17) command = (command & 0x0000FFFF) | (node.readHoldingRegister(i) << 16); } return MODBUS_SUCCESS; } uint8_t write_single_coil( uint8_t function, uint16_t address, uint16_t length) { uint16_t value; if (address == 0) { node.readCoil(address, 1, &value); if (value) digitalWrite(LED_BUILTIN, HIGH); else digitalWrite(LED_BUILTIN, LOW); } return MODBUS_SUCCESS; } void setup() { pinMode(LED_BUILTIN, OUTPUT); Ethernet.begin(mac, localIp); /* Modbus TCP Mode via Ethernet. */ bus.begin(MODBUS_TCP); /* Slave node initialize. */ node.attach(11, bus); /* Set the callback function of Read Holding Registers (0x03). */ node.cbFunc[MODBUS_CB_READ_HOLDING_REGISTERS] = read_holding_registers; /* Set the callback function of Read Input Registers (0x04). */ node.cbFunc[MODBUS_CB_READ_INPUT_REGISTERS] = read_input_registers; /* Set the callback function of Write Single Coil (0x05). */ node.cbFunc[MODBUS_CB_WRITE_SINGLE_COIL] = write_single_coil; /* Set the callback function of Write Multiple Registers (0x10). */ node.cbFunc[MODBUS_CB_WRITE_MULTIPLE_REGISTERS] = write_multiple_registers; } void loop() { uint32_t now; node.poll(); now = millis(); if (now - lasttime > 500) { lasttime = now; Serial.print("commnad = "); Serial.println(command); } }
函式庫參考主頁面
86Duino 參考的文本是根據 Creative Commons Attribution-ShareAlike 3.0 License,部分文本是從 the Arduino reference 修改的。 參考中的代碼示例已發佈到公共領域。