User Tools

Site Tools

한국어

logicpython:cubloc_api:setmodbus

This is an old revision of the document!


SetModbus

Start the LogicPython Modbus RTU slave worker using a pre-opened UART channel.

Syntax

from cubloc import SetModbus
 
SetModbus(channel: int, 
    slaveAddress: int,
    coils: object,
    discreteInputs: object,
    inputRegisters: object,
    holdingRegisters: object,
    memoryLock: object,
    returnInterval: int = 0)

Parameters

  • channel: RS-232 channel number. OpenCom must already be called for this channel.
  • 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: User-created lock object passed through to logic_python.modbus.start_modbus.
  • returnInterval: Non-blocking delay in microseconds before sending a response (default 0).

Exceptions

  • TypeError: An argument has an invalid type.
  • ValueError: slaveAddress is outside the supported range.
  • RuntimeError: OpenCom has not been called for this channel or Modbus startup failed.

Example

import struct
import time
import _thread
from cubloc import *
 
# Coils 0-3           -> digital outputs on GP14, GP16, GP18, GP20
# Discrete inputs 0-2 <- digital inputs  on GP6, GP8, GP10
# Input registers 0-2 <- ADC readings    on ADC0 (GP26), ADC1 (GP27), ADC2 (GP28)
# Holding register 0  -> setpoint value written by the Modbus master
 
OUTPUT_PINS = (25, 16, 18, 20)
INPUT_PINS  = (6,  8,  10)
ADC_CHANS   = (0,  1,  2)
 
# Allocate Modbus memory regions
coils           = bytearray(1)   # 8 coils (1 byte, bits 0-3 used)
discrete_inputs = bytearray(1)   # 8 discrete inputs (1 byte, bits 0-2 used)
input_regs      = bytearray(6)   # 3 input registers x 2 bytes each
holding_regs    = bytearray(2)   # 1 holding register x 2 bytes
mem_lock        = _thread.allocate_lock()
 
# Configure physical I/O
for pin in OUTPUT_PINS:
    Output(pin)
    Low(pin)
for pin in INPUT_PINS:
    Input(pin)
 
# Open UART0 at 460800 baud, 8N1
OpenCom(0, 460800, 3, 1024, 1024)
 
# Start Modbus RTU slave, address 1
SetModbus(0, 1, coils, discrete_inputs, input_regs, holding_regs, mem_lock)
 
# Main loop: mirror Modbus memory to/from physical I/O every 10 ms
while True:
    # Read coil byte without locking (master may update coils concurrently)
    coils_byte = coils[0]
 
    # Drive output pins from coil bits (master writes coils 0-3)
    for i, pin in enumerate(OUTPUT_PINS):
        if coils_byte & (1 << i):
            High(pin)
        else:
            Low(pin)
 
    # Capture digital inputs (prepare value to write into discrete_inputs)
    din_byte = 0
    for i, pin in enumerate(INPUT_PINS):
        if In(pin):
            din_byte |= (1 << i)
 
    # Capture ADC readings (prepare values to write into input_regs)
    adc_vals = [ADIn(ch) for ch in ADC_CHANS]
 
    # Now write the prepared Modbus memory updates under lock only while writing
    mem_lock.acquire()
    try:
        discrete_inputs[0] = din_byte
        for i, val in enumerate(adc_vals):
            struct.pack_into('>H', input_regs, i * 2, val)
    finally:
        mem_lock.release()
 
    # Read setpoint value from holding register 0 (master may write it) without locking
    setpoint = struct.unpack_from('>H', holding_regs, 0)[0]
 
    time.sleep(0.010)
logicpython/cubloc_api/setmodbus.1775805106.txt.gz · Last modified: by mfranklin