UART Communication: Maximum frequency ? Timeout?

Hi Guys !

I am trying to communicate with my ODrive via UART with a Raspberry pi. I basically copied the Arduino code that is proposed by @madcowswe here. I mostly use the setcurrent function as explained in the ascii protocol and I also wish to get the encoder position.
I am meeting a timeout issue (from the readString() function) :

  • I can send the current command at a quite frequency (1kHz) to ODrive and everything works perfectly fine.
  • If I want to get the encoder position (sending the request at 1kHz), while the motor is not turning, I receive the position and then I get a timeout response after one or two seconds, respectively when the motor is turning, it lasts a bit longer before I get a timeout. I tried at lower frequencies, it lasts longer but also ends up in a timeout.

After having a timeout my only option in order to restart a communication via UART is to shut the power down and restart it.

So here is my question, is there a maximal frequency for the UART communication ?
Has anybody an idea to what could cause this ?

Thanks a lot !

Maybe we are out of CPU-time and the read command is perhaps more expensive than the writes. I have seen some issues with intermittent spikes in CPU usage that I don’t know where they are coming from, and I intend to dig into that eventually.

Meanwhile, you can try to slow down the PWM frequency (the control loop frequency is tied to this), by increasing TIM_1_8_PERIOD_CLOCKS to 12000 here.

Thanks for the tip, I did try this but it still ended up in a timeout.

I made some tests directly in the code to see if I could find any way to make it work, and finally, in interface_uart.cpp in the uart thread, I commented the lign that checked for error so that the receive DMA is always restarted (see code below).

    // Check for UART errors and restart recieve DMA transfer if required
  //if (huart4.ErrorCode != HAL_UART_ERROR_NONE) {
       HAL_UART_AbortReceive(&huart4);
       HAL_UART_Receive_DMA(&huart4, dma_rx_buffer, sizeof(dma_rx_buffer));

//}

And also, I observed that the the new_rcv_idx did not change at all after some time (I observed that before changing the code above).
So I also added a = in the test below to be sure that the stream was processed anyway:

if (new_rcv_idx <= dma_last_rcv_idx) {
uart4_stream_input.process_bytes(dma_rx_buffer + dma_last_rcv_idx,
UART_RX_BUFFER_SIZE - dma_last_rcv_idx, nullptr); // TODO: use process_all
ASCII_protocol_parse_stream(dma_rx_buffer + dma_last_rcv_idx,
UART_RX_BUFFER_SIZE - dma_last_rcv_idx, uart4_stream_output);
dma_last_rcv_idx = 0;
}

Now it seems to work, even if I don’t really know why !

@CFluck I am new to programming and work mostly from tearing apart other peoples code to get it to work for my application. I was hoping I could see the code you are using to control the ODrive from PI through UART.

I am going to be trying to control it via a Jetson TX2, but I figured a Raspberry Pi is the closest thing in common use. Thanks!