Need ideas for UART pelase
Need ideas for UART pelase
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
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
-
- Posts: 203
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: Need ideas for UART pelase
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 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 .
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:
Additionally you should just setup UART pins and set RS485 mode:
This approach is checked and will work reliably to sniff the RS485 traffic on the bus.
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()
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);
Code: Select all
err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
Re: Need ideas for UART pelase
Thank you for the information.
This looks like exactly what I was after.
This looks like exactly what I was after.
Re: Need ideas for UART pelase
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.
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);
}
-
- Posts: 203
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: Need ideas for UART pelase
Refer: https://github.com/espressif/esp-idf/bl ... os/queue.hI 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).
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()
Code: Select all
xQueueSend()
Code: Select all
xQueueReceive()
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.
Re: Need ideas for UART pelase
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.
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.
-
- Posts: 203
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: Need ideas for UART pelase
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: Bing [Bot] and 137 guests