JetsonHacks

Jetson Nano – Using I2C

A simple way to control Servo Motors on the NVIDIA Jetson Nano Developer Kit is to connect the Jetson Nano via I2C to a PWM Driver. Looks here:

Jetson Nano I2C

Background

There are four types of serial communication ports on the Jetson Nano. The most obvious is USB, which is where you plug in the mouse and keyboard. The other three are hidden away in the headers on the board.

We’ve talked about Universal Asynchronous Receiver-Transmitter (UARTs) before (one of which is the serial console). The Jetson Nano has two, one on the J44 Serial Port header, and one on the J41 Expansion Header.

There are also provisions for Serial Peripheral Interface (SPI) ports. In the default Nano Image configuration, the Jetson Nano does not have SPI port access. However, the device tree can be reconfigured for accessing SPI through the J41 Expansion Header. In the Jetson Nano J41 Pinout, NVIDIA recommends placement for two SPI ports.

Note: You may also hear the J41 Expansion Header referred to as the GPIO Header. The two terms are interchangeable.

The remaining serial ports are Inter-integrated Circuit (I2C). The Inter-integrated Circuit (I2C) Protocol goes by various names depending on who you talk to, “I squared C”, “I two C” or “I I C”. I2C is intended for short distance communication within a single device. One of the reasons that it is popular with the maker crowd is that it only requires two wires (the “data” and the “clock”) along with power and ground to get functioning.

In order to control Servo Motors, we use Pulse Width Modulation (PWM). The Jetson Nano has the capability of generating two PWM pulses on the J41 Header. However, you need to reconfigure the device tree to make these signals available on Pins 32 and 33. A simpler way is to use an external piece of hardware.

For our demo, we use a PCA9685 12-bit PWM/Servo Driver. Using only two pins, we can control 16 free-running PWM outputs. You can even chain up 62 breakouts to control up to 992 PWM outputs! The PCA9685 breakout board is a nice little application specific micro controller for servo control.

Parts

In the video, we use several different pieces of hardware. Here’s a partial list:

For the demo, we also use a WiFi card and game controller. Here’s an article about how to install those.

Software Install

Here we will be using the Adafruit ServoKit Library. This is a Python library built on top of the Jetson.GPIO library. There are several I2C libraries available. For example, if you are using C, C++ or Python you can use libi2c for low level access to I2C.

On the JetsonHacksNano account on Github, there is a ServoKit repository. Clone the repository, switch to that repositories directory and install the adafruit-circuitpython-servokit library:

$ git clone https://github.com/JetsonHacksNano/ServoKit
$ cd ServoKit
$ ./installServoKit.sh

This installs the ServoKit library and also sets up the I2C and GPIO permissions so that we can run programs from user space. GPIO permissions are added to support the underlying Jetson.GPIO library.

Note: The group changes do not take effect until login. You must logoff/login or reboot the computer for the changes to take effect.

Demo 1

In the default Jetson Nano Image, there are two I2C ports available on the J41 Header. From the Jetson Nano J41 Pinout :

Note: Before wiring the Jetson, make sure that the power is disconnected. When the power is plugged in, the power and ground rails on the headers are always live, even if the processor itself is off.

For the first demo in the video, we wire Bus 1:

A 5V 4A power supply is connected to the PCA 9685. The SG90 micro server is connected to port 0 of the PWM outputs. Note that the GND signal is towards the outside edge of the board, the control signal is towards the center of the board.

After wiring the board, plug the Jetson in. Once the Nano is up and running, open a terminal and execute:

$ i2cdetect -y -r 1

The default address of the PCA9685 is 0x40 (this is hexadecimal 40). You should see an entry of ’40’ in the addresses listed. If you do not see the entry, then the wiring is probably incorrect. When the address does not show up, then you will not be able to use the device. Note: You can change the default address of the PCA9685, so you will need to take that into account when you check the device visibility.

We are now ready to run our first demo:

$ python3
>>> from adafruit_servokit import ServoKit
>>> kit = ServoKit(channels=16)
>>> kit.servo[0].angle=137
>>> kit.servo[0].angle=25
>>> quit()

Our servo should move to the appropriate angle when we command it.

Demo 2

Demo 2 is a little more involved. After powering down and unplugging the Nano, we wire up the PCA9685 and add the pan and tilt servo connections:

Here’s the full wiring diagram:

Dual Servo Wiring

J41 Pins 27 and 28 on the Jetson Nano conenct to I2C bus 0. Check to make sure that we can see 0x40 on IC2 Bus 0:

$ i2cdetect -y -r 0

Make sure that the game controller is paired to the Jetson Nano as described in the Jetson Nano Wifi Article (also shown in the video). You can run jstest-gtk to make sure everything is happy.

Then you are ready to run the demo:

$ python3 servoPlay.sh

After initialization (this takes a few seconds), you should be able to control the pan and tilt servos with the game controller. The left joystick in the X direction controls the bottom servo. The right joystick in the Y directions controls the top servo.

You should look through the servoPlay.sh script for insight on how all of this fits together. Also, we demonstrate the ServoKit ‘throttle’ command, which is useful for controlling continuous servos and the similar electronic speed controllers for motors.

Conclusion

This article is more complicated than the actual code and wiring itself. Get ahold of the parts, wire them up, and go play!

Notes

The Jetson Nano is running L4T 32.1 with no modifications.