Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regarding _uart_read in serial.py #98

Open
hbadshahp opened this issue Sep 27, 2024 · 0 comments
Open

Regarding _uart_read in serial.py #98

hbadshahp opened this issue Sep 27, 2024 · 0 comments

Comments

@hbadshahp
Copy link

Description

I am using Esp32, MAX485 AND Sensor

while trying to read slave(Sensor) from read_holding_registers function

sending the frame correctly
b'\x08\x03\x00\x00\x00\x02\xc4\x92'

but the response receive is wrong
b'\xc2\xb0\xdc\xa4\xe6X\x7f'
Error reading Modbus registers: invalid response CRC

i had played with some of the delay but does not able to resolve the issue.

kindly help me to resolve the issue. Thanks in advance. In code I will attach what are the modification I tried

Reproduction steps

1.In issue#50,73, 75 i have read but doesn't get an idea how to fix my issue
2.
3.
...

MicroPython version

v1.23.0

MicroPython board

ESP32

MicroPython Modbus version

# e.g. v2.3.7
# use the following command to get the used version
import os
from umodbus import version
print('MicroPython infos:', os.uname())
print('Used micropthon-modbus version:', version.__version__)

Relevant log output

MPY: soft reboot
Used micropthon-modbus version: 2.3.7

User code

main.py

from umodbus.serial import Serial
from machine import Pin
from machine import UART
import time

# Define the pins for Modbus communication
rtu_pins = (Pin(17), Pin(18))

# Initialize the Modbus object
m = Serial(baudrate=9600, data_bits=8, stop_bits=1, parity=None, pins=rtu_pins, ctrl_pin=Pin(15), uart_id=2)


# Increase timeout for Modbus response
m._uart.init(timeout=2000)  # Set UART timeout to 2000 ms (2 seconds)

# Function to read current die height
def readCurrentDieHeight():
    slave_addr = const(0x08)  # Modbus slave address (updated to 8)
    starting_address = const(0x00)  # Start reading from address 0x0000
    register_quantity = const(2)  # Read two registers (32-bit value)

    # Try reading the holding registers
    try:
        time.sleep(0.2)  # Small delay to give slave time to respond
        register_values = m.read_holding_registers(slave_addr, starting_address, register_quantity, signed=False)

    except Exception as e:
        print(f"Error reading Modbus registers: {e}")
        return False, 0.0

while True:
    print("start")
    success, die_height = readCurrentDieHeight()

In serial.py

# using _send function I had varied time.sleep_us(85) also eliminate +100 from sleep_time_us because my slave baud rate is 9600

def _send(self, modbus_pdu: bytes, slave_addr: int) -> None:
        print("................trace send frame...................")
        """
        Send Modbus frame via UART

        If a flow control pin has been setup, it will be controlled accordingly

        :param      modbus_pdu:  The modbus Protocol Data Unit
        :type       modbus_pdu:  bytes
        :param      slave_addr:  The slave address
        :type       slave_addr:  int
        """
        # modbus_adu: Modbus Application Data Unit
        # consists of the Modbus PDU, with slave address prepended and checksum appended
        modbus_adu = bytearray()
        modbus_adu.append(slave_addr)
        modbus_adu.extend(modbus_pdu)
        modbus_adu.extend(self._calculate_crc16(modbus_adu))
        print(modbus_adu)

        if self._ctrlPin:
            self._ctrlPin.on()
            #print('on')
            # wait until the control pin really changed
            # 85-95us (ESP32 @ 160/240MHz)
            #time.sleep_us(200)
            time.sleep_us(85)

        # the timing of this part is critical:
        # - if we disable output too early,
        #   the command will not be received in full
        # - if we disable output too late,
        #   the incoming response will lose some data at the beginning
        # easiest to just wait for the bytes to be sent out on the wire
        send_start_time = time.ticks_us()
        #print(f"Send start time: {send_start_time}")
        
        
        # 360-400us @ 9600-115200 baud (measured) (ESP32 @ 160/240MHz)
        #print(f"control pin condition befor write: {self._ctrlPin.value()}")
        
        self._uart.write(modbus_adu)
        
        send_finish_time = time.ticks_us()
        #print(f"Send finish time: {send_finish_time}")

        if self._has_uart_flush:
            self._uart.flush()
            time.sleep_us(self._t1char)
        else:
            sleep_time_us = (
                self._t1char * len(modbus_adu) -    # total frame time in us
                time.ticks_diff(send_finish_time, send_start_time)+
                100 # only required at baudrates above 57600, but hey 100us
            )
            time.sleep_us(sleep_time_us)

        if self._ctrlPin:
            
            self._ctrlPin.off()
            #print('off')

in _uart_read I didn't change anything and try to print the response which is wrong

def _uart_read(self) -> bytearray:
        
        """
        Read incoming slave response from UART

        :returns:   Read content
        :rtype:     bytearray
        """
        response = bytearray()
        print("...........trace response frame inside _uart_read..........")
        

        # TODO: use some kind of hint or user-configurable delay
        #       to determine this loop counter
        
        for x in range(1, 120):
            if self._uart.any():
                # WiPy only
                #response.extend(self._uart.readall())
                
                response.extend(self._uart.read())
                

                # variable length function codes may require multiple reads
                if self._exit_read(response):
                    break

            # wait for the maximum time between two frames
            time.sleep_us(self._inter_frame_delay)
        print(response)
        return response

Additional informations

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant