Jetson Nano GPIO

We use GPIO to talk to external devices on the NVIDIA Jetson Nano. Looky here:

Introduction

One of the nice things about the Jetson Nano is that there is an expansion header which is useful for General Purpose Input Output (GPIO). You may have thought about turning a light on or off as the output of your program, or would like a read a press from an external button. That’s where GPIO is useful!

In this article, we’ll cover how to control GPIO output by turning a Light Emitting Diode (LED) on and off. This is probably one of the most basic examples on how to use GPIO.

As you may have heard, the GPIO pin layout on the Jetson Nano is compatible with the 40 pin layout of a Raspberry Pi (RPi). Also, there is a Jetson GPIO python library which is mostly compatible with RPi.GPIO. Jetson.GPIO is preinstalled in the standard Jetson Nano disk image.

With that said, note that the electrical characteristics of the GPIO expansion header on the Jetson Nano are not the same as a Raspberry Pi. In particular, the Jetson Nano flows much less current on the GPIO pins than the RPi.

For example, a RPi can drive a LED directly from the GPIO pins, whereas a Jetson leaves the LED dimly lit because there is not enough current. The Jetson needs a little help. As you will see, a switching transistor comes to the rescue!

There are a couple of ways to use this article. The first way is to work your way through everything, and use your pearl catcher to grab the wisdom being thrown about. If you’re more pragmatic, jump around to the bits and pieces you find useful. Be forewarned that there be maths here, we’re using electricity, and things could go horribly wrong if you’re not careful. Other than that, play and have some fun.

LED Circuit

Parts List

Here are the parts we are going to use in this circuit:

  • A 5mm red LED
  • A P2N2222 Transistor
  • 1 330Ω resistor
  • 1 10kΩ resistor
  • Hookup wire
  • A breadboard to connect everything together

The easiest way to acquire the parts is to get a collection, such as this “Electronic Fun Kit“. There are many of these types of kits available for experimenting with Raspberry Pi and Arduinos. You may also want to acquire some extra resistors or such. Sparkfun and Adafruit are good sources.

It is also useful to have a multimeter on hand. I use a pretty hard core one, but if you’re just starting out you can get a less expensive one instead.

LEDs

If you want a little more in depth introduction to LEDs, checkout “A detailed introduction on how to use LEDs” This should give you a good feel for what we are doing here.

Here’s the thing about LEDs. They don’t use power linearly. Like little pigs they’ll suck so much current up that they will destroy themselves in a puff of magic smoke if left to their own devices. But we can make sure that does not happen.

By adding a resistor (in this application it is called a current limiting resistor), we will limit the amount of current that the LED is able draw. We select the resistor based on Ohm’s Law.

Oh My! Maths …

One of the fundamental rules in electronics is Ohm’s law. You have probably heard about it. Specifically:

Ohm’s law states that the current through a conductor between two points is directly proportional to the voltage across the two points. Introducing the constant of proportionality, the resistance,[1] one arrives at the usual mathematical equation that describes this relationship:[2]

where I is the current through the conductor in units of amperesV is the voltage measured across the conductor in units of volts, and R is the resistance of the conductor in units of ohms. The main point to remember is that current, voltage and resistance are all related.

And what does that mean to us? In short, we can set the limit on the amount of current that the LED can actually draw by cleverly selecting a proper resistor. This is because a resistor’s current value responds directly proportional to the applied voltage. All we need to know is a couple of things about the LED to calculate the proper resistor value.

First, LEDs have what is called a Forward Voltage, which is basically the minimum voltage difference between the cathode and anode (different terms for this is the minus and plus sides) that you need to supply to an LED. Another thing that we need for our calculation is the Forward Current which is the maximum amount of current that the LED is able to handle continously.

In the LED data sheets, you will see Forward Voltage as $V_F$ and Forward Current as $I_F$.

The LED in this example has a Forward Current of 20mA and a Forward Voltage of 2.0V. We will be using the Jetson Nano 5V pin to drive the LED, so we subtract the Forward Voltage from the 5V and divide by 20mA (0.020A), just like Ohm’s Law tell us to:

We get a result of 150Ω This is the value to flow the maximum amount of current that is safe for this particular LED. A couple of things to note here. First, resistors don’t tend to come in a 150Ω flavor. Even if they did, they have some tolerance built in, which indicates they can have some variance from the actual stated resistance. This is usually a small percentage, but smaller inexpensive resistors may be around 20%! This means that the resistor can be in a range of 120-180Ω for one rated at 150Ω. Because we live in a modern age, we can use an online calculator to help us for this calculation.

Second:

Tyrell:
The light that burns twice as bright burns half as long – and you have burned so very, very brightly, Roy.

Blade Runner, 1982

Maybe not quite as drastically as the movie quote, but running an LED at maximum current will effect its lifespan. Typically people end up using between 220 and 470Ω resistors for this application. We will be using a generic 330Ω.

About that Transistor

That takes care of protecting our little LED friend. But as we were talking about, because a Jetson Nano GPIO pin is not strong enough to power the LED by itself it needs a little help. We will use a Transistor which will act as a switch to provide current to the LED.

Transistors amplify power. We will be using a Bipolar Junction Transistor (BJT). BJTs are available in two flavors, PNP and NPN. We will be using a NPN transistor, which is what the majority of low power switching circuits use. If you want a deeper background see: A practical guide to transistors and their use. A BJT is made up of three pieces of silicon. A NPN transistor has a piece of P-Type silicon (the Base) sandwiched between two pieces of N-Type silicon (the Collector and the Emitter).

Fun Fact: If you don’t know what P-Type and N-Type mean, here’s a quick explanation. A silicon crystal by itself is an insulator. Adding a minute amount of impurities turn the silicon from a good insulator to a viable (but not great) conductor (hence the name semiconductor). A process called Doping introduces impurities into the pure silicon crystal in order to modify the conductivity. Typically Boron (P-Doping) and Phosphorus (N-Doping) are used. Combining P-Type and N-Type silicon allows electricity to flow.

We are making the most fundamental transistor switch circuit. A normal switch would require a mechanical device to physically flip the circuit. Our switch here will be controlled by the current sent from the Jetson GPIO pin to the transistor. The control signal from the Jetson flows into the Base of the transistor, the Emitter connects to ground, and the output is tied to the Collector.

The Circuit

Here’s a schematic of the circuit we will be using:

  • L1 is our 5V LED
  • R1 is the current limiting resistor for the LED
  • Q1 is the transistor we’ve been talking about, a P2N2222
  • R2 is the Base Resistor which tells how much current to let flow in the circuit.
  • For this circuit, use a NPN BJT transistor

Calculating the Transistor Bit

There’s one more bit of mystery. When the Jetson GPIO is low (0V), the transistor is in cutoff mode. It looks like an open circuit between the Collector and the Emitter.

However, there is amount of current applied to the Base at which point the transistor starts to “saturate”. This then acts like a short circuit between the Collector and the Emitter. At that point, current flows and our LED lights up, all nice and happy.

In our example the Base current is determined by a Base Resistor which sits between the Jetson GPIO pin and the base of the transistor. The Base Resistor performs much the same function as the current limiting resistor on the LED. Note that the saturation of the transistor is determined by current, not voltage in a BJT.

There’s a little more math involved to figure out what value the Base Resistor should be.

This reads as the current on the Base of the transistor is equal to the desired current at the Collector divided by the gain of the transistor. You remember that transistors are amplifiers, and have an associated gain. The term hFE in the transistor data sheet is the gain number. For this particular transistor, it is equal to 100. If we provide 0.00020A to the Base of the transistor, we should get 20mA at the Collector.

There’s one more little trick. We need to use Ohm’s Law one more time. We know that the GPIO of the Jetson is 3.3V. We divide that by the 0.00020A to get the Resistance, right? Nope. It turns out that there is a 0.7V drop between the Base and the Emitter that we need to take into account. This drop is attributable to the N-P junction of the Base to the Emitter in the transistor. So:

In this circuit, the 13000Ω value of the Base resistor is the maximum resistance that you can have to get 20mA at the Collector.

You will notice that in our circuit we threw in a 10kΩ resistor instead of the 13kΩ. This is for a couple of reasons. First, we know that the LED won’t draw more than 20mA because of the limiting resistor from earlier. Second, 13kΩ is not a common resistor value, so we need to substitute. If you want to be safe, you would tend to go up a size rather than down. But we live wild! And we have a fire extinguisher.

There are also transistor calculators online if you need to check your maths.

Wiring

We’re now ready to wire everything up and give it a spin. Both LEDs and Transistors flow current in only one direction, and have a + and – side. For the LED, + is the anode, – is the cathode. On a 5mm LED, the + side usually has a longer leg, and usually the – side has a flat spot on the rim of the bulb.

For the Transistor, the Collector goes to the + side, and the Emitter goes to the – side. The arrangement of the pins depends on the particular part chosen.

Given the schematic above, here’s a wiring diagram:

Jetson GPIO Wiring Diagram

You will need to examine your transistor. The Collector, Base, and Emitter are different depending on which part number you have. We’re using a P2N2222 here. We will be wiring the red wire to +5V on Pin 2 on the Jetson, the black wire to GND on pin 6, and the transistor Base through the base resistor on Pin 12. Pin 12 is selected for the demo examples below.

All wired up!

Software

Once everything is wired up, we’re ready to run some software to blink our light.

We can control our LED from the command line. Here are some useful commands:

# Map GPIO Pin
# gpio79 is pin 12 on the Jetson Nano
$ echo 79 > /sys/class/gpio/export
# Set Direction
$ echo out > /sys/class/gpio/gpio79/direction
# Bit Bangin'!
$ echo 1 > /sys/class/gpio/gpio79/value
$ echo 0 > /sys/class/gpio/gpio79/value
# Unmap GPIO Pin
$ echo 79 > /sys/class/gpio/unexport
# Query Status
$ cat /sys/kernel/debug/gpio

In the above code, the 79 refers to a translation of the Linux sysfs GPIO named gpio79. If we look at the Jetson Nano J41 Header Pinout, we can see that gpio79 is physically pin 12 of the header.

Note: Except for the power, ground, I2C and UART pins, the header pins are GPIO in the Jetson default configuration. Any extra names in the Header Pinout refer to preferred usage if the user makes changes to the device tree and reassigns the pins.

In order to be able to access the GPIO pins, you need to have the proper permissions. This can be accomplished in a couple of ways. First, you can run your commands from a super user terminal. Open the Terminal and execute:

$ sudo su

You are then able to execute the commands with the correct permissions. Also, the permissions can be assigned to a group which you are a member. This is typically done by:

$ sudo groupadd -f -r gpio
$ sudo usermod -a -G gpio your_user_name

Install custom udev rules by copying the 99-gpio.rules file into the rules.d directory:

$ sudo cp /opt/nvidia/jetson-gpio/etc/99-gpio.rules /etc/udev/rules.d/

Please note that for the new rule to take place, you may either need to reboot or reload the udev rules by issuing this command:

sudo udevadm control --reload-rules && sudo udevadm trigger

This sequence is from the Jetson-GPIO Python library documentation, which is installed in the default Jetson Nano image at: /opt/nvidia/jetson-gpio/doc/README.txt.

Jetson.GPIO Python Library

There is an official Jetson.GPIO library for Python. The Jetson.GPIO library aims to be compatible with RPi.GPIO. We can run the sample for simple output to control our LED:

$ cd /opt/nvidia/jetson-gpio/samples
$ sudo ./run_sample.sh simple_out.py

The run_sample.sh script sets up the paths to the Jetson.GPIO library and calls simple_out.py to flash the LED that is connected to pin 12 on the GPIO header.

This is just touching the Jetson.GPIO library, it is much richer than just this. We’ll examine more functions in subsequent articles.

Conclusion

While it seems like a lot to know to turn LEDs on and off, we now have the foundation to control external devices over the Jetson GPIO Header. In our next installment of the GPIO series, we’ll take a look at input through the GPIO header. Stay tuned!

Notes

P2N2222 Transistor Datasheet

Here’s some useful information from the NVIDIA Jetson Nano Forum. PinballWizard writes:

The Jetson Nano carrier board uses TXB0108 bidirectional voltage-level translators on the GPIOs to go from the module’s 1.8 V levels to the headers 3.3 V levels. The data sheet for the TXB0108 states “With regard to capacitive loads, TXB translators are designed to drive up to 70 pF without issue.” The capacitance of my test leads is above 70 pF, so I tried an oscilloscope with 10 MΩ, 16 pF probes and the Jetson Nano outputs work fine. With both the multimeter and oscilloscope connected, I get a 56 MHz oscillation on the outputs. The multimeter reads the average, which is ~1.55 V.

The TXB0108 also has a 4 kΩ output impedance. That combined with the 70 pF capacitance limit means that any load on the Jetson Nano’s GPIOs should be both high impedance and low capacitance.

28 Comments

  1. Great work! Can you tell me what is the maximum current that each pin can supply and maximum total current from all pins ?

  2. Your videos are great! They are providing us with a lifeline to making this Nano thing work in reality. We will be attempting to use the Nano to control a heap of servo motors via Adafruit’s 16-Channel 12-bit PWM/Servo Shield with its I2C interface, so if you just so happen to use that as an example in your I2C video, we promise not to become so ecstatic it kills us. Thanks!

      • OMG! Just a few days ago my students were on the verge of tears trying to get their Nano to run some servo motors via the i2c link when, lo and behold, they found your video using Adafruit’s 16-Channel 12-bit PWM/Servo I2C thingy! They got their system working now. You saved the day – maybe even their summer. You’re like a saint or something. I promised we wouldn’t become so ecstatic that it kills us, but we sure have come close to it. Thank you! Thank you!

        • On the verge of tears? Most people have that reaction *after* they watch my videos! Or at least the ones that are still awake afterwards.
          I’m glad they got it to work, tell them I said “Hi”.

      • Check out his video using the i2c. I don’t think his website has a link to it yet.
        Just be aware when you’re using shields or hats, etc. that there is some power wiring, etc. that comes up to those shields or hats from the boards they are usually attached to, and so that won’t be provided by the Nano unless you wire it directly.
        https://www.youtube.com/watch?v=RnGUTny1hG8

  3. Hi Kangalow,

    we’re attempting to “embody” an AI and have it learn with that physical body (rather than just crunch through sets of disembodied data). Our hope is that we can get a Nano to learn to track the movement of an object and have a simple robot (on a chassis with wheels driven by servos) follow that object around in 3-D space. Our first step aims to have the robot track an object back and forth with the same kind of behavior one might expect from a robotic system controlled by a classic PID loop but have it learn on its own. So maybe a “heap” of motors was an exaggeration, but we’re certainly going to need at least 3 if this starts to work. Thanks!

  4. I’m using this with a 5v relay switch. Noticing that the echo 1 and 0 have no effect on the switch while switching in to out turns the switch on and off. What exactly are low and high supposed to do vs. in and out? And risks to using in as the switch mechanism?

  5. I don’t understand your description. Typically you would give a code snippet or something to put a context around how you are using these commands. Also, it is difficult to understand how you are using the 5V relay switch without some type of description of the wiring diagram, and a description of the part. The GPIO pins on the Jetson are 3.3V. Does the relay use a 5V signal, switch on a 5V signal, or something else?

    • Here’s the description for you. The switch has 3 input/outputs on either side. One side had NO, COM and NC. The other has VCC, GND and IN. I’m also using a barrel jack to plug the power supply in
      NO gets the positive side of the barrel jack, COM gets the positive side of the LED wire. GND gets a GND pin on the nano, VCC gets the 3.3v pin and IN gets the GPIO pin 79. Using the in/out commands I can turn on/off the switch. The Hi/Lo commands have no effect.

      It’s been working fine using the 3.3V input, however the nano only has 2 3.3V inputs. So I tried the 5V. That also turns on the switch, but I can’t get it to turn off the switch. Both with using the In/Out and Hi/Lo commands.

      • Question for you. What do you think In/Out do? Also, what do you believe the Hi/Lo commands are? Do you have a part number for the relay?
        What is the code you are using?

  6. Great tutorial, thank you!
    I’m looking to interface the Nano’s GPIO with C++ library instead of python, so I can reuse existing code. Have you stumbled upon a good solution?

    Thank you very much for your blog posts!
    -Phil

  7. Thanks for the great article as usual!

    I was trying to figure out what this business with mode BCM vs mode BOARD means. From the documentation:

    “`
    … uses the BCM pin numbering mode from
    Raspberry Pi and outputs alternating high and low values at BCM pin 18 (or
    board pin 12 on the header) …
    “`

    At first I didn’t understand this because the raspberry pi pin numbering is the same as the nano J41, but after looking at the pi
    pinouts I realized that in BCM mode the channel number is the *gpio* number (in this case gpio18). This number does not
    match the gpio number on the nano however.

    In summary, to use nano gpio79 you either use BCM18 or BOARD12 (pi gpio 18 or pin number 12).

  8. Hi Sir,
    i am trying to access gpio pins in jetson nano development kit ,i would like to perform i2c , spi and uart applications in jetson nano using c program but i couldnt find any tutorial or documents what i am looking for,i could only able to find examples in python version, please guide me and please share the needful documents and tutorial links to access gpio in jetson nano in c version.

  9. Actually Jetson works in two power modes i.e., LOW and HIGH. To set Jetson in low power mode type the following command-
    $ sudo nvpmodel -m1
    $ sudo nvpmodel -q

    As you enter these commands your Jetson will start working in LOW Power mode and now you can easily control the GPIOs

    • This is not related to GPIO. nvpmodel controls the power consumption of the Jetson by setting the clock speeds of the CPU and GPU. The Jetson Nano has a 5W and a 10W mode through nvpmodel, which represents the amount of current draw for the configuration CPU/GPU clocks.

Leave a Reply

Your email address will not be published.


*