Need ideas for UART pelase

orbitcoms
Posts: 141
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Need ideas for UART pelase

Postby orbitcoms » Tue Apr 13, 2021 4:08 am

Hi
I am working on a project that sniffs data packets on RS485 network. The packets are binary (so do not have a start/eot character delimited structure for parsing.

The packets are small (less than 20 bytes0 and Baud rate is 115200.

Currently I use this command below to receive data but it is not reliable (I am getting some packets received twice)
const int bytes_received = uart_read_bytes(rs485_uart, buf, 20, pdMS_TO_TICKS(10));

Is there a way to start receiving on first character and stop and flag received data when there is a gap in data of say 5ms? (ie. Use the gap between packets to delimit). The software will handle a part received packet as the data uses CRC-16 to validate.

Thanks

ESP_alisitsyn
Posts: 203
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: Need ideas for UART pelase

Postby ESP_alisitsyn » Wed Apr 14, 2021 7:04 pm

Hi @orbitcoms,

You can easily do this using UART timeout feature. Please take a look to ESP_MODBUS :
https://docs.espressif.com/projects/esp ... odbus.html
and its serial port module:
https://github.com/espressif/esp-idf/bl ... serial_m.c

The

Code: Select all

xMBMasterPortSerialInit()
function setup the UART and its event queue to receive the data with the gap timeout ~3.5T (symbols on current baud rate). In the vUartTask() on UART_DATA event you receive the data and the xEvent.timeout_flag is set when there is a gap between packets >= than you set in the

Code: Select all

uart_set_rx_timeout(ucUartNumber, SERIAL_TOUT_SYMBOLS);
.
For your 5ms timeout the SERIAL_TOUT_SYMBOLS should be equal 5ms = 52 symbols on 115200 baudrate.
So, once the xEvent.timeout_flag is triggered you can just read your packet from ring buffer into data_buffer:

Code: Select all

int packet_size = uart_read_bytes(ucUartNumber, (uint8_t*)data_buffer, xEvent.size, RX_BUF_TOUT_TICKS);
Additionally you should just setup UART pins and set RS485 mode:

Code: Select all

err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
This approach is checked and will work reliably to sniff the RS485 traffic on the bus.

orbitcoms
Posts: 141
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: Need ideas for UART pelase

Postby orbitcoms » Wed Apr 14, 2021 10:03 pm

Thank you for the information.

This looks like exactly what I was after.

orbitcoms
Posts: 141
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: Need ideas for UART pelase

Postby orbitcoms » Thu Apr 15, 2021 4:05 am

Below is my implementation so far, does this look correct?

I need to access the data from another C module in my code so have used a global buffer for now but would later like to learn how to make this available in the other module without being global).

The other module has a task that waits for a "data_ready" semaphore to start processing received info.

Code: Select all

QueueHandle_t uart_queue;

uint8_t rx_buffer[30];

void uart_event_task(void *params)
{
    uart_event_t uart_event;

    while(1)
    {
        if(xQueueReceive(uart_queue,&uart_event,portMAX_DELAY))
        {
            switch(uart_event.type)
            {
                case 
                  UART_DATA:
                    if(uart_event.timeout_flag)
                    {
                      uart_read_bytes(rs485_uart, rx_buffer, uart_event.size,UART_BREAK_TIME);
                      xEventGroupSetBits(evtGrp, data_ready);
                    }
                break;

                default:
                break;
            }
        }
    }
}

void init_rs485_uart(void)
{
    const uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE};

    uart_param_config(rs485_uart, &uart_config);
    uart_set_pin(rs485_uart, RS485_TXD_PIN, RS485_RXD_PIN, RS485_EN_PIN, UART_PIN_NO_CHANGE);
    ESP_ERROR_CHECK(uart_driver_install(rs485_uart, RX_BUFFER_SIZE,0,UART_QUEUE_SIZE,&uart_queue,0));
    ESP_ERROR_CHECK(uart_set_mode(rs485_uart, UART_MODE_RS485_HALF_DUPLEX));
    uart_set_rx_timeout(rs485_uart,UART_BREAK_TIME);
    uart_set_always_rx_timeout(rs485_uart,true);
    xTaskCreate(uart_event_task,"uart event task",2048,NULL,10,NULL);
}

ESP_alisitsyn
Posts: 203
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: Need ideas for UART pelase

Postby ESP_alisitsyn » Thu Apr 15, 2021 7:20 am

I need to access the data from another C module in my code so have used a global buffer for now but would later like to learn how to make this available in the other module without being global).
Refer: https://github.com/espressif/esp-idf/bl ... os/queue.h
You can create the structure which will keep the pointer to buffer in your serial module (A) with actual size of received data, flags and other required information, + handler to semaphore to lock buffer in serial module (A) while processing is not completed. Then create queue

Code: Select all

xQueueCreate()
to transfer this strucure. After this you can send the structure

Code: Select all

xQueueSend()
to your module (C), which will use the

Code: Select all

 xQueueReceive()
with infinite timeout waiting data from your module (A). Once the module receive the queue your moddule (C) can process this.
Other approach is to use ring buffer: https://github.com/espressif/esp-idf/tr ... sp_ringbuf

Did not explain details but hope approach is clear.

It looks like you are trying to create sniffer for DMX512 protocol or something similar.

orbitcoms
Posts: 141
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: Need ideas for UART pelase

Postby orbitcoms » Thu Apr 15, 2021 7:44 am

Thanks again. I'll looking into using queue send and receive.
I now have the routine running and works like a charm.

It is not for dmx project but for my own project. Receiving byte when no characters for a set time (character times) rather than waiting for a packet for a set time. Because the data does not have delimiters and was asynch in nature, I could not prevent the old handler from missing packets.

I have been previously programming the Cypress 5LP processor using very sequential code. Now I have started with ESP32, I love it. Lots of performance and the freertos is easy to implement. I installed the esp-idf extension in VScode and that latest updates seem to work quite well and save me going in and out of Windows to command prompt.

ESP_alisitsyn
Posts: 203
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: Need ideas for UART pelase

Postby ESP_alisitsyn » Thu Apr 29, 2021 12:08 pm

That is very good that you find the good solution and like the ESP32. It is little bit untipical microcontroller compare to other micros. Good luck with your projects! Don't hesitate to ask again here.

Who is online

Users browsing this forum: MicroController and 101 guests