This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| logicpython:cubloc_api:setmodbus [2026/04/14 04:59] – [Example] mfranklin | logicpython: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 35: | Line 35: | ||
| * **holdingRegisters**: | * **holdingRegisters**: | ||
| * **memoryLock**: | * **memoryLock**: | ||
| - | * **returnInterval**: | + | * **returnInterval**: |
| '' | '' | ||
| Line 61: | 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 | + | machine |
| - | INPUT_PINS | + | print(machine) |
| - | ADC_CHANS | + | |
| - | coils = bytearray(1) | + | if " |
| - | discrete_inputs | + | OUTPUT_PINS |
| - | input_regs | + | |
| - | holding_regs | + | |
| - | mem_lock | + | else: |
| + | OUTPUT_PINS | ||
| + | | ||
| + | ADC_CHANS | ||
| + | |||
| + | OUTPUT_COUNT = len(OUTPUT_PINS) | ||
| + | INPUT_COUNT | ||
| + | ADC_COUNT | ||
| + | ADC_BYTES | ||
| + | # 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) |
| + | # Configure and start the Modbus RTU slave process | ||
| UART_CHANNEL = 0 | UART_CHANNEL = 0 | ||
| - | BAUD_RATE = 115200 | + | BAUD_RATE = 460800 |
| PROTOCOL = 3 # 8N1 | PROTOCOL = 3 # 8N1 | ||
| BUFFER_SIZE = 64 | BUFFER_SIZE = 64 | ||
| SLAVE_ADDRESS = 1 | SLAVE_ADDRESS = 1 | ||
| - | SetModbus(UART_CHANNEL, | + | |
| + | # Configure the Modbus memory | ||
| + | coils = bytearray(1) | ||
| + | discrete_inputs = bytearray(2) | ||
| + | input_regs | ||
| + | holding_regs | ||
| + | mem_lock | ||
| + | adc_shadow | ||
| + | setpoint | ||
| + | |||
| + | # Start the Modbus slave | ||
| + | print(" | ||
| + | SetModbus( | ||
| + | | ||
| BAUD_RATE, | BAUD_RATE, | ||
| PROTOCOL, | PROTOCOL, | ||
| BUFFER_SIZE, | BUFFER_SIZE, | ||
| BUFFER_SIZE, | BUFFER_SIZE, | ||
| - | SLAVE_ADDRESS, | + | SLAVE_ADDRESS, |
| - | coils, discrete_inputs, | + | coils, |
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | ) | ||
| + | # Run in an infinite loop synchronizing Modbus memory with the physical IO | ||
| + | print(" | ||
| while True: | while True: | ||
| - | # Read coils snapshot under lock | + | # Read the coil memory |
| mem_lock.acquire() | mem_lock.acquire() | ||
| - | | + | coils_byte = coils[0] |
| - | | + | mem_lock.release() |
| - | | + | |
| - | | + | |
| - | # Drive outputs from that snapshot | + | # Drive digital |
| - | | + | i = 0 |
| - | | + | while i < OUTPUT_COUNT: |
| - | High(pin) | + | |
| - | | + | |
| - | Low(pin) | + | |
| - | # Sample physical | + | # Read digital |
| din_byte = 0 | din_byte = 0 | ||
| - | | + | i = 0 |
| - | if In(pin): | + | while i < INPUT_COUNT: |
| - | din_byte |= (1 << i) | + | if In(INPUT_PINS[i]): |
| + | din_byte |= 1 << i | ||
| + | i += 1 | ||
| - | | + | # Transfer digital inputs to discrete input memory |
| - | + | ||
| - | | + | |
| mem_lock.acquire() | mem_lock.acquire() | ||
| - | | + | discrete_inputs[0] = din_byte |
| - | | + | mem_lock.release() |
| - | for i, val in enumerate(adc_vals): | + | # Read analog inputs |
| - | | + | |
| + | j = 0 | ||
| + | while i < ADC_COUNT: | ||
| + | val = ADIn(ADC_CHANS[i]) | ||
| - | | + | |
| - | finally: | + | |
| - | | + | |
| - | 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() | ||
| </ | </ | ||