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/14 04:54] – [Parameters] mfranklinlogicpython:cubloc_api:setmodbus [2026/05/19 06:34] (current) – [Example] mfranklin
Line 1: Line 1:
 ====== SetModbus ====== ====== SetModbus ======
  
-Configure UART settings and start the LogicPython Modbus RTU slave worker.+Configure UART settings and start the LogicPython Modbus RTU slave process.
  
 ===== Syntax ===== ===== Syntax =====
Line 26: Line 26:
     * **channel**: Serial ''channel'' number. ''Channel'' 0 maps to UART0 (GP0/GP1) and ''channel'' 1 maps to UART1 (GP4/GP5).     * **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).     * **baudRate**: Serial baud rate (2400 to 921600).
-    * **protocol**: Encoded bit field for data bits, parity, and stop bits.+    * **protocol**: Encoded bit field for data bits, parity, and stop bits.  See the tables below.
     * **recvSize**: Receive buffer size in bytes (1 to 4096).     * **recvSize**: Receive buffer size in bytes (1 to 4096).
     * **sendSize**: Send buffer size in bytes (1 to 4096).     * **sendSize**: Send buffer size in bytes (1 to 4096).
Line 35: Line 35:
     * **holdingRegisters**: Writable holding-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.     * **memoryLock**: lock object to synchronize Modbus memory access between the user program and the Modbus RTU slave process.
-    * **returnInterval**: Non-blocking delay in microseconds before sending response (default 0).+    * **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 =====
Line 46: Line 61:
  
 <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
  
-OUTPUT_PINS = (25, 16, 18, 20+machine os.uname().machine 
-INPUT_PINS  = (6,  8,  10) +print(machine)
-ADC_CHANS   (0,  1,  2)+
  
-coils           bytearray(1+if "LP126T" in machine: 
-discrete_inputs bytearray(1+    OUTPUT_PINS = (3, 16, 17, 18, 19
-input_regs      bytearray(6+    INPUT_PINS  = (32, 33, 34, 35, 36, 37, 38, 39
-holding_regs    bytearray(2+    ADC_CHANS   = (40, 41, 42, 43, 44, 45
-mem_lock        _thread.allocate_lock()+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: 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)
  
-SetModbus(0, 9600, 364, 64, 1, coils, discrete_inputs, input_regs, holding_regs, mem_lock)+# Configure and start the Modbus RTU slave process 
 +UART_CHANNEL = 0 
 +BAUD_RATE = 460800 
 +PROTOCOL =        # 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: while True:
-    # Read coils snapshot under lock+    # Read the coil memory
     mem_lock.acquire()     mem_lock.acquire()
-    try: +    coils_byte = coils[0] 
-        coils_byte = coils[0] +    mem_lock.release()
-    finally: +
-        mem_lock.release()+
  
-    # Drive outputs from that snapshot +    # Drive digital outputs from the coil memory 
-    for i, pin in enumerate(OUTPUT_PINS)+    i = 0 
-        if coils_byte & (<< i): +    while i < OUTPUT_COUNT
-            High(pin+        Out(OUTPUT_PINS[i], (coils_byte >> i) & 1) 
-        else: +        i += 1
-            Low(pin)+
  
-    # Sample physical inputs outside the lock+    # Read digital inputs
     din_byte = 0     din_byte = 0
-    for i, pin in enumerate(INPUT_PINS)+    i = 0 
-        if In(pin): +    while i < INPUT_COUNT
-            din_byte |= (1 << i)+        if In(INPUT_PINS[i]): 
 +            din_byte |= 1 << i 
 +        i += 1
  
-    adc_vals = [ADIn(ch) for ch in ADC_CHANS] +    # Transfer digital inputs to discrete input memory
- +
-    Publish a coherent snapshot and read setpoint atomically+
     mem_lock.acquire()     mem_lock.acquire()
-    try: +    discrete_inputs[0] = din_byte 
-        discrete_inputs[0] = din_byte+    mem_lock.release()
  
-        for i, val in enumerate(adc_vals)+    # Read analog inputs 
-            struct.pack_into('>H', input_regs, * 2, val)+    = 0 
 +    j = 0 
 +    while i < ADC_COUNT
 +        val = ADIn(ADC_CHANS[i])
  
-        setpoint struct.unpack_from('>H', holding_regs, 0)[0] +        adc_shadow[j]     = (val >> 8& 0xFF 
-    finally: +        adc_shadow[j + 1] = val & 0xFF
-        mem_lock.release()+
  
-    time.sleep(0.010)+        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> </code>
  
  
logicpython/cubloc_api/setmodbus.1776142489.txt.gz · Last modified: by mfranklin