Skip to content

Commit 1764f41

Browse files
Merge debf453 into eee18c2
2 parents eee18c2 + debf453 commit 1764f41

File tree

12 files changed

+1101
-115
lines changed

12 files changed

+1101
-115
lines changed

changelog.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
<!-- ## [Unreleased] -->
1616

1717
## Released
18+
## [2.1.0] - 2022-12-17
19+
### Added
20+
- Typing hints available for all functions of [umodbus](umodbus), see #27
21+
- Docstrings available for all constants, functions and classes of [umodbus](umodbus/), see #27
22+
- Test for reading more than 8 coils in a row to verify fix of #36
23+
- Test for reading single negative holding register value
24+
- Test for writing multiple coils to verify fix of #22
25+
- Test for writing multiple registers to verify fix of #23
26+
- Usage documentation for coil, discrete inputs, holding register and input register usage
27+
- Modbus TCP IP and port binding can be checked with `is_bound` property in [tcp.py](umodbus/tcp.py)
28+
29+
### Changed
30+
- Reordered modules of API documentation
31+
- `data_as_registers` and `data_as_bits` of [common.py](umodbus/common.py) removed
32+
- Send illegal function code `0x01` if a register other than coil or holding register is requested to be set
33+
- Simplified `_process_write_access` logic of [tcp.py](umodbus/tcp.py)
34+
35+
### Fixed
36+
- Typing hints of function input parameters and return values
37+
- Response data of multiple changed registers (`write_multiple_registers`) is validated with respect to the provided `signed` flag in [serial.py](umodbus/serial.py) and [tcp.py](umodbus/tcp.py), see #23
38+
- Enable reading more than 8 coils in a row, see #36
39+
- Writing multiple coils in TCP, see #22
40+
- Writing multiple registers in TCP, see #23
41+
- Unit test `test_bytes_to_bool` uses MSB and LSB data correctly
42+
1843
## [2.0.0] - 2022-12-03
1944
### Added
2045
- Perform MicroPython based unittests on every `Test` workflow run
@@ -151,8 +176,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
151176
- PEP8 style issues on all files of [`lib/uModbus`](lib/uModbus)
152177

153178
<!-- Links -->
154-
[Unreleased]: https://github.com/brainelectronics/micropython-modbus/compare/2.0.0...develop
179+
[Unreleased]: https://github.com/brainelectronics/micropython-modbus/compare/2.1.0...develop
155180

181+
[2.1.0]: https://github.com/brainelectronics/micropython-modbus/tree/2.1.0
156182
[2.0.0]: https://github.com/brainelectronics/micropython-modbus/tree/2.0.0
157183
[1.2.0]: https://github.com/brainelectronics/micropython-modbus/tree/1.2.0
158184
[1.1.1]: https://github.com/brainelectronics/micropython-modbus/tree/1.1.1

docs/USAGE.md

Lines changed: 259 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,6 @@ config
182182
The output will be a list of 5 elements like `[True, False, False, True, True]`
183183
depending on the actual device coil states of course.
184184

185-
186-
187185
##### Value
188186

189187
The key `val` defines the value of registers to be set on the target/client
@@ -217,6 +215,265 @@ of the register. In case of the PWM output register example of the
217215
[optional range key](#optional-range) the recommended value for this key could
218216
be `percent`.
219217

218+
### Register usage
219+
220+
This section describes the usage of the following available functions
221+
222+
- [0x01 `read_coils`](umodbus.tcp.TCP.read_coils)
223+
- [0x02 `read_discrete_inputs`](umodbus.tcp.TCP.read_discrete_inputs)
224+
- [0x03 `read_holding_registers`](umodbus.tcp.TCP.read_holding_registers)
225+
- [0x04 `read_input_registers`](umodbus.tcp.TCP.read_input_registers)
226+
- [0x05 `write_single_coil`](umodbus.tcp.TCP.write_single_coil)
227+
- [0x06 `write_single_register`](umodbus.tcp.TCP.write_single_register)
228+
- [0x0F `write_multiple_coils`](umodbus.tcp.TCP.write_multiple_coils)
229+
- [0x10 `write_multiple_registers`](umodbus.tcp.TCP.write_multiple_registers)
230+
231+
based on TCP togehter with the latest provided
232+
[examples](https://github.com/brainelectronics/micropython-modbus/tree/develop/examples)
233+
234+
All described functions require a successful setup of a Host communicating
235+
to/with a Client device which is providing the data and accepting the new data.
236+
237+
```python
238+
from umodbus.tcp import TCP as ModbusTCPMaster
239+
240+
slave_tcp_port = 502 # port to listen to
241+
slave_addr = 10 # bus address of client
242+
slave_ip = '192.168.178.69' # IP address, to be adjusted
243+
244+
host = ModbusTCPMaster(
245+
slave_ip=slave_ip,
246+
slave_port=slave_tcp_port,
247+
timeout=5) # optional, default 5
248+
```
249+
250+
#### Coils
251+
252+
Coils represent binary states, which can be get as and set to either `0` (off)
253+
or `1` (on).
254+
255+
##### Read
256+
257+
> The function code `0x01` is used to read from 1 to 2000 contiguous status of
258+
coils in a remote device.
259+
260+
With the function [`read_coils`](umodbus.tcp.TCP.read_coils) a single coil
261+
status can be read.
262+
263+
```python
264+
coil_address = 125
265+
coil_qty = 2
266+
coil_status = host.read_coils(
267+
slave_addr=slave_addr,
268+
starting_addr=coil_address,
269+
coil_qty=coil_qty)
270+
print('Status of COIL {}: {}'.format(coil_address, coil_status))
271+
# Status of COIL 125: [True, False]
272+
```
273+
274+
> :warning: Please be aware of bug
275+
[#35](https://github.com/brainelectronics/micropython-modbus/issues/35). It is
276+
not possible to read a specific position within a configured list of multiple
277+
coils on a MicroPython Modbus TCP client device. Reading coil 126 in the above
278+
example will throw an error. This bug affects only devices using this package.
279+
Other devices work as expected and can be addressed as specified.
280+
281+
##### Write
282+
283+
Coils can be set with `False` or `0` to the `OFF` state and with `True` or `1`
284+
to the `ON` state.
285+
286+
###### Single
287+
288+
> The function code `0x05` is used to write a single output to either `ON` or
289+
`OFF` in a remote device.
290+
291+
With the function [`write_single_coil`](umodbus.tcp.TCP.write_single_coil)
292+
a single coil status can be set.
293+
294+
```python
295+
coil_address = 123
296+
new_coil_val = 0
297+
operation_status = host.write_single_coil(
298+
slave_addr=slave_addr,
299+
output_address=coil_address,
300+
output_value=new_coil_val)
301+
print('Result of setting COIL {}: {}'.format(coil_address, operation_status))
302+
# Result of setting COIL 123: True
303+
```
304+
305+
> :warning: Please be aware of bug
306+
[#15](https://github.com/brainelectronics/micropython-modbus/issues/15). It is
307+
not possible to write to a specific position within a configured list of multiple coils on a MicroPython Modbus TCP client device. This bug affects only
308+
devices using this package. Other devices work as expected and can be addressed
309+
as specified.
310+
311+
###### Multiple
312+
313+
> The function code `0x0F` is used to force each coil in a sequence of coils to
314+
either `ON` or `OFF` in a remote device.
315+
316+
With the function [`write_multiple_coils`](umodbus.tcp.TCP.write_multiple_coils)
317+
multiple coil states can be set at once.
318+
319+
```python
320+
coil_address = 126
321+
new_coil_vals = [1, 1, 0]
322+
operation_status = self._host.write_multiple_coils(
323+
slave_addr=slave_addr,
324+
starting_address=coil_address,
325+
output_values=new_coil_vals)
326+
print('Result of setting COIL {}: {}'.format(coil_address, operation_status))
327+
# Result of setting COIL 126: True
328+
```
329+
330+
> :warning: Please be aware of bug
331+
[#35](https://github.com/brainelectronics/micropython-modbus/issues/35). It is
332+
not possible to write to a specific position within a configured list of multiple coils on a MicroPython Modbus TCP client device. Setting coil 127, which is `1` in the above example will throw an error. This bug affects only
333+
devices using this package. Other devices work as expected and can be addressed
334+
as specified.
335+
336+
#### Discrete inputs
337+
338+
Discrete inputs represent binary states, which can be get as either `0` (off)
339+
or `1` (on). Unlike [coils](#coils), these cannot be set.
340+
341+
##### Read
342+
343+
> The function code `0x02` is used to read from 1 to 2000 contiguous status of
344+
discrete inputs in a remote device.
345+
346+
With the function [`read_discrete_inputs`](umodbus.tcp.TCP.read_discrete_inputs)
347+
discrete inputs can be read.
348+
349+
```python
350+
ist_address = 68
351+
input_qty = 2
352+
input_status = host.read_discrete_inputs(
353+
slave_addr=slave_addr,
354+
starting_addr=ist_address,
355+
input_qty=input_qty)
356+
print('Status of IST {}: {}'.format(ist_address, input_status))
357+
# Status of IST 68: [True, False]
358+
```
359+
360+
#### Holding registers
361+
362+
Holding registers can be get as and set to any value between `0` and `65535`.
363+
If supported by the client device, data can be marked as signed values to
364+
represent `-32768` through `32767`.
365+
366+
##### Read
367+
368+
> The function code `0x03` is used to read the contents of a contiguous block
369+
of holding registers in a remote device.
370+
371+
With the function
372+
[`read_holding_registers`](umodbus.tcp.TCP.read_holding_registers) a single
373+
holding register can be read.
374+
375+
```python
376+
hreg_address = 94
377+
register_qty = 3
378+
register_value = host.read_holding_registers(
379+
slave_addr=slave_addr,
380+
starting_addr=hreg_address,
381+
register_qty=register_qty,
382+
signed=False)
383+
print('Status of HREG {}: {}'.format(hreg_address, register_value))
384+
# Status of HREG 94: [29, 38, 0]
385+
```
386+
387+
> :warning: Please be aware of bug
388+
[#35](https://github.com/brainelectronics/micropython-modbus/issues/35). It is
389+
not possible to read a specific position within a configured list of multiple
390+
holding registers on a MicroPython Modbus TCP client device. Reading holding
391+
register 95, holding the value `38` in the above example will throw an error.
392+
This bug affects only devices using this package. Other devices work as
393+
expected and can be addressed as specified.
394+
395+
##### Write
396+
397+
Holding registers can be set to `0` through `65535` or `-32768` through `32767`
398+
in case signed values are used.
399+
400+
###### Single
401+
402+
> The function code `0x06` is used to write a single holding register in a
403+
remote device.
404+
405+
With the function
406+
[`write_single_register`](umodbus.tcp.TCP.write_single_register) a single
407+
holding register can be set.
408+
409+
```python
410+
hreg_address = 93
411+
new_hreg_val = 44
412+
operation_status = host.write_single_register(
413+
slave_addr=slave_addr,
414+
register_address=hreg_address,
415+
register_value=new_hreg_val,
416+
signed=False)
417+
print('Result of setting HREG {}: {}'.format(hreg_address, operation_status))
418+
# Result of setting HREG 93: True
419+
```
420+
421+
###### Multiple
422+
423+
> The function code `0x10` is used to write a block of contiguous registers
424+
(1 to 123 registers) in a remote device.
425+
426+
With the function
427+
[`write_multiple_registers`](umodbus.tcp.TCP.write_multiple_registers)
428+
holding register can be set at once.
429+
430+
```python
431+
hreg_address = 94
432+
new_hreg_vals = [54, -12, 30001]
433+
operation_status = self._host.write_multiple_registers(
434+
slave_addr=slave_addr,
435+
starting_address=hreg_address,
436+
register_values=new_hreg_vals,
437+
signed=True)
438+
print('Result of setting HREG {}: {}'.format(hreg_address, operation_status))
439+
# Result of setting HREG 94: True
440+
```
441+
442+
> :warning: Please be aware of bug
443+
[#35](https://github.com/brainelectronics/micropython-modbus/issues/35). It is
444+
not possible to write to a specific position within a configured list of
445+
multiple holding registers on a MicroPython Modbus TCP client device. Setting
446+
holding register 95+96 to e.g. `[-12, 30001]` in the above example will throw
447+
an error. This bug affects only devices using this package. Other devices work
448+
as expected and can be addressed as specified.
449+
450+
#### Input registers
451+
452+
Input registers can hold values between `0` and `65535`. If supported by the
453+
client device, data can be marked as signed values to represent `-32768`
454+
through `32767`. Unlike [holding registers](#holding-registers), these cannot
455+
be set.
456+
457+
##### Read
458+
459+
> The function code `0x04` is used to read from 1 to 125 contiguous input
460+
registers in a remote device.
461+
462+
With the function [`read_input_registers`](umodbus.tcp.TCP.read_input_registers)
463+
input registers can be read.
464+
465+
```python
466+
ireg_address = 11
467+
register_qty = 3
468+
register_value = host.read_input_registers(
469+
slave_addr=slave_addr,
470+
starting_addr=ireg_address,
471+
register_qty=register_qty,
472+
signed=False)
473+
print('Status of IREG {}: {}'.format(ireg_address, register_value))
474+
# Status of IREG 11: [59123, 0, 390]
475+
```
476+
220477
### TCP
221478

222479
Get two network capable boards up and running, collecting and setting data on

docs/umodbus.rst

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,50 @@ micropython-modbus API
44
.. autosummary::
55
:toctree: generated
66

7-
umodbus.common module
7+
Modbus Constants
88
---------------------------------
99

10-
.. automodule:: umodbus.common
10+
.. automodule:: umodbus.const
1111
:members:
12+
:private-members:
1213
:show-inheritance:
1314

14-
umodbus.const module
15+
Common module
1516
---------------------------------
1617

17-
.. automodule:: umodbus.const
18+
.. automodule:: umodbus.common
1819
:members:
20+
:private-members:
1921
:show-inheritance:
2022

21-
umodbus.functions module
23+
Common functions
2224
---------------------------------
2325

2426
.. automodule:: umodbus.functions
2527
:members:
28+
:private-members:
2629
:show-inheritance:
2730

2831
umodbus.modbus module
2932
---------------------------------
3033

3134
.. automodule:: umodbus.modbus
3235
:members:
36+
:private-members:
3337
:show-inheritance:
3438

35-
umodbus.serial module
39+
Serial
3640
---------------------------------
3741

3842
.. automodule:: umodbus.serial
3943
:members:
44+
:private-members:
4045
:show-inheritance:
4146

42-
umodbus.tcp module
47+
TCP
4348
---------------------------------
4449

4550
.. automodule:: umodbus.tcp
4651
:members:
52+
:private-members:
4753
:show-inheritance:

0 commit comments

Comments
 (0)