uarte for modbus communication/ strange behaviour

Hi everyone

I am testing the modbus library over zephyr framework (Nrfconnect (skd v2.2.0 ) on visual studio code).

I started from the examples (link) and I am implementing a modbus master.

In the image below you can see, by status analyzer, the TX and DE pin before conversion to RS-485.

The problem I am experiencing is that more bits are being transmitted than are needed.
my code is quite simple:

#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/modbus/modbus.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(mbc_sample, LOG_LEVEL_INF);

static int client_iface;

const static struct modbus_iface_param client_param = {
    .mode = MODBUS_MODE_RTU,
    .rx_timeout = 50000,
    .serial = {
        .baud = 9600,
        .parity = UART_CFG_PARITY_NONE,
        .stop_bits_client = UART_CFG_STOP_BITS_1,
    },
};

#define MODBUS_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_modbus_serial)

static int init_modbus_client(void)
{
    const char iface_name[] = {DEVICE_DT_NAME(MODBUS_NODE)};
    client_iface = modbus_iface_get_by_name(iface_name);
    int lres = 0;
    return modbus_init_client(client_iface, client_param);
}

void main(void)
{

    static uint8_t client = 1;
    int coil = 12;
    int err;

    bool stato = false;

    init_modbus_client();

    bool todo = true;
   
                                //node,coil,val
    modbus_write_coil(client_iface, 4, 12, true);

}

So I am trying to set coil 12 of slave 4 to true.

In modbus term this mean:

FC=5

ID=4

VALUE=FF00

CRC=6C4C

so needed symbol that have to be send di uart are: 40-5000-12-FF00-6C4C.

Via logic analyzer i verified that the trasmission is correct except that some bit are sent (number and shape change every time).

As you can see till DE is enabled (tx enable sent to rs 485 converter) is ok: all simbol are correct. the problem come after transmission.
I've been trying to dig into what's going on.
In a nutshell, I have verified that the modbus stack works perfectly, i.e., from the set coil command I get the correct modbus sequence and the same data is copied with a memcopy into the buffer of the uarte. the problem is that the uarte transmits other symbols that I do not understand by whom they are being queued.
With more detail:
modbus_write_coil(client_iface, 4, 12, true);
-->(modbus_client.c) mbc_send_cmd(ctx, unit_id, MODBUS_FC05_COIL_WR, NULL);  work fine
--> modbus_tx_wait_rx_adu  work fine
--> modbus_tx_adu(ctx); work fine
-->   modbus_serial_tx_adu(ctx)) 
-->        rtu_tx_adu(ctx);
ok
then from code:
tx byte = 8 so ok
crc 16 is correct 

cfg->uart_buf[0] = ctx->tx_adu.unit_id;
    cfg->uart_buf[1] = ctx->tx_adu.fc;
    tx_bytes = 2 + ctx->tx_adu.length;
    data_ptr = &cfg->uart_buf[2];

    memcpy(data_ptr, ctx->tx_adu.data, ctx->tx_adu.length);

    ctx->tx_adu.crc = crc16_ansi(&cfg->uart_buf[0], ctx->tx_adu.length + 2);
    sys_put_le16(ctx->tx_adu.crc, &cfg->uart_buf[ctx->tx_adu.length + 2]);
    tx_bytes += 2;

    cfg->uart_buf_ctr = tx_bytes;
    cfg->uart_buf_ptr = &cfg->uart_buf[0];
    LOG_HEXDUMP_DBG(cfg->uart_buf, cfg->uart_buf_ctr, "uart_buf");
    LOG_DBG("Start frame transmission");
    modbus_serial_rx_off(ctx);
    modbus_serial_tx_on(ctx);

then byte copy of buffer in uarte buffer as last but non least 
modbus_serial_rx_off(ctx);
modbus_serial_tx_on(ctx);
that mean 
uart_irq_tx_enable(cfg->dev);
so 
    z_impl_uart_irq_tx_enable(dev);
then:
api->irq_tx_enable(dev);
then...
in conclusion following the lines of code the modbus stack boxes the symbols correctly and passes them to the serial communication part.
Maybe it's just a matter of setting something up correctly.

Can you help me with this?
In my opinion it is something at the uarte level
  • in conclusion following the lines of code the modbus stack boxes the symbols correctly and passes them to the serial communication part

    If I read this correctly, what you are trying to write here is that the modbus requests to write some data which is going down to the backend uarte drivers. The transmit request from the uarte API also looks same with the right data and size, but when the uarte is transmitting the data on the pins, then the transmitted packets looks different than the one requested to send in the API?

    This seems strange and I have not seen this before. If you are very confident that the uarte drivers are being requested to send the right data but data on pins is wrong, then it most likely sounds like the issue with the pull configuration of the pins. I thought that each uarte pin pull configuration is set at the time of uart init, not sure how it goes with modbus libraries. PLease check if the uarte pins have the right pull configurations.

  • Hi Susheel and thanks for the support

    From my point of view I am sure that the thread I just read passes all and only the correct data into the array of data transmitted by the serial.
    Isn't it possible that there are other threads that queue data to be passed?

    I find it strange that it is a wrong pin setting: the initial part of the transmission is correct bit by bit, I just have the problem that additional bits are being transmitted and I don't understand who and how is queuing them.

    can you explain to me what you mean by pull configuration of the pins so that I can do the checks you kindly suggested?

    Best

  • Lorenz898989 said:
    Isn't it possible that there are other threads that queue data to be passed?

    It is possible that nRF Logger is using the same uart instance as you are using as the backend?

    Try to set RTT as backend instead of UART in your config file just to make sure that logs are not causing this


    CONFIG_LOG_BACKEND_RTT=y

    Also check which uart instance is being used as default zephyr console in your dts file?

    zephyr,console
    Make sure that your uart instance is not being used anywhere else in the device tree file.
Related