Help Cool Research - I2C Driver SOS


Sorry this is such a long post, but it there’s a lot of context for these questions, so I’m just trying to get all of the relevant info out from the beginning. I’m a student at MIT working on a research plane for testing cutting edge ultra-short takeoff techniques. One of the key data points that we need for our analysis is motor RPM.

Of course most available brushless motor RPM sensors are not Pixhawk compatible, at least in the quantity that we need, and that doesn’t address our other sensors that we would like to integrate.

High Level Plan

  • Two Arduinos read RPM and thermocouple data coming from outboard sensors
  • Each Arduino connects to a Pixhawk as an I2C slave
  • Pixhawk reads each Arduino at some x > 1 Hz
  • Pixhawk logs and also transmits this data via MAVLINK

Already Done Stuff

  • Arduino reading sensors and writing to I2C
  • I2C::read(), afaik (as far as I know)
  • I2C::ioctl(), afaik
  • I2C::probe(), currently unused
  • Config variable that has values
    • 0 for disabled
    • 1 for a single Arduino at some ARDUINO_ADDRESS_0
    • 2 for a single Arduino at some ARDUINO_ADDRESS_1
    • 3 for two Arduinos at both of the above addresses
  • CMakeLists.txt similar to the sf1xx driver


  1. Am I correct that messages sent to the DEBUG_VALUE topic will get forwarded on to QGroundControl via Mavlink?
  2. How do I keep track of which driver instance is talking to which Arduino? Do I make a single class that runs both and just use switches everywhere?
  3. Do I need to do anything beyond an empty definition for probe() under the assumption that the Arduinos are working properly?
  4. init() likely only needs to call the I2C constructor and set default values for any internal state I want?
  5. Why do the other I2C drivers use ring buffers to store the messages published to uORB?
  6. Are there other big “gotchas” that I should be aware of to get this driver working asap?


If you want to just take a look at the code itself, I’ve get a fork of PX4 at:

My stuff is in src/drivers/arduino. Excuse the general sad state of my C++.

Yay, I like this question! There is context, there is information, there are questions, there is source code (supposedly :smile:).

I don’t see it. Is it in a branch?

Now let me try to answer your questions:

  1. I think so. Do they not show up in the Analyze or MAVLink Inspector widget?

  2. I would add a cli argument where you select the instance on startup of the driver.

  3. probe() is usually used as a first step to make sure the device and driver can talk to each other. So it’s usually just some simple handshake/whoami call. But anyway if you leave it out because you don’t implement it and it works anyway, then that’s fine.

  4. I’d say so, yes.

  5. Good question. This might be leftovers from earlier times where sensor values were also taken from the drivers using read(), and they are needed if the driver needs to read in bursts before publishing. I don’t think you need to necessarily implement it.

  6. I usually like the simple whoami call and would start there to make sure it works but that’s up to you. Also, make sure you select the bus speed correctly on both sides.

Thanks for taking a look! Yes, I’m on a different branch called “mit-16821”.

Ok got it.

One thing that I see in your code is that you’re missing the orb_advertise call here:

It should look something like that:

A followup question on the driver initialization: how do I control which drivers are loaded and with what arguments? Is there some config file for that?

It’s all part of the startup script, see:


Thanx for the topic and all the data that has been made available. I am also working on a similar project which aims to use an Arduino UNO which will use I2C comms to set the desired RPM for motor thrust output. The goal is to test an airframe and mixer driver pipeline for experimental airframe designs.

I have come to understand the Mixer file structure and control groups and now it is time to work on the I2C. I have looked at the example code on both the PX4 developer guides and also the branch listed here: JMurph2015/ PX4-Firmware.

Process Flow

  • Issue a RPM command to an Arduino UNO via UART. (Coded)
  • The UNO must then update the RPM topic in the uOrb via I2C. (Help please :sweat_smile:)
  • Control logic transfers the data to the control group. (Still working on this)
  • Mixer converts the signal. (Coded)
  • ESC drives the motor. (Wired)

I am hoping that you can help me with some topics I don’t understand. Please keep in mind that I am new to PX4 and still learning.


  1. The Arduino driver you created, where do we start the driver? (Maybe PX4-Firmware/boards/px4/fmu-v4/init/ rc.board_sensors if you use the fmu-v4 build?)

  2. Since the Arduino is a slave, then I presume the PX4 connects once and keeps the bus open for that one device?

Again thank you for all the work you have put in thus far, hope I can get up to speed with it too.