IMU and PWM Driver over I2C for NVIDIA Jetson TX1

Another couple of devices that will be needed for upcoming projects on the Jetson TX1 Development Kit are an IMU and a PWM driver for servo control. These devices can be interfaced over I2C. Looky here:


We have covered using the Bosch IMU BNO055 under ROS and the PWM/Servo Driver is based on a PCA9685 Breakout Board in earlier articles. This is just a short recap to discuss the differences between the earlier articles and this demonstration.


The parts used in the demonstration:


Both of these devices can interface with the Jetson TX1 using I2C. We have covered using I2C with the Jetson in an earlier article. In this demonstration, we use the same I2C pins as in the previous article, the Jetson TX1 J21 pins 27 (SDA) and 28 (SCL). These are I2C_GP1_DAT and I2C_GP1_CLK respectively, on I2C bus 1. Both the PCA9685 and BNO055 are wired from these signals, and both use the 3.3V supply from J21 Pin 1, and GND from J21 Pin 6.

Note: Here is the Jetson TX1 J21 header pinout for reference. The GPIO numbers have not been verified by a third party, so use those at your own risk, but the signals should be correct.

The wiring is straightforward. The 3.3V goes to VCC on both the BNO055 and PCA9685, as does GND. SDA from the Jetson goes to both breakout boards, as does SCL. In the demonstration both of the devices were placed on separate prototyping boards, and a USB cable was connected to connect the two. A USB A breakout board and micro USB B female breakout board were used to carry the I2C signal from one breadboard to the next. On the USB breakout boards, 3.3V is wired to VCC, GND is wired to GND, SDA is wired to D+, SCL is wired to D-. On the micro USB B breakout, the remaining signal (ID) is not used. The cable used is the Jetson programming cable.

Note that this is for demonstration purposes only, for an actual application some calculations should be done to find an appropriate wiring solution.


The demonstration software is available in the JetsonHacks Github RTIMULib repository. RTIMULib is originally from from richards-tech LLC. Here is an article which gives a deeper talk about IMU stuff on that website.
To install the demonstration:

git clone

then open a file browser and navigate to ‘./RTIMULib/Linux/JetsonTX1DemoGL’. Then open the file ‘’ with Qt Creator and compile the demo. Here’s an article we did a while ago on how to install Qt Creator.

After the file is finished building, go to where the executable file resides (this is dependent on how Qt Creator is configured) and execute the demo using ‘sudo’. For example:

$ sudo ./JetsonTX1DemoGL

At that point the demonstration should begin with the IMU orientation being displayed in a GUI, and the servos being positioned by the orientation of the IMU. Remember that this demonstration uses only two servos and is therefore a 2 Degree of Freedom (2 DOF) rig. That means that only two of the three axes will change the servo settings. In the demonstration the yaw (Z axis) and the roll change the servos.


Camera gimbals are typically controlled using input from an IMU, at which this demonstration begins to hint. Typically there is a known orientation where the user would like to point the camera. The IMU is mounted on the camera gimbal itself and reports back to a micro controller a pose. The micro controller then calculates the desired pose from the IMU pose, and positions the servos motors accordingly. Note that other types of motors can be used, such as the now more common gimbal motors, but the idea behind both are the same.

This type of servo setup can also be used for face tracking, though no IMU is needed in that case. A camera is mounted on the pan and tilt head. The camera takes a video feed and sends it to the Jetson which can then use a program such as OpenCV to detect faces in the image. Using this information, the Jetson can then position the servos so that the camera centers itself on the face that has been detected.


  1. Hey kangalow!

    I’ve been trying to run this and also RTIMULibDemoGL to test my BNO055. The BNO055 is connected on I2C bus 0 (pins 3 and 5 for SDA and SCL, respectively). I’m able to detect the device at address 0x28. However, when I try to run RTIMULibDemoGL, I get the error “Failed to open I2C bus 0”. Have you encountered this error before and do you have ideas for how to address it?


  2. Howdy folks,

    I am using the PCA9685 from a ROS node and I am running in the same issue where my ROS node doesn’t have permission to open /dev/i2c-* .

    While “sudo chmod a+rw /dev/i2c-*” works as a temporary get-around, eventually I would like something that just works without having to first change the permissions of the device file.

    Taking in mind that the executable is called from a ROS launch file and while I can use a “sudo launch prefix”, I don’t want the launch to be interrupted for entering a password, nor do I want to setup a passwordless sudo either.

    How does one normally go about solving “embedded permission issues” like these?

    Thanks in advance


  3. I finally got around to creating a udev rule as suggested by kangalow to set the I2C device permissions. Here are the details:

    First create a new rule file (my editor of choice is emacs, pick yours)
    $ sudo emacs /etc/udev/rules.d/50-myi2c.rules

    Then put in the following line:
    ACTION==”add”, KERNEL==”i2c-[0-1]*”, MODE=”0666″

    I had to reboot my JTX1 before it took effect.



  4. Hello,

    IMU is giving me more troubles than I want 🙂 first of all I2C rules in udev/rules.d folder don’t help. I created the document and added both the line suggested in one of the previous tutorials, and the line that Galto suggested, but neither is working. Only thing that works is manually typing “sudo chmod a+rw /dev/i2c-*”. But that’s not the main problem.

    Main problem is that rtimulib-ros doesn’t find IMU. I use Pololu AltIMU-10 v4, which is supported by RTIMULib, and RTIMULib library is installed, as well as rtimulib-ros, but when I launch the node, it gives error “No IMU found”. In RTIMULib.ini configuration file BusIsI2C=true, and I2CBus=1, while wiring is the same as proposed here.

    Any idea what I could do to diagnose the problem? Tried i2cdetect -y -r 1, but there is a bunch of stuff, and it doesn’t change regardless if wires are connected or not.

    • Ok, ignore my No IMU problem, I am just retarded 😀 Connection was loose and that’s why it didn’t see IMU. Now just udev rules to sort out…

  5. Did you ever sort out the udev rules ?
    I tried the $ sudo emacs /etc/udev/rules.d/50-myi2c.rules

    Then put in the following line:
    ACTION==”add”, KERNEL==”i2c-[0-1]*”, MODE=”0666″
    suggested by Galto but no luck. It only works with:“sudo chmod a+rw /dev/i2c-*”
    But I really want the launch file to run without having to do this.

Leave a Reply

Your email address will not be published.