Meadow.Modbus
is designed to be cross-platform, and does not require the use of Meadow.Core
, meaning that it can be used in pretty much any modern .NET application.
It has been verified on hardware on the following platforms:
Feature | Platform | Notes |
---|---|---|
Modbus RTU Client | Meadow Feather F7 | b6.2 or later |
Modbus RTU Client | Windows 10 | .NET 6 |
Modbus RTU Client | Raspberry Pi, Raspbian Buster | .NET 5, .NET 6 and Mono |
Modbus TCP Client | Windows 10 | .NET 6 |
Modbus TCP Client | Raspberry Pi, Raspbian Buster | .NET 5, .NET 6 and Mono |
Modbus TCP Server | Windows 10 | .NET 6 |
This sample assumes you have a Thermostat connected over RS485 and configured to be at Modbus address 201.
Create a ModbusRtuClient instance, passing in the SerialPort for COM4 and DigitalOutputPort used for the enable.
var port = Device.CreateSerialPort(Device.SerialPortNames.Com4, 19200, 8, Meadow.Hardware.Parity.None, Meadow.Hardware.StopBits.One);
port.WriteTimeout = port.ReadTimeout = TimeSpan.FromSeconds(5);
var enable = Device.CreateDigitalOutputPort(Device.Pins.D02, false);
var client = new ModbusRtuClient(port, enable);
The Temco TSTAT8 uses holding registers for all of its interfacing. It has a lot of registers for reading or controlling just about every aspect of its operation. For our purposes we’ll only look at two of them: current temperature and current occupied setpoint. Since Modbus holding registers are ushort values, but the actual temperature and setpoint are in tenths of a degree, we have to do scaling in our application. For example a current temperature register reading of 721 equates to a temeprature of 72.1 degrees. Similarly if we want to set a setpoint of 69.5 degrees, we write 695.
To read the current temperature and output it to the console every 5 seconds, we can use a loop like this:
byte address = 201;
ushort tempRegister = 121; // current temp, in tenths of a degree
while (true)
{
registers = await client.ReadHoldingRegisters(address, tempRegister, 1);
Console.WriteLine($"Current temp: {registers[0] / 10f}");
await Task.Delay(TimeSpan.FromSeconds(5));
}
Writing to a holding register is similar to the read shown above. Below is code that reads the setpoint, changes it with a write, then re-reads to verify the change:
byte address = 201;
ushort setPointRegister = 345; // occupied setpoint, in tenths of a degree
Console.WriteLine($"Reading setpoint holding register...");
var registers = await client.ReadHoldingRegisters(address, setPointRegister, 1);
Console.WriteLine($"Current set point: {registers[0] / 10f}");
var r = new Random();
var delta = r.Next(-20, 20);
var newSetpoint = (ushort)(registers[0] + delta);
Console.WriteLine($"Changing set point to: {newSetpoint / 10f}...");
await client.WriteHoldingRegister(address, setPointRegister, newSetpoint);
Console.WriteLine($"Re-reading thermostat holding registers...");
registers = await client.ReadHoldingRegisters(address, setPointRegister, 1);
Console.WriteLine($"Current set point: {registers[0] / 10f}");
Coming Soon!
Coming Soon!
Apache 2.0
See LICENSE File