Skip to content

Commit 65b578f

Browse files
add examples file, outsourced from usage
1 parent 25a3bb8 commit 65b578f

File tree

1 file changed

+263
-0
lines changed

1 file changed

+263
-0
lines changed

docs/EXAMPLES.md

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# Examples
2+
3+
Usage examples of this `micropython-modbus` library
4+
5+
---------------
6+
7+
## RTU
8+
9+
```{note}
10+
Check the port specific
11+
[MicroPython UART documentation](https://docs.micropython.org/en/latest/library/machine.UART.html)
12+
for further details.
13+
14+
A Raspberry Pi Pico e.g. requires the UART pins as a tuple of `Pin`, like
15+
`rtu_pins = (Pin(4), Pin(5))` and the corresponding `uart_id` for those pins,
16+
whereas ESP32 boards can use almost any pin for UART communication as shown in
17+
the following examples and shall be given as `rtu_pins = (25, 26)`. If
18+
necessary, the `uart_id` parameter may has to be adapted to the pins used.
19+
```
20+
21+
### Client/Slave
22+
23+
With this example the device is acting as client (slave) and providing data via
24+
RTU (serial/UART) to a requesting host device.
25+
26+
```python
27+
from umodbus.serial import ModbusRTU
28+
29+
# RTU Client/Slave setup
30+
# the following example is for an ESP32
31+
rtu_pins = (25, 26) # (TX, RX)
32+
slave_addr = 10 # address on bus as client
33+
34+
client = ModbusRTU(
35+
addr=slave_addr, # address on bus
36+
pins=rtu_pins, # given as tuple (TX, RX)
37+
# baudrate=9600, # optional, default 9600
38+
# data_bits=8, # optional, default 8
39+
# stop_bits=1, # optional, default 1
40+
# parity=None, # optional, default None
41+
# ctrl_pin=12, # optional, control DE/RE
42+
# uart_id=1 # optional, see port specific documentation
43+
)
44+
45+
register_definitions = {
46+
"COILS": {
47+
"EXAMPLE_COIL": {
48+
"register": 123,
49+
"len": 1,
50+
"val": 1
51+
}
52+
},
53+
"HREGS": {
54+
"EXAMPLE_HREG": {
55+
"register": 93,
56+
"len": 1,
57+
"val": 19
58+
}
59+
},
60+
"ISTS": {
61+
"EXAMPLE_ISTS": {
62+
"register": 67,
63+
"len": 1,
64+
"val": 0
65+
}
66+
},
67+
"IREGS": {
68+
"EXAMPLE_IREG": {
69+
"register": 10,
70+
"len": 1,
71+
"val": 60001
72+
}
73+
}
74+
}
75+
76+
# use the defined values of each register type provided by register_definitions
77+
client.setup_registers(registers=register_definitions)
78+
79+
while True:
80+
try:
81+
result = client.process()
82+
except KeyboardInterrupt:
83+
print('KeyboardInterrupt, stopping RTU client...')
84+
break
85+
except Exception as e:
86+
print('Exception during execution: {}'.format(e))
87+
```
88+
89+
### Host/Master
90+
91+
With this example the device is acting as host (master) and requesting on or
92+
setting data at a RTU (serial/UART) client/slave.
93+
94+
```python
95+
from umodbus.serial import Serial as ModbusRTUMaster
96+
97+
# RTU Host/Master setup
98+
# the following example is for an ESP32
99+
rtu_pins = (25, 26) # (TX, RX)
100+
101+
host = ModbusRTUMaster(
102+
pins=rtu_pins, # given as tuple (TX, RX)
103+
# baudrate=9600, # optional, default 9600
104+
# data_bits=8, # optional, default 8
105+
# stop_bits=1, # optional, default 1
106+
# parity=None, # optional, default None
107+
# ctrl_pin=12, # optional, control DE/RE
108+
# uart_id=1 # optional, see port specific documentation
109+
)
110+
111+
coil_status = host.read_coils(slave_addr=10, starting_addr=123, coil_qty=1)
112+
print('Status of coil 123: {}'.format(coil_status))
113+
```
114+
115+
## TCP
116+
117+
### Client/Slave
118+
119+
With this example the device is acting as client (slave) and providing data via
120+
TCP (socket) to a requesting host device.
121+
122+
```python
123+
import network
124+
from umodbus.tcp import ModbusTCP
125+
126+
# network connections shall be made here, check the MicroPython port specific
127+
# documentation for connecting to or creating a network
128+
129+
# TCP Client/Slave setup
130+
# set IP address of this MicroPython device explicitly
131+
# local_ip = '192.168.4.1' # IP address
132+
# or get it from the system after a connection to the network has been made
133+
# it is not the task of this lib to provide a detailed explanation for this
134+
station = network.WLAN(network.STA_IF)
135+
local_ip = station.ifconfig()[0]
136+
tcp_port = 502 # port to listen for requests/providing data
137+
138+
client = ModbusTCP()
139+
140+
# check whether client has been bound to an IP and a port
141+
if not client.get_bound_status():
142+
client.bind(local_ip=local_ip, local_port=tcp_port)
143+
144+
register_definitions = {
145+
"COILS": {
146+
"EXAMPLE_COIL": {
147+
"register": 123,
148+
"len": 1,
149+
"val": 1
150+
}
151+
},
152+
"HREGS": {
153+
"EXAMPLE_HREG": {
154+
"register": 93,
155+
"len": 1,
156+
"val": 19
157+
}
158+
},
159+
"ISTS": {
160+
"EXAMPLE_ISTS": {
161+
"register": 67,
162+
"len": 1,
163+
"val": 0
164+
}
165+
},
166+
"IREGS": {
167+
"EXAMPLE_IREG": {
168+
"register": 10,
169+
"len": 1,
170+
"val": 60001
171+
}
172+
}
173+
}
174+
175+
# use the defined values of each register type provided by register_definitions
176+
client.setup_registers(registers=register_definitions)
177+
178+
while True:
179+
try:
180+
result = client.process()
181+
except KeyboardInterrupt:
182+
print('KeyboardInterrupt, stopping TCP client...')
183+
break
184+
except Exception as e:
185+
print('Exception during execution: {}'.format(e))
186+
```
187+
188+
### Host/Master
189+
190+
With this example the device is acting as host (master) and requesting on or
191+
setting data at a TCP (socket) client/slave.
192+
193+
```python
194+
from umodbus.tcp import TCP as ModbusTCPMaster
195+
196+
# valid network connections shall be made here
197+
198+
# RTU Host/Master setup
199+
slave_tcp_port = 502 # port to send request on
200+
slave_ip = '192.168.178.69' # IP address of client, to be adjusted
201+
202+
host = ModbusTCPMaster(
203+
slave_ip=slave_ip,
204+
slave_port=slave_tcp_port,
205+
# timeout=5.0 # optional, timeout in seconds, default 5.0
206+
)
207+
208+
coil_status = host.read_coils(slave_addr=10, starting_addr=123, coil_qty=1)
209+
print('Status of coil 123: {}'.format(coil_status))
210+
```
211+
212+
## Callbacks
213+
214+
Callbacks can be registered to be executed *after* setting a register with
215+
`on_set_cb` or to be executed *before* getting a register with `on_get_cb`.
216+
217+
```{note}
218+
Getter callbacks can be registered for all registers with the `on_get_cb`
219+
parameter whereas the `on_set_cb` parameter is only available for coils and
220+
holding registers as only those can be set by a external host.
221+
```
222+
223+
```{eval-rst}
224+
.. warning::
225+
Keep the get callback actions as short as possible to avoid potential
226+
request timeouts due to a to long processing time.
227+
```
228+
229+
```python
230+
def my_coil_set_cb(reg_type, address, val):
231+
print('Custom callback, called on setting {} at {} to: {}'.
232+
format(reg_type, address, val))
233+
234+
235+
def my_coil_get_cb(reg_type, address, val):
236+
print('Custom callback, called on getting {} at {}, currently: {}'.
237+
format(reg_type, address, val))
238+
239+
240+
# define some registers, for simplicity only a single coil is used
241+
register_definitions = {
242+
"COILS": {
243+
"EXAMPLE_COIL": {
244+
"register": 123,
245+
"len": 1,
246+
"val": 1,
247+
"on_get_cb": my_coil_get_cb,
248+
"on_set_cb": my_coil_set_cb
249+
}
250+
}
251+
}
252+
253+
# use the defined values of each register type provided by register_definitions
254+
client.setup_registers(registers=register_definitions)
255+
256+
# callbacks can also be defined after a register setup has been performed
257+
client.add_coil(
258+
address=123,
259+
value=bool(1),
260+
on_set_cb=my_coil_set_cb,
261+
on_get_cb=my_coil_get_cb
262+
)
263+
```

0 commit comments

Comments
 (0)