I2C communication Arduino <-> ODrive


Hello guys,

I am a new oDrive (v3.5, 48V) user, and really happy with how it works and how well communication goes with the native protocol and the ASCII protocol.

I’ve found this Arduino I2C library, but can not wrap my head around how to implement it, so until now I haven’t tried if it works from scratch because I do not know what it will be doing.

Via the oDrive Tool, I have activated I2C with

enable_i2c_instead_of_can = True

but still get back a

  addr = 0 (int)
  addr_match_cnt = 0 (int)
  rx_cnt = 0 (int)
  error_cnt = 0 (int)

I also tried to change the address manually by typing

In [12]: odrv0.system_stats.i2c.addr = 104

which is not a valid command.

Would appreciate any advice to get I2C running, so I can try out the commands specified in the Arduino library.
Unfortunately I am not familiar with STM32 programming.

Thank you very much!


Just a guess, but did you try rebooting your ODrive? Found this here: https://github.com/madcowswe/ODrive/blob/3113aedf081cf40e942d25d3b0b36c8806f11f23/Firmware/communication/communication.cpp#L157.

Maybe try “odrv0.reboot()”. Otherwise, reach out to those on the “Support” channel on the discord chat (here: https://discordapp.com/channels/369667319280173067/369678934985408524).


Makes sense! :slightly_smiling_face: Now it works. Thank you very much.


Ok now I will come up with some new questions.

  1. In the Discourse #support chat, Oskar mentioned that one has to ‘desolder the can tranciever and make two bridge connections’, and I understand that this is for I2C. Right?
    So it is impossible to use I2C out of the box? Or am I getting something wrong?

  2. I’ve tried using the I2C. The odrivetool I2C stats are

    addr = 111 (int)
    addr_match_cnt = 0 (int)
    rx_cnt = 0 (int)
    error_cnt = 0 (int)

and when using the available Arduino I2C library and the example, so I guess I have to put

byte odrive_num = 7;

because 111 (dec) = 1101111 (bin) = 1101xxx + 111 (bin) where 1101000 is defined in Arduino/ArduinoI2C/odrive.c

static constexpr const uint8_t i2c_addr = (0xD << 3); // write: 1101xxx0, read: 1101xxx1

Anyway I also tried with address odrive_num = 6, leaving out the read bit (LSB = 0).

Whatever address I put, I get the following result: Oscilloscope shows exactly the same signal (the 100 kHz clock signal) on both lines, exactly the same amplitude and phase.
Ia am using a Mega2560, with connections


Connected to another Arduino, my Mega2560 talks proper I2C :slight_smile:

I tried also to switch the odrive on-board switch to CAN NO R, which just gave worse results (no clk at all).

The reason why I want to use I2C is a position update rate higher than 200 Hz for two motors, which I achieved with 1,000,000 Bd/s UART via ASCII protocol.

A hint where to work on or where I missed something would be awesome!!


With respect to your #1, I’d say that: yeah, he means you’d need to desolder the CAN IC (using a heat gun), then bridge the CAN H and L connections, such that when you hook up the CAN headers (schematic here: https://github.com/madcowswe/ODriveHardware/blob/master/v3/v3.5docs/schematic_v3.5.pdf), you are directly addressing the pins on the STM32 (which you enable using the function you previously experimented with). So…no, the I2C doesn’t work right out of the box - it requires some modification.

I’m not sure how to get it to work any further, as I haven’t played around with it yet or investigated it much myself. I’m going to play with it a bit right now, and spend more serious time looking into it tomorrow. I’m interested in perhaps using I2C to talk to multiple ODrives from a Mega, and am curious if that level of functionality exists and would work.