Odrive UART communication failure[Fixed But ...]

Hello ODrive Community,

I have been struggling for a long time with a persistent “UART communication failure” on my oDrive v3.6 board running firmware version 0.5.6. The issue would occur intermittently, and the only temporary solution was to perform a hard reset of the board.

After extensive troubleshooting, I decided to modify the firmware. The UART communication failures have completely disappeared since I implemented the change below.

Here is the code I modified in :

interface_uart.cpp :  
osThreadDef(uart_server_thread_def, uart_server_thread, osPriorityNormal, 0, stack_size_uart_thread / sizeof(StackType_t) /* the ascii protocol needs considerable stack space */);
Change to ->
osThreadDef(uart_server_thread_def, uart_server_thread, osPriorityRealtime, 0, stack_size_uart_thread / sizeof(StackType_t) /* the ascii protocol needs considerable stack space */);
............................................................
board.cpp :
std::array<Axis, AXIS_COUNT> axes{{
    {
        0, // axis_num
        1, // step_gpio_pin
        2, // dir_gpio_pin
        (osPriority)(osPriorityHigh + (osPriority)1), // thread_priority
        encoders[0], // encoder
        sensorless_estimators[0], // sensorless_estimator
        controllers[0], // controller
        motors[0], // motor
        trap[0], // trap
        endstops[0], endstops[1], // min_endstop, max_endstop
        mechanical_brakes[0], // mechanical brake
    },
    {
        1, // axis_num
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 5
        7, // step_gpio_pin
        8, // dir_gpio_pin
#else
        3, // step_gpio_pin
        4, // dir_gpio_pin
#endif
        osPriorityHigh, // thread_priority
        encoders[1], // encoder
        sensorless_estimators[1], // sensorless_estimator
        controllers[1], // controller
        motors[1], // motor
        trap[1], // trap
        endstops[2], endstops[3], // min_endstop, max_endstop
        mechanical_brakes[1], // mechanical brake
    },
}};
Change to ->
std::array<Axis, AXIS_COUNT> axes{{
    {
        0, // axis_num
        1, // step_gpio_pin
        2, // dir_gpio_pin
        osPriorityHigh, // thread_priority
        encoders[0], // encoder
        sensorless_estimators[0], // sensorless_estimator
        controllers[0], // controller
        motors[0], // motor
        trap[0], // trap
        endstops[0], endstops[1], // min_endstop, max_endstop
        mechanical_brakes[0], // mechanical brake
    },
    {
        1, // axis_num
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 5
        7, // step_gpio_pin
        8, // dir_gpio_pin
#else
        3, // step_gpio_pin
        4, // dir_gpio_pin
#endif
        osPriorityHigh, // thread_priority
        encoders[1], // encoder
        sensorless_estimators[1], // sensorless_estimator
        controllers[1], // controller
        motors[1], // motor
        trap[1], // trap
        endstops[2], endstops[3], // min_endstop, max_endstop
        mechanical_brakes[1], // mechanical brake
    },
}};

This change has proven to be a stable fix for the communication issue. However, I am not entirely certain about the potential side effects.

My question for the experts here is: **Could this modification negatively impact the motor’s performance or behavior in any way?

Hi!

Yes, I think this could have some side effects regarding motor performance, however it’s very difficult to tell.

What’s the actual symptom of the UART/communications failure? Is it dropped messages? Or just a longer reply time? I can only see increasing the thread priority as helping with faster response time / higher incoming message processing bandwidth. But UART is frankly not a good choice if you need fast communication, that’s what CAN is for.

Thank you for your replies. Let me provide some more specific details about my setup and the failure mode, which might help with the analysis.

My Communication Workflow:

My standard process for communicating with the oDrive is as follows:

  1. ​I send a command to the oDrive.
  2. ​I wait for a fixed 30 ms delay.
  3. ​I then read the response data back from the oDrive for use in my application.

Specifics of the “UART Communication Failure”:

To be more precise, the failure isn’t data corruption; it’s that the oDrive’s response (TX) line completely stops sending any data.

​What’s very strange is that the communication still works perfectly in one direction (from my controller to the oDrive). For example, even after the failure has occurred:

  • ​If I send a command to request AXIS_STATE_CLOSED_LOOP_CONTROL (state 8), the motor engages correctly.
  • ​If I send a command to request AXIS_STATE_IDLE (state 1), the motor disengages as expected.

​However, any command that requires the oDrive to send data back (like requesting the current state or other feedback) receives no response at all.

​This one-way communication failure is the exact state that I could only recover from with a hard reset, prior to oDrive firmware modification.

​I hope this additional information provides more clarity. Thank you again for your help!

The axes array is initialised with the following thread priorities:
Axis 0: osPriorityHigh + 1 (which is likely osPriorityRealtime)
Axis 1: osPriorityHigh
UART thread: osPriorityNormal

In my opinion, sometimes the two high-priority motor control threads are consuming all the CPU time, preventing the normal-priority UART thread from ever running. When the UART thread can’t run, it can’t process transmit-complete events, and the entire communication pipeline stalls.

Hello. I am experiencing the exact same issues.

I have a 56v Flipsky odesc 4.2 (odrive 3.6 clone) with 0.5.6fw version. It completely stops sending data to arduino after 5-20 seconds of active polling, no matter the frequency (10-500hz).

I have tried different arduino/esp32 boards on different baud rates, different firmware versions (both official and unofficial) and trying to make my configs from scratch like 4 times.
I even wrote a custom arduino library to replace official ODriveArduino.

I am very tired and frustrated and i want to complete my project. What options do i have?

Unfortunately they run some weird hacked up ODrive firmware on those, which we can’t support. I’d recommend reaching out to the manufacturer for support. Alternatively, you may want to get a logic analyzer or ST-Link debugger and jump in yourself, but that’ll take some work.

Thank you for the reply. Yes, i am informed that flipsky uses some obscure modified firmware versions on those, but the issue is persistent across all of firmware versions i’ve tried, both flipsky provided and downloaded from odrive cdn,

Also somehow the bootloader is also screwed up on my board so i was using ST-Link instead of recommended DFU mode. But the issue is unrelated to that.

I am saying that TX line stops any communication because i’ve seen it with an oscilloscope. I do have a logic analyzer, and if you want i can make a setup and send you packet captures.

Edit: pulseview packet captures are available at https://zamonary1.ru/static/pw-odesc-uart-fault-filter (sorry, discourse doesn’t allow .zip attachments for new accounts.)
Edit2: packet captures were made with esp32-c3 connected via UART. Unfortunately right now i have an unofficial flipsky firmware, but as i said earlier the issue is exactly the same.

Hm, it might be some weird hardware issue. Unfortunately I think only the manufacturer can really help with this one, unless you want to try doing some actual debugging with the ST-Link. Those cheap clones are almost never worth the time, in my experience.

By the way, i tried compiling the firmware on 2 separate systems (running arch and alpine) and they both fail with the same error. Is there any way i can fix that?

 ~/ODrive    Firmware  make                         Пт 09 янв 2026 21:08:17
board version: v3.6-56V
Firmware version 0.5.6-dev (fw-v0.5.6-4-gf9b5419c)
* 102) python -B interface_generator_stub.py --definitions odrive-interface.yaml --template fibre-cpp/function_stubs_template.j2 --output autogen/function_stubs.hpp
/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py:489: SyntaxWarning: invalid escape sequence '\.'
  property_value_type = re.findall('^fibre\.Property<([^>]*), (readonly|readwrite)>$', prop['type'].fullname)
Traceback (most recent call last):
  File "/home/zamonary1/ODrive/Firmware/interface_generator_stub.py", line 8, in <module>
  File "/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py", line 588, in <module>
    raise Exception(err.message + '\nat ' + str(list(err.absolute_path)))
Exception: None is not of type 'object'
at []
 *** tup messages ***
 *** Command ID=402 failed with return value 1
* 101) python -B interface_generator_stub.py --definitions odrive-interface.yaml --template fibre-cpp/type_info_template.j2 --output autogen/type_info.hpp
/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py:489: SyntaxWarning: invalid escape sequence '\.'
  property_value_type = re.findall('^fibre\.Property<([^>]*), (readonly|readwrite)>$', prop['type'].fullname)
Traceback (most recent call last):
  File "/home/zamonary1/ODrive/Firmware/interface_generator_stub.py", line 8, in <module>
  File "/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py", line 588, in <module>
    raise Exception(err.message + '\nat ' + str(list(err.absolute_path)))
Exception: None is not of type 'object'
at []
 *** tup messages ***
 *** Command ID=406 failed with return value 1
* 100) python -B interface_generator_stub.py --definitions odrive-interface.yaml --template fibre-cpp/interfaces_template.j2 --output autogen/interfaces.hpp
/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py:489: SyntaxWarning: invalid escape sequence '\.'
  property_value_type = re.findall('^fibre\.Property<([^>]*), (readonly|readwrite)>$', prop['type'].fullname)
Traceback (most recent call last):
  File "/home/zamonary1/ODrive/Firmware/interface_generator_stub.py", line 8, in <module>
  File "/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py", line 588, in <module>
    raise Exception(err.message + '\nat ' + str(list(err.absolute_path)))
Exception: None is not of type 'object'
at []
 *** tup messages ***
 *** Command ID=400 failed with return value 1
*  99) python -B interface_generator_stub.py --definitions odrive-interface.yaml --generate-endpoints ODrive3 --template fibre-cpp/endpoints_template.j2 --output autogen/endpoints.hpp
/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py:489: SyntaxWarning: invalid escape sequence '\.'
  property_value_type = re.findall('^fibre\.Property<([^>]*), (readonly|readwrite)>$', prop['type'].fullname)
Traceback (most recent call last):
  File "/home/zamonary1/ODrive/Firmware/interface_generator_stub.py", line 8, in <module>
  File "/home/zamonary1/ODrive/tools/fibre-tools/interface_generator.py", line 588, in <module>
    raise Exception(err.message + '\nat ' + str(list(err.absolute_path)))
Exception: None is not of type 'object'
at []
 *** tup messages ***
 *** Command ID=404 failed with return value 1
 [                   ETA~=8s  Remaining=99  Active=0                    ]   3%
 *** tup: 4 jobs failed.
make: *** [Makefile:33: all] Error 1

@Surasak_Sudaiam i have created a new fork of ODrive firmware, with your fixes included. You can take a look.
Also, there is a firmware release with you patches applied.
Don’t worry, i did all the proper attribution. If you want you can open a PR to add link to your socials.