User Tools

Site Tools

한국어

logicpython:cubloc_api:setmodbus

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
logicpython:cubloc_api:setmodbus [2026/04/10 07:00] – [Example] mfranklinlogicpython:cubloc_api:setmodbus [2026/05/19 06:34] (current) – [Example] mfranklin
Line 1: Line 1:
 ====== SetModbus ====== ====== SetModbus ======
  
-Start the LogicPython Modbus RTU slave worker using a pre-opened UART ''channel''.+Configure UART settings and start the LogicPython Modbus RTU slave process.
  
 ===== Syntax ===== ===== Syntax =====
Line 8: Line 8:
 from cubloc import SetModbus from cubloc import SetModbus
  
-SetModbus(channel: int, +SetModbus(channel: int, 
 +    baudRate: int, 
 +    protocol: int, 
 +    recvSize: int, 
 +    sendSize: int,
     slaveAddress: int,     slaveAddress: int,
     coils: object,     coils: object,
Line 20: Line 24:
 ===== Parameters ===== ===== Parameters =====
  
-  * **channel**: RS-232 ''channel'' number. ''OpenCom'' must already be called for this ''channel''+    * **channel**: Serial ''channel'' number. ''Channel'' 0 maps to UART0 (GP0/GP1) and ''channel'' 1 maps to UART1 (GP4/GP5)
-  * **slaveAddress**: Modbus unit ID (1 to 247). +    * **baudRate**: Serial baud rate (2400 to 921600). 
-  * **coils**: Writable bit-packed coil buffer (8 ''coils'' per byte). +    * **protocol**: Encoded bit field for data bits, parity, and stop bits.  See the tables below. 
-  * **discreteInputs**: Writable bit-packed discrete-input buffer (8 inputs per byte). +    * **recvSize**: Receive buffer size in bytes (1 to 4096). 
-  * **inputRegisters**: Writable input-register byte buffer (2 bytes per register). +    * **sendSize**: Send buffer size in bytes (1 to 4096). 
-  * **holdingRegisters**: Writable holding-register byte buffer (2 bytes per register). +    * **slaveAddress**: Modbus unit ID (1 to 247). 
-  * **memoryLock**: User-created lock object passed through to logic_python.modbus.start_modbus+    * **coils**: Writable bit-packed coil buffer (8 ''coils'' per byte). 
-  * **returnInterval**: Non-blocking delay in microseconds before sending response (default 0).+    * **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 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 ===== ===== 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#TypeError|TypeError]]: An argument has an invalid type. 
-  * [[https://docs.micropython.org/en/latest/library/builtins.html#ValueError|ValueError]]: ''slaveAddress'' is outside the supported range. +    * [[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]]: ''OpenCom'' has not been called for this ''channel'' or Modbus startup failed.+    * [[https://docs.micropython.org/en/latest/library/builtins.html#RuntimeError|RuntimeError]]: Modbus startup failed.
  
 ===== Example ===== ===== Example =====
  
 <code python> <code python>
-import struct 
-import time 
 import _thread import _thread
 from cubloc import * from cubloc import *
 +from machine import *
 +import os
 +from time import sleep
  
-# Coils 0-3           -> digital outputs on GP14, GP16, GP18, GP20 +machine = os.uname().machine 
-# Discrete inputs 0-2 <- digital inputs  on GP6, GP8, GP10 +print(machine)
-# 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 = (14, 16, 18, 20+if "LP126T" in machine: 
-INPUT_PINS  = (6 8 10+    OUTPUT_PINS = (3, 16, 17, 18, 19
-ADC_CHANS   = (0 1,  2)+    INPUT_PINS  = (323334, 35, 36, 37, 38, 39
 +    ADC_CHANS   = (404142, 43, 44, 45) 
 +else: 
 +    OUTPUT_PINS = (25, 16, 17, 18) 
 +    INPUT_PINS  = (19, 20, 21) 
 +    ADC_CHANS   = (26, 27, 28)
  
-# Allocate Modbus memory regions +OUTPUT_COUNT len(OUTPUT_PINS
-coils           bytearray(1)   # 8 coils (1 byte, bits 0-3 used+INPUT_COUNT  len(INPUT_PINS
-discrete_inputs bytearray(1)   # 8 discrete inputs (1 byte, bits 0-2 used+ADC_COUNT    len(ADC_CHANS
-input_regs      bytearray(6  # 3 input registers x 2 bytes each +ADC_BYTES    ADC_COUNT << 1
-holding_regs    bytearray(2)   # holding register x 2 bytes +
-mem_lock        = _thread.allocate_lock()+
  
-Configure physical I/O+Initialize the physical IO
 for pin in OUTPUT_PINS: for pin in OUTPUT_PINS:
     Output(pin)     Output(pin)
     Low(pin)     Low(pin)
 +
 for pin in INPUT_PINS: for pin in INPUT_PINS:
-    Input(pin)+    Input(pin, 1)
  
-Open UART0 at 460800 baud, 8N1 +Configure and start the Modbus RTU slave process 
-OpenCom(04608003, 1024, 1024)+UART_CHANNEL = 0 
 +BAUD_RATE = 460800 
 +PROTOCOL =        # 8N1 
 +BUFFER_SIZE = 64 
 +SLAVE_ADDRESS = 1
  
-# Start Modbus RTU slave, address 1 +# Configure the Modbus memory 
-SetModbus(01, coils, discrete_inputs, input_regs, holding_regs, mem_lock)+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 
 +)
  
-Main loop: mirror Modbus memory to/from physical I/O every 10 ms+Run in an infinite loop synchronizing Modbus memory with the physical IO 
 +print("Starting the main loop")
 while True: while True:
-    with mem_lock: +    # Read the coil memory 
-        Drive output pins from coil bits (master writes coils 0-3) +    mem_lock.acquire() 
-        for i, pin in enumerate(OUTPUT_PINS): +    coils_byte = coils[0] 
-            if coils[0] & (1 << i): +    mem_lock.release()
-                High(pin) +
-            else: +
-                Low(pin)+
  
-        Capture digital inputs and store as discrete-input bits (master reads) +    Drive digital outputs from the coil memory 
-        din_byte = 0 +    = 0 
-        for i, pin in enumerate(INPUT_PINS)+    while < OUTPUT_COUNT
-            if In(pin): +        Out(OUTPUT_PINS[i], (coils_byte >> i) & 1
-                din_byte |= (1 << i) +        i +1
-        discrete_inputs[0] din_byte+
  
-        Capture ADC readings and store in input registers (big-endian, master reads) +    Read digital inputs 
-        for i, ch in enumerate(ADC_CHANS): +    din_byte = 0 
-            struct.pack_into('>H', input_regs, * 2, ADIn(ch))+    = 0 
 +    while i < INPUT_COUNT: 
 +        if In(INPUT_PINS[i]): 
 +            din_byte |= 1 << i 
 +        i += 1
  
-        Read setpoint value from holding register 0 (master writes) +    Transfer digital inputs to discrete input memory 
-        setpoint = struct.unpack_from('>H', holding_regs, 0)[0]+    mem_lock.acquire() 
 +    discrete_inputs[0] = din_byte 
 +    mem_lock.release()
  
-    time.sleep(0.010) +    # Read analog inputs 
-</code>+    i = 
 +    j = 0 
 +    while i ADC_COUNT: 
 +        val = ADIn(ADC_CHANS[i])
  
-===== Related APIs =====+        adc_shadow[j]     (val >> 8) & 0xFF 
 +        adc_shadow[j + 1] val & 0xFF
  
-  * [[logicpython:cubloc_api:opencom|OpenCom]]+        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() 
 +</code>
  
  
logicpython/cubloc_api/setmodbus.1775804440.txt.gz · Last modified: by mfranklin