Skip to content

Commit 3ef5cba

Browse files
committed
updating readme
1 parent 1fc0bc7 commit 3ef5cba

File tree

1 file changed

+51
-46
lines changed

1 file changed

+51
-46
lines changed

README.md

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,74 @@
11
# Modbus
22
C++ Modbus parsing library.
33

4-
# Setting Up a Slave Device
5-
The focus of this library is to allow for a serializable data types to be exposed over
6-
modbus in a clearer manner. Modbus registers are unsigned 16 bit values. Other data types
7-
need to be translated to these 16 bit values and back. The idea of this library is to use
8-
a user defined data store type that controls access to the underlying data types this is especially
9-
useful for preventing unaligned data accesses.
10-
11-
A slave device is composed of controlled and data stores using C++ templates.
12-
Each slave needs a CoilController, HoldingRegisterController, DiscreteInputController, and an InputRegisterController.
13-
Each of these controls access to a data store.
14-
A simple data store for registers would just be an array of uint16_ts. For a coil or discrete input it would be a bit field.
15-
These basic data stores are available but are less powerful than creating a data store for the data types being used.
16-
The basic controller types are:
17-
18-
using CoilController =
19-
Modbus::CoilController<Modbus::BitFieldDataStore<kCoilCount>>;
20-
using HoldingRegisterController =
4+
## Setting Up a Slave Device
5+
This library facilitates exposing serializable data types over Modbus in a more transparent manner. Modbus registers are 16-bit unsigned integers, and other data types must be translated into these 16-bit values and vice versa. The core concept of the library is to use a user-defined data store type that controls access to the underlying data types. This approach is especially useful for preventing unaligned data access.
6+
7+
A slave device in this library consists of controlled data stores, managed via C++ templates. Each slave device requires a `CoilController`, `HoldingRegisterController`, `DiscreteInputController`, and an `InputRegisterController`, with each controller managing access to a specific data store.
8+
9+
A basic data store for registers might simply be an array of `uint16_t` values, while coils or discrete inputs are typically stored as bit fields. Basic data stores are available, but more complex, user-defined data stores can provide additional flexibility and power.
10+
11+
Example of basic controller types:
12+
13+
```cpp
14+
using CoilController =
15+
Modbus::CoilController<Modbus::BitFieldDataStore<kCoilCount>>;
16+
using HoldingRegisterController =
2117
Modbus::HoldingRegisterController<Modbus::RegisterDataStore<kHoldingRegisterCount>>;
22-
using DiscreteInputController =
23-
Modbus::DiscreteInputController<Modbus::BitFieldDataStore<kDiscreteInputCount>>;
24-
using InputRegisterController =
25-
Modbus::InputRegisterController<Modbus::RegisterDataStore<kInputRegisterCount>>;
18+
using DiscreteInputController =
19+
Modbus::DiscreteInputController<Modbus::BitFieldDataStore<kDiscreteInputCount>>;
20+
using InputRegisterController =
21+
Modbus::InputRegisterController<Modbus::RegisterDataStore<kInputRegisterCount>>;
22+
````
2623

27-
## Specialized Data Stores
28-
Using mapped data stores allows the user to expose the actual data types being used with
29-
the serialization encapsulated.
24+
### Specialized Data Stores
3025

26+
To expose actual data types with the serialization encapsulated, you can use mapped data stores. For instance:
27+
28+
```cpp
3129
using HoldingRegisterController =
3230
Modbus::HoldingRegisterController<Modbus::MappedRegisterDataStore<HoldingRegisters::MemoryMapController>>;
3331
using InputRegisterController =
3432
Modbus::InputRegisterController<Modbus::MappedRegisterDataStore<InputRegisters::MemoryMapController>>;
33+
```
34+
35+
## Protocol Layer
3536

37+
A slave device is managed by a subclass of `ProtocolRtuSlave`. The protocol layer handles:
3638

37-
1. Subclass of ProtocolRtuSlave.
38-
- Timeouts
39-
- When to process packets
40-
- IO device control, this layer puts the recieved characters
41-
into the protocol and transmitting the generated responses
42-
2. Data Stores
43-
- The holding registers, coils, discrete inputs, and input registers are
44-
generalized as data stores. The default store mechanism can be used where
45-
the data store is literal, i.e. all bits and registers are stored
46-
and accessed directly. Other data stores might define a memory map
47-
that accesses system variables. This will lower memory use and remove the
48-
need to update the store or poll on changes.
39+
1. **Timeouts**: Managing the timeout between the master and slave.
40+
2. **Packet Processing**: Determining when to process incoming packets.
41+
3. **IO Device Control**: This layer receives characters and inputs them into the protocol, while also handling the transmission of generated responses.
42+
43+
## Data Stores
44+
45+
The Modbus data types—holding registers, coils, discrete inputs, and input registers—are treated as data stores. By default, the data store mechanism directly stores and accesses all bits and registers. However, it is possible to use specialized data stores that define a memory map to access system variables, which reduces memory usage and eliminates the need for periodic updates or polling.
4946

5047
## Testing With Other Libraries
48+
5149
### Using socat
52-
[socat][1] is an easy way to spoof a serial
53-
connection. A bidirectional pipe is setup allowing two processes
54-
to see the pipe as if it was an attached serial device.
5550

56-
**Use** :
51+
[socat](http://www.dest-unreach.org/socat/) can simulate a serial connection between two processes. It creates a bidirectional pipe, allowing both processes to treat the pipe as if it were a physical serial device.
52+
53+
**Example**:
54+
55+
```bash
5756
socat -d -d -d -x PTY,link=/tmp/ptyp0,raw,echo=0,ispeed=b9600 PTY,link=/tmp/ttyp0,raw,echo=0,ospeed=b9600
57+
```
5858

59-
In this example the pipes are setup at /tmp/ptyp0 and /tmp/ttyp0 running at 9600 baud with some debug info (level set by the number of '-d').
60-
The master is started on one pipe and the slave on another and can be treated as connected hardware.
59+
This command sets up two pipes at `/tmp/ptyp0` and `/tmp/ttyp0` running at 9600 baud with debug information. The master can be started on one pipe, and the slave on another, simulating a connected hardware setup.
6160

6261
### Libmodbus
6362

63+
For more information on the Modbus protocol and a C library implementation, check out [Libmodbus](https://libmodbus.org/).
64+
6465
### PyModbus
6566

66-
[1]: http://www.dest-unreach.org/socat/
67-
[2]: https://libmodbus.org/
68-
[3]: https://github.com/Jacajack/liblightmodbus
69-
[4]: https://github.com/riptideio/pymodbus
67+
PyModbus is a Python library that implements the Modbus protocol. It can be used to test and interface with the C++ slave. More information can be found on [GitHub](https://github.com/riptideio/pymodbus).
68+
69+
## References
70+
71+
+ [socat](http://www.dest-unreach.org/socat/)
72+
+ [Libmodbus](https://libmodbus.org/)
73+
+ [PyModbus GitHub](https://github.com/riptideio/pymodbus)
74+
+ [liblightmodbus](https://github.com/Jacajack/liblightmodbus)

0 commit comments

Comments
 (0)