====== SetModbus ======
Configure UART settings and start the LogicPython Modbus RTU slave process.
===== Syntax =====
from cubloc import SetModbus
SetModbus(channel: int,
baudRate: int,
protocol: int,
recvSize: int,
sendSize: int,
slaveAddress: int,
coils: object,
discreteInputs: object,
inputRegisters: object,
holdingRegisters: object,
memoryLock: object,
returnInterval: int = 0)
===== Parameters =====
* **channel**: Serial ''channel'' number. ''Channel'' 0 maps to UART0 (GP0/GP1) and ''channel'' 1 maps to UART1 (GP4/GP5).
* **baudRate**: Serial baud rate (2400 to 921600).
* **protocol**: Encoded bit field for data bits, parity, and stop bits. See the tables below.
* **recvSize**: Receive buffer size in bytes (1 to 4096).
* **sendSize**: Send buffer size in bytes (1 to 4096).
* **slaveAddress**: Modbus unit ID (1 to 247).
* **coils**: Writable bit-packed coil buffer (8 ''coils'' per byte).
* **discreteInputs**: Writable bit-packed discrete-input buffer (8 inputs per byte).
* **inputRegisters**: Writable input-register byte buffer (2 bytes per register).
* **holdingRegisters**: Writable holding-register byte buffer (2 bytes per register).
* **memoryLock**: lock object to synchronize Modbus memory access between the user program and the Modbus RTU slave process.
* **returnInterval**: Delay in microseconds before replying to a Modbus query from the Modbus master (default 0).
''protocol'' bit layout:
^ Field ^ Bits ^ Meaning ^
| Data bits | 1..0 | 00=5 bits, 01=6 bits, 10=7 bits, 11=8 bits |
| Stop bits | 2 | 0=1 stop bit, 1=2 stop bits |
| Parity | 4..3 | 00=None, 10=Even, 11=Odd (01 is reserved and raises ''ValueError'') |
Common ''protocol'' values:
^ protocol ^ Frame format ^
| 3 | 8N1 |
| 11 | 8E1 |
| 19 | 8O1 |
| 7 | 8N2 |
===== Exceptions =====
* [[https://docs.micropython.org/en/latest/library/builtins.html#TypeError|TypeError]]: An argument has an invalid type.
* [[https://docs.micropython.org/en/latest/library/builtins.html#ValueError|ValueError]]: ''baudRate'', ''protocol'', ''recvSize'', ''sendSize'', or ''slaveAddress'' is outside the supported range.
* [[https://docs.micropython.org/en/latest/library/builtins.html#RuntimeError|RuntimeError]]: Modbus startup failed.
===== Example =====
import _thread
from cubloc import *
from machine import *
import os
from time import sleep
machine = os.uname().machine
print(machine)
if "LP126T" in machine:
OUTPUT_PINS = (3, 16, 17, 18, 19)
INPUT_PINS = (32, 33, 34, 35, 36, 37, 38, 39)
ADC_CHANS = (40, 41, 42, 43, 44, 45)
else:
OUTPUT_PINS = (25, 16, 17, 18)
INPUT_PINS = (19, 20, 21)
ADC_CHANS = (26, 27, 28)
OUTPUT_COUNT = len(OUTPUT_PINS)
INPUT_COUNT = len(INPUT_PINS)
ADC_COUNT = len(ADC_CHANS)
ADC_BYTES = ADC_COUNT << 1
# Initialize the physical IO
for pin in OUTPUT_PINS:
Output(pin)
Low(pin)
for pin in INPUT_PINS:
Input(pin, 1)
# Configure and start the Modbus RTU slave process
UART_CHANNEL = 0
BAUD_RATE = 460800
PROTOCOL = 3 # 8N1
BUFFER_SIZE = 64
SLAVE_ADDRESS = 1
# Configure the Modbus memory
coils = bytearray(1)
discrete_inputs = bytearray(2)
input_regs = bytearray(16)
holding_regs = bytearray(16)
mem_lock = _thread.allocate_lock()
adc_shadow = bytearray(ADC_BYTES)
setpoint = 0
# Start the Modbus slave
print("Starting Modbus")
SetModbus(
UART_CHANNEL,
BAUD_RATE,
PROTOCOL,
BUFFER_SIZE,
BUFFER_SIZE,
SLAVE_ADDRESS,
coils,
discrete_inputs,
input_regs,
holding_regs,
mem_lock
)
# Run in an infinite loop synchronizing Modbus memory with the physical IO
print("Starting the main loop")
while True:
# Read the coil memory
mem_lock.acquire()
coils_byte = coils[0]
mem_lock.release()
# Drive digital outputs from the coil memory
i = 0
while i < OUTPUT_COUNT:
Out(OUTPUT_PINS[i], (coils_byte >> i) & 1)
i += 1
# Read digital inputs
din_byte = 0
i = 0
while i < INPUT_COUNT:
if In(INPUT_PINS[i]):
din_byte |= 1 << i
i += 1
# Transfer digital inputs to discrete input memory
mem_lock.acquire()
discrete_inputs[0] = din_byte
mem_lock.release()
# Read analog inputs
i = 0
j = 0
while i < ADC_COUNT:
val = ADIn(ADC_CHANS[i])
adc_shadow[j] = (val >> 8) & 0xFF
adc_shadow[j + 1] = val & 0xFF
i += 1
j += 2
# Transfer analog inputs to input register memory
mem_lock.acquire()
i = 0
while i < ADC_BYTES:
input_regs[i] = adc_shadow[i]
i += 1
mem_lock.release()
# Transfer holding register memory to the setpoint variable
mem_lock.acquire()
setpoint = (holding_regs[0] << 8) | holding_regs[1]
mem_lock.release()