pdf-icon

Arduino Quick Start

StamPLC Modbus Slave

The StamPLC driver library integrates Modbus Slave functionality. After a simple initialization of the device, it can function as a slave device and easily connect to a Modbus bus via the PWR-485 interface. Other devices can also conveniently control the StamPLC's relays and read input signal states.

Example Program

StamPLC Modbus Slave

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/*
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
#include <Arduino.h>
#include <M5StamPLC.h>
void setup()
{
/* Enable Modbus */
auto config = M5StamPLC.config();
config.enableModbusSlave = true;
config.modbusBaudRate = 115200;
config.modbusSlaveId = 1;
config.enableCan = true;
M5StamPLC.config(config);
/* Init M5StamPLC */
M5StamPLC.begin();
}
void loop()
{
/* Now you can control StamPLC via Modbus RS485 */
/*
* Modbus Slave Configuration for M5StamPLC
* =======================================
*
* Register Map:
* -------------
* 1. Coils (Read/Write)
* - Address 0: Relay 1 output (true/false)
* - Address 1: Relay 2 output (true/false)
* - Address 2: Relay 3 output (true/false)
* - Address 3: Relay 4 output (true/false)
*
* 2. Input Registers (Read-only)
* - Address 0-7: Inputs (true/false) - 8 registers
* - Address 8-9: Temperature (FLOAT32) - 2 registers
* - Address 10-11: Bus Voltage (FLOAT32) - 2 registers
* - Address 12-13: Shunt Current (FLOAT32) - 2 registers
*
* Note: FLOAT32 values use 2 consecutive registers (32 bits total)
*/
delay(1000);
}

Modbus Master

Use any ESP32 main controller device, along with Unit RS485, to implement a Modbus Master. Then control StamPLC through the PWR-485 interface.
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>
RS485Class RS485(Serial2, 39, 0, 46, -1);
uint8_t slave_id = 1;
// Parse two 16-bit registers into a FLOAT32
float parseFloat(uint16_t high, uint16_t low)
{
union {
uint32_t i;
float f;
} value;
value.i = ((uint32_t)high << 16) | low;
return value.f;
}
void setup()
{
Serial.begin(115200);
delay(2000);
if (!ModbusRTUClient.begin(115200, SERIAL_8N1)) {
Serial.println("Failed to start Modbus RTU Client");
while (1);
}
}
void loop()
{
/* Now you can control StamPLC via Modbus RS485 */
/*
* Modbus Slave Configuration for M5StamPLC
* =======================================
*
* Register Map:
* -------------
* 1. Coils (Read/Write)
* - Address 0: Relay 1 output (true/false)
* - Address 1: Relay 2 output (true/false)
* - Address 2: Relay 3 output (true/false)
* - Address 3: Relay 4 output (true/false)
*
* 2. Input Registers (Read-only)
* - Address 0-7: Inputs (true/false) - 8 registers
* - Address 8-9: Temperature (FLOAT32) - 2 registers
* - Address 10-11: Bus Voltage (FLOAT32) - 2 registers
* - Address 12-13: Shunt Current (FLOAT32) - 2 registers
*
* Note: FLOAT32 values use 2 consecutive registers (32 bits total)
*/
Serial.println("\n--- Reading Modbus Registers ---");
// 1. Control Coils (0x01)
Serial.println("Turning Relays ON:");
for (uint8_t addr = 0; addr < 4; addr++) {
if (ModbusRTUClient.coilWrite(slave_id, addr, 0xFF)) {
Serial.printf("Relay %d ON\n", addr);
} else {
Serial.printf("Failed to turn on Relay %d\n", addr);
}
delay(500);
}
Serial.println("Reading Coils Status:");
for (uint8_t addr = 0; addr < 4; addr++) {
if (ModbusRTUClient.requestFrom(slave_id, COILS, addr, 1)) {
Serial.printf("Relay %d: ", addr);
while (ModbusRTUClient.available()) {
Serial.print(ModbusRTUClient.read(), HEX);
Serial.print(' ');
}
Serial.println();
} else {
Serial.printf("Failed to read Relay %d\n", addr);
}
}
Serial.println("Turning Relays OFF:");
for (uint8_t addr = 0; addr < 4; addr++) {
if (ModbusRTUClient.coilWrite(slave_id, addr, 0x00)) {
Serial.printf("Relay %d OFF\n", addr);
} else {
Serial.printf("Failed to turn off Relay %d\n", addr);
}
delay(500);
}
Serial.println("Reading Coils Status Again:");
for (uint8_t addr = 0; addr < 4; addr++) {
if (ModbusRTUClient.requestFrom(slave_id, COILS, addr, 1)) {
Serial.printf("Relay %d: ", addr);
while (ModbusRTUClient.available()) {
Serial.print(ModbusRTUClient.read(), HEX);
Serial.print(' ');
}
Serial.println();
} else {
Serial.printf("Failed to read Relay %d\n", addr);
}
}
delay(500);
// Read each Input Register section separately
Serial.println("Reading Input Registers:");
uint16_t tempRegisters[2], voltageRegisters[2], currentRegisters[2];
float temperature, busVoltage, shuntCurrent;
if (ModbusRTUClient.requestFrom(slave_id, INPUT_REGISTERS, 8, 2)) {
for (uint8_t i = 0; i < 2; i++) {
tempRegisters[i] = ModbusRTUClient.read();
}
temperature = parseFloat(tempRegisters[0], tempRegisters[1]);
Serial.printf("Temperature: %.2f°C\n", temperature);
} else {
Serial.println("Failed to read Temperature Registers");
}
if (ModbusRTUClient.requestFrom(slave_id, INPUT_REGISTERS, 10, 2)) {
for (uint8_t i = 0; i < 2; i++) {
voltageRegisters[i] = ModbusRTUClient.read();
}
busVoltage = parseFloat(voltageRegisters[0], voltageRegisters[1]);
Serial.printf("Bus Voltage: %.2fV\n", busVoltage);
} else {
Serial.println("Failed to read Bus Voltage Registers");
}
if (ModbusRTUClient.requestFrom(slave_id, INPUT_REGISTERS, 12, 2)) {
for (uint8_t i = 0; i < 2; i++) {
currentRegisters[i] = ModbusRTUClient.read();
}
shuntCurrent = parseFloat(currentRegisters[0], currentRegisters[1]);
Serial.printf("Shunt Current: %.2fA\n", shuntCurrent);
} else {
Serial.println("Failed to read Shunt Current Registers");
}
Serial.printf(">>>>>> Temperature: %.2f°C, Bus Voltage: %.2fV, Shunt Current: %.2fA\n", temperature, busVoltage,
shuntCurrent);
delay(5000);
}
On This Page