MODBUS
https://en.wikipedia.org/wiki/Modbus
Implements MODBUS-RTU protocols.
Can use this directly, but generally preferable to create custom Device and Request classes. See R421A Relay Boards for an example.
Device properties include:
- Address
The address of a modbus slave. Modbus docs. call this the slave ID.
- Node
Represents something a slave device does. Modbus relay boards have one node for each output it controls.
- Node ID
The channel a node lives on. For the R421Axx relay boards this is the address or channel number. In a modbus transaction this is the address field.
For efficiency, nodes aren’t implemented as objects, just identifiers used by a Device / Controller. Nodes can be controlled using generic commands such as ‘open’, ‘close’, ‘toggle’, etc.
-
namespace Modbus
Modbus/ADU.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/Debug.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/Device.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/Exception.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/Function.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/GenericRequest.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/PDU.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/Request.h
Created on: 1 May 2018
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Modbus/Slave.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Debug print support, outputs contents of packet
Enums
-
enum class Exception
Modbus exception codes returned in response packets.
Values:
-
enumerator Success
No exception, transaction completed normally.
-
enumerator IllegalFunction
Function not allowed/supported/implemented, or device in wrong state to process request.
For example, an unconfigured device may be unable to return register values.
-
enumerator IllegalDataAddress
Data address not allowed.
More specifically, the combination of reference number and transfer length is invalid. For a controller with 100 registers, the ADU addresses the first register as 0, and the last one as 99.
If a request is submitted with a starting register address of 96 and a quantity of registers of 4, then this request will successfully operate (address-wise at least) on registers 96, 97, 98, 99.
If a request is submitted with a starting register address of 96 and a quantity of registers of 5, then this request will fail with Exception Code 0x02 “Illegal Data Address” since it attempts to operate on registers 96, 97, 98, 99 and 100, and there is no register with address 100.
-
enumerator IllegalDataValue
Data value not allowed.
This indicates a fault in the structure of the remainder of a complex request, such as that the implied length is incorrect. It specifically does NOT mean that a data item submitted for storage in a register has a value outside the expectation of the application program, since the MODBUS protocol is unaware of the significance of any particular value of any particular register.
-
enumerator SlaveDeviceFailure
Protocol slave device failure exception.
An unrecoverable error occurred while the server (or slave) was attempting to perform the requested action.
-
enumerator Success
Functions
-
ErrorCode readRequest(RS485::Controller &controller, ADU &adu)
-
void sendResponse(RS485::Controller &controller, ADU &adu)
-
struct ADU
- #include <ADU.h>
Prepare outgoing packet
The
slaveAddress
andpdu
fields must be correctly initialised.- retval size_t:
Size of ADU, 0 on error
Parse a received packet
- param receivedSize:
How much data was received
- retval ErrorCode:
Result of parsing
-
class Device : public IO::RS485::Device
- #include <Device.h>
A virtual device, represents a modbus slave device.
Actual devices must implement:
callback()
fillRequestData()
Subclassed by IO::Modbus::NT18B07::Device, IO::Modbus::R421A::Device, IO::Modbus::RID35::Device, IO::Modbus::STM8Relay::Device, IO::Modbus::STS::Fan::Device
Public Functions
-
virtual IO::Request *createRequest() override
Create a request object for this device.
- Return values:
Request* – Caller must destroy or submit the request
-
virtual void handleEvent(IO::Request *request, Event event) override
Implementations may override this method to customise event handling.
-
class Factory : public IO::RS485::Device::FactoryTemplate<Device>
- #include <Device.h>
Public Functions
-
inline virtual const FlashString &deviceClass() const override
Return the Device class name, e.g. ‘r421a’.
-
inline virtual const FlashString &deviceClass() const override
-
struct PDU
- #include <PDU.h>
Protocol Data Unit.
Content is independent of the communication layer. Structure does NOT represent over-the-wire format as packing issues make handling PDU::Data awkward. Therefore, the other fields are unaligned and adjusted as required when sent over the wire.
byteCount
fieldSome functions with a
byteCount
field are marked ascalculated
. This means it doesn’t need to be set when constructing requests or responses, and will be filled in later based on the values of other fields.In other cases, a
setCount
method is provided to help ensure the byteCount field is set correctly.Get PDU size based on content
Calculation uses byte count so doesn’t access any 16-bit fields
-
union Data
- #include <PDU.h>
Public Members
-
uint8_t exceptionCode
-
ReadDiscreteInputs readDiscreteInputs
-
ReadRegisters readHoldingRegisters
-
ReadRegisters readInputRegisters
-
WriteSingleCoil writeSingleCoil
-
WriteSingleRegister writeSingleRegister
-
ReadExceptionStatus readExceptionStatus
-
GetComEventCounter getComEventCounter
-
GetComEventLog getComEventLog
-
WriteMultipleCoils writeMultipleCoils
-
WriteMultipleRegisters writeMultipleRegisters
-
ReportServerId reportServerId
-
MaskWriteRegister maskWriteRegister
-
ReadWriteMultipleRegisters readWriteMultipleRegisters
-
union GetComEventLog
- #include <PDU.h>
-
union ReadCoils
- #include <PDU.h>
-
struct Request
- #include <PDU.h>
-
struct Response
- #include <PDU.h>
-
struct Request
-
union ReportServerId
- #include <PDU.h>
-
uint8_t exceptionCode
-
union Data
-
class Request : public IO::RS485::Request
- #include <Request.h>
Subclassed by IO::Modbus::GenericRequest, IO::Modbus::NT18B07::Request, IO::Modbus::R421A::Request, IO::Modbus::RID35::Request, IO::Modbus::STM8Relay::Request, IO::Modbus::STS::Fan::Request
-
namespace NT18B07
Modbus/NT18B07/Device.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Rayleigh Instruments RI-D35 energy meter
Device registers are read-only. The Node ID corresponds to the register address.
Modbus/NT18B07/Request.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Typedefs
-
using TempData = int16_t[channelCount]
Variables
-
const size_t channelCount = {7}
-
class Device : public IO::Modbus::Device
- #include <Device.h>
Public Functions
-
virtual IO::Request *createRequest() override
Create a request object for this device.
- Return values:
Request* – Caller must destroy or submit the request
-
int16_t getIntValue(uint8_t channel) const
Get temperature value in 0.1C increments (avoids floating point)
-
inline virtual uint16_t maxNodes() const override
Determine maximum number of nodes supported by the device.
- Return values:
uint16_t – 0 if device doesn’t support nodes
-
class Factory : public IO::RS485::Device::FactoryTemplate<Device>
- #include <Device.h>
Public Functions
-
inline virtual const FlashString &deviceClass() const override
Return the Device class name, e.g. ‘r421a’.
-
inline virtual const FlashString &deviceClass() const override
-
virtual IO::Request *createRequest() override
-
using TempData = int16_t[channelCount]
-
namespace R421A
Modbus/R421A/Device.h
Created on: 1 May 2018
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
R421A08 modbus 8-channel relay board
Channels are numbered 1 - 8. This is the 16-bit address field in a request.
To simplify operation we use a bitmask to specify relay states. We use the channel number directly so values can range between 0x0001 and 0x01FE
The query command returns a range of states, but other commands work with only a single channel. We therefore implement a mechanism to iterate through all requested channels using the same request.
There is a similar 4-channel board but with no markings and (as yet) no documentation. However all commands appear to work so a designation of R421A04 seems appropriate. Some typos in the 8-channel datasheet indicate that it was adapted from that of a 4-channel version.
R421A04 - 32 addresses set with DIP1-5, DIP6 ON for RTU mode R421A08 - 64 addresses set with DIP1-6, RTU mode only
Modbus/R421A/Request.h
Created on: 1 May 2018
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
-
struct StateMask
- #include <Device.h>
Tracks state of multiple relays.
Public Members
-
BitSet32 channelMask
Identifies valid channels.
-
BitSet32 channelMask
-
class Device : public IO::Modbus::Device
- #include <Device.h>
Public Functions
-
virtual IO::Request *createRequest() override
Create a request object for this device.
- Return values:
Request* – Caller must destroy or submit the request
-
inline virtual DevNode::ID nodeIdMin() const override
Get minimum valid Node ID for this device.
Typically devices have a contiguous valid range of node IDs
-
inline virtual uint16_t maxNodes() const override
Determine maximum number of nodes supported by the device.
- Return values:
uint16_t – 0 if device doesn’t support nodes
-
virtual DevNode::States getNodeStates(DevNode node) const override
Return the current set of states for all nodes controlled by this device.
Used to determine if, say, all nodes are ON, OFF or a combination.
-
virtual void handleEvent(IO::Request *request, Event event) override
Implementations may override this method to customise event handling.
-
class Factory : public IO::RS485::Device::FactoryTemplate<Device>
- #include <Device.h>
Public Functions
-
inline virtual const FlashString &deviceClass() const override
Return the Device class name, e.g. ‘r421a’.
-
inline virtual const FlashString &deviceClass() const override
-
virtual IO::Request *createRequest() override
-
class Request : public IO::Modbus::Request
- #include <Request.h>
Public Functions
-
virtual ErrorCode parseJson(JsonObjectConst json) override
Fill this request from a JSON description.
-
virtual void getJson(JsonObject json) const override
Get result of a completed request in JSON format.
-
virtual bool setNode(DevNode node) override
If nodes are supported, implement this method.
/
/**
-
virtual DevNode::States getNodeStates(DevNode node) override
Query node status from response.
-
virtual ErrorCode parseJson(JsonObjectConst json) override
-
struct StateMask
-
namespace RID35
Modbus/RID35/Request.h
Created on: 24 March 2022
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Enums
Variables
-
constexpr uint16_t stdRegBase = 0x01
-
constexpr uint16_t ovfRegBase = 0x96
-
constexpr size_t registerCount = stdRegCount + ovfRegCount
-
class Device : public IO::Modbus::Device
- #include <Device.h>
Public Functions
-
virtual IO::Request *createRequest() override
Create a request object for this device.
- Return values:
Request* – Caller must destroy or submit the request
-
class Factory : public IO::RS485::Device::FactoryTemplate<Device>
- #include <Device.h>
Public Functions
-
inline virtual const FlashString &deviceClass() const override
Return the Device class name, e.g. ‘r421a’.
-
inline virtual const FlashString &deviceClass() const override
-
virtual IO::Request *createRequest() override
-
constexpr uint16_t stdRegBase = 0x01
-
namespace STM8Relay
Modbus/STM8Relay/Device.h
Created on: 24 June 2022
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
STM8S103 modbus relay board
4-channel relay boards with optocouplers and digital inputs. Advertised as using STM8S103 microcontroller, but no model number. Relays controlled using Modbus ‘coil’ commands. Digital inputs read as ‘discrete inputs’. Connected directly to 3.3v microcontroller. Grounding pin sets bit.
Modbus/STM8Relay/Request.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
-
struct StateMask
- #include <Device.h>
Tracks state of multiple relays.
Public Members
-
BitSet32 channelMask
Identifies valid channels.
-
BitSet32 channelMask
-
class Device : public IO::Modbus::Device
- #include <Device.h>
Public Functions
-
virtual IO::Request *createRequest() override
Create a request object for this device.
- Return values:
Request* – Caller must destroy or submit the request
-
inline virtual DevNode::ID nodeIdMin() const override
Get minimum valid Node ID for this device.
Typically devices have a contiguous valid range of node IDs
-
inline virtual uint16_t maxNodes() const override
Determine maximum number of nodes supported by the device.
- Return values:
uint16_t – 0 if device doesn’t support nodes
-
virtual DevNode::States getNodeStates(DevNode node) const override
Return the current set of states for all nodes controlled by this device.
Used to determine if, say, all nodes are ON, OFF or a combination.
-
virtual void handleEvent(IO::Request *request, Event event) override
Implementations may override this method to customise event handling.
-
class Factory : public IO::RS485::Device::FactoryTemplate<Device>
- #include <Device.h>
Public Functions
-
inline virtual const FlashString &deviceClass() const override
Return the Device class name, e.g. ‘r421a’.
-
inline virtual const FlashString &deviceClass() const override
-
virtual IO::Request *createRequest() override
-
class Request : public IO::Modbus::Request
- #include <Request.h>
Public Functions
-
virtual ErrorCode parseJson(JsonObjectConst json) override
Fill this request from a JSON description.
-
virtual void getJson(JsonObject json) const override
Get result of a completed request in JSON format.
-
virtual bool setNode(DevNode node) override
If nodes are supported, implement this method.
/
/**
-
virtual DevNode::States getNodeStates(DevNode node) override
Query node status from response.
-
virtual ErrorCode parseJson(JsonObjectConst json) override
-
struct StateMask
-
namespace STS
-
namespace Fan
Modbus/STS/Fan/Device.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
STS Fan Controller - see samples/Fan
Modbus/STS/Fan/Request.h
Copyright 2022 mikee47 mike@sillyhouse.net
This file is part of the IOControl Library
This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 or later.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this library. If not, see https://www.gnu.org/licenses/.
Variables
-
const size_t channelCount = {3}
-
struct FanData
- #include <Device.h>
-
class Device : public IO::Modbus::Device
- #include <Device.h>
Public Functions
-
virtual IO::Request *createRequest() override
Create a request object for this device.
- Return values:
Request* – Caller must destroy or submit the request
-
inline virtual uint16_t maxNodes() const override
Determine maximum number of nodes supported by the device.
- Return values:
uint16_t – 0 if device doesn’t support nodes
-
class Factory : public IO::RS485::Device::FactoryTemplate<Device>
- #include <Device.h>
Public Functions
-
inline virtual const FlashString &deviceClass() const override
Return the Device class name, e.g. ‘r421a’.
-
inline virtual const FlashString &deviceClass() const override
-
virtual IO::Request *createRequest() override
-
class Request : public IO::Modbus::Request
- #include <Request.h>
Public Functions
-
inline virtual bool setNode(DevNode node) override
If nodes are supported, implement this method.
/
/**
-
inline virtual bool setValue(int value) override
If nodes support values, implement this method.
-
virtual ErrorCode callback(PDU &pdu) override
Process a received PDU.
- Parameters:
pdu –
- Return values:
ErrorCode – If request is re-submitted, return Error::pending, otherwise request will be completed with given error.
-
virtual void getJson(JsonObject json) const override
Get result of a completed request in JSON format.
-
inline virtual bool setNode(DevNode node) override
-
const size_t channelCount = {3}
-
namespace Fan
-
enum class Exception