Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

devhari
Posts: 8
Joined: Thu Mar 13, 2025 2:01 pm

Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

Postby devhari » Thu Mar 13, 2025 2:18 pm

Hi
I'm working on controlling controlling MODBUS RTU from esp32 mini1 and esp32s3 wroom1.
Few days back I did controlling with MODBUS.
if I send frames from esp to modbus device and after making read/write pin low I got acknowledgement frames from modbus to esp that time.
But
Now same source code, same connections and same devices I'm trying to repeat with sending frames to modbus. But the issue is now unable to read and print acknowledgement frames in esp.
I checked acknowledgement frames by connecting esp chip Rx line to TTL device and frames was read in Realterm.
But why esp chip is failing to read and print acknowledgement frames??? Why this sudden behaviour???
Helo me to figure out this issue..
Thanks

User avatar
egionet
Posts: 39
Joined: Thu Sep 26, 2024 4:34 am
Location: Atlantic Canada

Re: Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

Postby egionet » Fri Mar 14, 2025 7:49 am

You have two potential sources for errors. Do you have an independent RTU sensor or device to test with to act as a control?

I am using the ESP MODBUS component, and it works fine. I am polling multiple RTUs with different addresses on the same RS-485 bus.
Regards,

Eric Gionet P.Tech.(Eng.), CIOTP, SMIEEE

devhari
Posts: 8
Joined: Thu Mar 13, 2025 2:01 pm

Re: Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

Postby devhari » Fri Mar 14, 2025 10:09 am

Yes, I have independent RTU device(Jaguar).
I'm working with this device only.

And response I got after delay and at a time response bytes printing.
Check below logs that I have got.

No response received.
No response received.
No response received.
No response received.
No response received.
No response received.
No response received.
Response: FF 00 01 03 02 00 02 39 85 00 00 01 03 02 00 02 39 85 00 00 01 03 02 00 02 39 85 00 00 01 03 02
Response: 00 02 39 85 00 00 01 03 02 00 04 B9 87 00 00 01 03 02 00 04 B9 87 00 00 01 03 02 00 20 B9 9C 00
Response: 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00
Response: 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01
No response received.

User avatar
egionet
Posts: 39
Joined: Thu Sep 26, 2024 4:34 am
Location: Atlantic Canada

Re: Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

Postby egionet » Sat Mar 15, 2025 5:02 am

Difficult to comment without seeing your code. Here is an example that polls two RTU devices: https://github.com/K0I05/KINCONY-S3_RTU ... _connect.c
Regards,

Eric Gionet P.Tech.(Eng.), CIOTP, SMIEEE

devhari
Posts: 8
Joined: Thu Mar 13, 2025 2:01 pm

Re: Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

Postby devhari » Sat Mar 15, 2025 1:04 pm

Thanks for sharing source code. But unfortunately no use that source code for me. Because I'm controlling MODBUS via RS485 circuit.
(ESP chip -> RS485 circuit-> MODBUS device and viceversa).

My Intention is just want to send frame to MODBUS via RS485 circuit and need to receive acknowledgement frame from modbus.
Response I'm getting fast from modbus device at esp chip Rx pin and this response frame also I tested with RealTerm(using TTL device) and printing in realterm. But with esp chip unable to read and print that response frame from RX pin.
Just I want to print incoming frame with esp chip Rx pin.

I have observed issue was if I sent 8 times frame from esp to modbus then after some time 8 responses priting at one time. But I want to print each response frame after sending each frame to modbus.

Below I attached my source code about sending and reading frames from modbus device. Let me know any modifications are required.

Code: Select all


#include <stdio.h>
#include <stdint.h>
#include "driver/uart.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define ID_VALUE 1
#define ZONE_REQUIREMENTS 1
#define FRAME_SIZE 8
#define UART_NUM UART_NUM_1  // Use UART1 for communication
#define TXD_PIN GPIO_NUM_4   // TX pin for UART1 (change as needed)
#define RXD_PIN GPIO_NUM_5   // RX pin for UART1 (change as needed)
#define BAUD_RATE 9600       // Baud rate (match with TTL device)
#define RS485_ENABLE_PIN GPIO_NUM_2  // RS485 Enable (Connect to DE & RE)

uint8_t response_buffer[32];
int prev_scene[16] = {-1}; // Array to store previous scene for each zone (0-15)
int active_button = 0;

uint16_t Read_Register_value = 6999;
uint16_t Write_Register_value = 5999;

// Function to calculate Modbus CRC-16
uint16_t calculate_modbus_crc(uint8_t *data, size_t length) {
    uint16_t crc = 0xFFFF;
    for (size_t i = 0; i < length; i++) {
        crc ^= data[i];
        for (int j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

void init_uart() {
    uart_config_t uart_config = {
        .baud_rate = BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_driver_install(UART_NUM, 256, 0, 0, NULL, 0);
    uart_param_config(UART_NUM, &uart_config);
    uart_set_pin(UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    // Configure GPIO for RS485 TX/RX control
    gpio_set_direction(RS485_ENABLE_PIN, GPIO_MODE_OUTPUT);
}


void get_response_from_rs485(void *pvParameters) {
    uint8_t modbus_frames[ZONE_REQUIREMENTS][FRAME_SIZE];

    for (int i = 0; i < ZONE_REQUIREMENTS; i++) {
        
        uint16_t decimal_value = Read_Register_value + (i + 1);

        modbus_frames[i][0] = ID_VALUE;
        modbus_frames[i][1] = 0x03;// Read Holding Register command
        modbus_frames[i][2] = (decimal_value >> 8) & 0xFF;
        modbus_frames[i][3] = decimal_value & 0xFF;
        modbus_frames[i][4] = 0x00;
        modbus_frames[i][5] = 0x01;

        uint16_t crc = calculate_modbus_crc(modbus_frames[i], 6);
        modbus_frames[i][6] = crc & 0xFF;
        modbus_frames[i][7] = (crc >> 8) & 0xFF;
    }

    while (1) {
        for (int i = 0; i < ZONE_REQUIREMENTS; i++) {
            // Enable TX mode
            gpio_set_level(RS485_ENABLE_PIN, 1);
            vTaskDelay(pdMS_TO_TICKS(1)); // Small delay for RS485 control stabilization

            // Send data via UART
            // printf("----Sending Frame (ZONE - %d)---\n", i + 1);
            for (int j = 0; j < FRAME_SIZE; j++) {
                // printf("%02X ", modbus_frames[i][j]);
            }
            // printf("\n");

            uart_write_bytes(UART_NUM, (const char *)modbus_frames[i], FRAME_SIZE);

            vTaskDelay(pdMS_TO_TICKS(10)); // Allow time for transmission

            // Switch to RX mode to receive response
            gpio_set_level(RS485_ENABLE_PIN, 0);

            // Read response
            
            int len = uart_read_bytes(UART_NUM, response_buffer, sizeof(response_buffer), 100 / portTICK_PERIOD_MS);
            if (len > 0) {
                 printf("Response: ");
                for (int k = 0; k < len; k++) {
                    printf("%02X ", response_buffer[k]);
                }
                printf("\n");
            } else {
                printf("No response received.\n");
            }

            vTaskDelay(pdMS_TO_TICKS(500));  // Wait 2ms before sending next frame
        }
    }
}


void app_main() {
    init_uart();
     xTaskCreate(get_response_from_rs485, "get_response_from_rs485", 4096, NULL, 5, NULL);
}

The observed logs as follow.

No response received.
No response received.
No response received.
No response received.
No response received.
No response received.
No response received.
Response: FF 00 01 03 02 00 02 39 85 00 00 01 03 02 00 02 39 85 00 00 01 03 02 00 02 39 85 00 00 01 03 02
Response: 00 02 39 85 00 00 01 03 02 00 04 B9 87 00 00 01 03 02 00 04 B9 87 00 00 01 03 02 00 20 B9 9C 00
Response: 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00
Response: 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01 03 02 00 20 B9 9C 00 00 01
No response received.
No response received.
No response received.
No response received.

User avatar
egionet
Posts: 39
Joined: Thu Sep 26, 2024 4:34 am
Location: Atlantic Canada

Re: Unable to read MODBUS RTU acknowledgement frames through esp32 Rx line

Postby egionet » Thu Mar 20, 2025 9:41 pm

Okay, so you are constructing the packet yourself and not using the esp-modbus component. I would have to understand your circuit given it looks like you are toggling a GPIO to switch from TX to RX. A simple test would be connecting the two boards using TTL levels (ie.g RX to TX and TX to RX) and enabling RS485 half-duplex when you configure the UARTS. If this works then the problem is elsewhere and it could be timing-related if you are using a single GPIO for both TX and RX transactions. I am not sure of the reasoning for reinventing the wheel, the esp-modbus library encodes and decodes packets and takes care of get/set transactions for holding registers, coils, etc. provided the circuit design follows best practices for modbus serial and/or modbus tcp.
Regards,

Eric Gionet P.Tech.(Eng.), CIOTP, SMIEEE

Who is online

Users browsing this forum: Semrush [Bot] and 5 guests