GPIO Help: Migration From Raspberry Pi To Jetson Nano

Problem

I’m currently migrating from a Raspberry Pi Model 4B to a Jetson Nano. I’ve ran into some issues using my DC motor with the Jetson GPIO pins. I’ve included a drawing of my current configuration.

The issue I’m running into is that I can’t get the motor to spin at all. As seen in my drawing, I’m using pin 16 and pin 18. All that is needed to get this motor spinning is alternating pin 16 and pin 18 between HIGH and LOW. I’ve written a script that does this for me as seen here:

import Jetson.GPIO as GPIO
import time

# Pin Definitions
motor_pin_a = 18  
motor_pin_b = 16  

def main():
    # Pin Setup:
    # Board pin-numbering scheme
    GPIO.setmode(GPIO.BOARD)
    # Set both pins LOW to keep the motor idle
    # You can keep one of them HIGH and the LOW to start with rotation in one direction 
    GPIO.setup(motor_pin_a, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(motor_pin_b, GPIO.OUT, initial=GPIO.HIGH)

    print("Starting demo now! Press CTRL+C to exit")
    curr_value_pin_a = GPIO.HIGH
    curr_value_pin_b = GPIO.LOW
    try:
        while True:
            time.sleep(5)
            # Toggle the output every second
            print("Outputting {} to pin {} AND {} to pin {}".format(curr_value_pin_a,        motor_pin_a, curr_value_pin_b, motor_pin_b))
            GPIO.output(motor_pin_a, curr_value_pin_a)
            GPIO.output(motor_pin_b, curr_value_pin_b)
            curr_value_pin_a ^= GPIO.HIGH
            curr_value_pin_b ^= GPIO.HIGH
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Using the same exact configuration with the same exact code on the Raspberry Pi works perfectly fine, but not on the Jetson. Any ideas on how to resolve this?

Things I Tried

My first thought was that maybe pins 16 and 18 were not actually outputting HIGH and LOW. I tested this theory with a multimeter and saw that both pins were oscillating every 5 seconds between 0V and 3.3V, which I assume is good.

I also tried getting rid of the battery pack and just powering the L9110 Motor driver directly with the Jetson Nano via pin 2(5V) and pin 41(GND). When I did this, the DC motor would move ever so slightly on GPIO.Cleanup().

Lastly, I tried following this guide to help setup the GPIO pins: https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/hw_setup_jetson_io.html. I clicked on “Confiugre 40-pin expansion header”, and I activated the following:

  • pwm0
  • pwm1
  • spi1
  • spi2

Please let me know if there is anything I forgot to add that would help resolve this issue.

Hi sorozco,
I’m currently using a jetson nano for motor control and also migrated from RPI.

The PWM Frequency Upper Limit on Jetson Nano is around 187 kHz :
If the 187KHz frequency limitation as well as the lack of documentation don’t bother you I recommend you to read this post if you havn’t already.

If you want to rapidly find a way to get to the full potential of your driver use the si5351 (see below)

The speed limitation at high step resolution:
I tested many stepper motor driver and I found that the DM542 is a good deal for 6$.
The important datas about drivers are resolution and speed :

Résolution: The DM542 can get to 25000 steps by rotation for a 1.8° stepper motor, I’m using 0.9° motors so I get a max resolution of 0.0072° per step, not bad !

Speed: The max 50/50 pwm frequency of DM542 is 200KHz so 200 000 steps per sec.
So my motor max speed is 1440°/sec=4rot/sec at max résolution and 180000°/sec=500 rot/sec at minimum resolution.
4rot/sec is not bad but we have yet to get the 200KHz pwm signal to the motors…

Generating a 200KHz pwm signal using external signal generator:
I found the Si5351 to be a good deal for 2$.
With it you can drive 3 motor drivers with 200KHz pwm signal (or above if compatible with your driver).
You can use I2C to control the Si5351 from the jetson nano.

Change your driver:
You also could buy a driver with an I2C interface, they are cheap but have very limited speed.

Regards

Hi Planktos,

While I find your post helpful for the future, it doesn’t really help me with my current situation. Do you have any input regarding my current configuration?

Thanks,
Sergio

My gess is wrong pwm voltage :
my DM542 only accept pwm signal within the 5V-24V range, trying to drive it with 3.3 V will result in failure,
if your driver also need at least 5V you can use a DC/DC step up converter to get your signal to 5V
Also be sure to connect the pwm signal ground of the driver to the jetson GND else no signal can pass.
Regards

So I checked, and the raspberry pi also supplies a HIGH of 3.3V, yet it still works in my current configuration. As you can see in my configuration above, I am also connecting a common GND between my power supply (6V), the motor driver, and the Jetson Nano.

Is there some difference between pins 16 and 18 on the Raspberry Pi as opposed to the Jetson Nano that I’m not seeing?

I should also note that I am not a hardware guy in the slightest. I’m a software engineer by profession, so apologies if some of this seems really trivial.

Voltage :
I checked your driver doc,
input can range from 2.5v to 9v so it unlikely that the issue come frome voltage (for product grade prototype the typical voltage should be 5v).
PWM HIGH state duration :
Check out the figure 11 of the doc of my driver, their is some time spec that you may not be using properly, but it depend on your driver, in my case pwm pulse width must be around 2.5µs, so if it was’nt working with your RPI I would have gess that the issue is the 5s wich is very long … I would advise to make the HIGH state not stay more than a few ms, enven if it don’t solve the issue it’a a good practice.
PWM current and consistency :
The L9110 documentation is … well short to say the least, 2 pages, mine is 15 pages long … it make it harder to find where your issue come from…
I gess you don’t want to wait 2 weeks to get a properly documented driver so here is the experiment I would try :
Monitor the pwm signal voltage and current of RPI and compare it to the nano one, your multimeter should do the trick for low frequencies but if you can access an oscilloscope it would be perfect as you would be able to also check the signal quality and consistency !
GND :
Try powering the driver with a different power source than for nano, follow exactly the shematic “Application Circuit” of your driver doc and don’t make a common GND between nano and the driver.
Don’t Worry Be Happy :

No worries we are all here to learn and help each other, this is the power of internet ! :D
If thoses tests don’t give us an hint of where the issue come from I’ll try your code with my nano and rpi but it would not be fast as I would need to wait to receive the L9110 driver. I could also test your code with some of my drivers in a near future.

Regards

So I am currently not even trying to use PWM at the moment. I followed this guide: How to use the HG7881 (L9110) Dual Channel Motor Driver Module which states that I can supply HIGH voltage to IA and LOW voltage to IB. This should cause the motor to start spinning clockwise, and reversing the voltages should make it spin counter-clockwise (this happens on RPi). The code I wrote should just alternate the motor spinning clockwise and counter-clockwise every 5 seconds, no PWM code yet.

I am also currently powering the driver using a separate power supply from the jetson nano. Why do you suggest not making a common GND between the nano and driver? I read somewhere(can’t remember where exactly) that if I power my driver using a separate power supply, I should keep a common GND between the Nano and the driver.

I also have a spare L298N driver. Maybe I could swap that in place of my current L9110. Most DC motor tutorials I see use the L298N as the gold standard for motor driver support

looking at the code :
// functional connections
#define MOTOR_B_PWM HG7881_B_IA // Motor B PWM Speed
#define MOTOR_B_DIR HG7881_B_IB // Motor B Direction
So for this test, just trying to run it clockwise you don’t need to use IB as for IA as you can see in the code, case 1 of the switch :
case '1' : // 1) Fast forward
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
delay( DIR_DELAY );
// set the motor speed and direction
digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
analogWrite( MOTOR_B_PWM, 255-PWM_FAST ); // PWM speed = fast
isValidInput = true ;
break ;
the IA is drived using analogWrite( MOTOR_B_PWM, 255-PWM_FAST ); so they are using pwm.
I know there is the table at the beginning of the tuto but they don’t explecitly sayed that you could drive it with a solid HIGH on IA or at least I don’t see it.
Yes yes it works with RPI but you can make an easy test : just wire a 5v or so power supply to the IA and see if it works, it may but anyways it’s not good as it will try to run your motors at max speed not necessarily letting the motor the time to move resulting in undefined behavior; then just briefly touch the IA with 5v wire and your motor will do a step if you are fast enought.
Anyway you need to do a proper pwm code as you will need it soon enough to controle speed.
No driver is made to be controlled with const voltave on a pwm pin it’s just not made for that and most of them won’t work like that at all moreover the lack of documentation make it impossible to predict the speed of the motor if pwm stay high resulting in hardly approximatable motor position estimation…

Just try IA pin with 10Hz pwm with 50% duty cycle if it don’t work try with 100Hz and then with and without common GND.
If it still don’t work I would say : Houston, We’ve Got a Problem !
Best of luck !

Alright I’ll try some stuff out either tomorrow or Saturday with PWM. Thank you for all the help! I really appreciate it.

So I just ran this code with my motor driver, but to no avail. I tried with both 10 and 100 Hz.

import RPi.GPIO as GPIO
import time

# Pin Definitions
motor_pin_a = 33
motor_pin_b = 16  

def main():
    GPIO.setmode(GPIO.BOARD)

    GPIO.setup(motor_pin_a, GPIO.OUT)
    GPIO.setup(motor_pin_b, GPIO.OUT)

    pwm = GPIO.PWM(motor_pin_a,100)

    GPIO.output(motor_pin_b,GPIO.LOW)
    pwm.start(0)

    for i in range(100):
        print(i)
        pwm.ChangeDutyCycle(i)
        time.sleep(0.1)

    GPIO.cleanup()

if __name__ == '__main__':
    main()

I am going to try with the L298N driver right now and see how that goes.

Just ran the following code for the L298N which did not work either:

import RPi.GPIO as GPIO
import time

# Pin Definitions
ena  = 33
in1 = 16
in2 = 18

def main():
    GPIO.setmode(GPIO.BOARD)

    GPIO.setup(in1, GPIO.OUT)
    GPIO.setup(in2, GPIO.OUT)
    GPIO.setup(ena, GPIO.OUT)

    pwm = GPIO.PWM(ena,100)
    pwm.start(0)

    GPIO.output(in1,GPIO.LOW)
    GPIO.output(in2,GPIO.HIGH)

    for i in range(100):
        print(i)
        pwm.ChangeDutyCycle(i)
        time.sleep(0.1)

    GPIO.cleanup()

if __name__ == '__main__':
    main()

The configuration for the L298N is as follows:

Hi,
First of all : why a 6v battery for a 5v driver ? …
Duty cycle
p.start(dc) # where dc is the duty cycle (0.0 <= dc <= 100.0)
So you should start in1 with dc=50 (if it’s 0 it will be always LOW and if 100 it will always be HIGH…)

ENA pin
pwm = GPIO.PWM(ena,100)
p = GPIO.PWM(channel, frequency) from doc
so 100 is your freq but ena pin on driver should not be pwm,
the ena pin will enable you to keep the motor in place if HIGH or be able to move it manually if LOW so no need for PWM there.

Just unwire ena pin, for now it’s useless.

in2
Keep in2 LOW because it’s for rotation direction, it’s not PWM and we don’t care about it for now.
Just unwire in2 pin, for now it’s useless.

in1
An example to blink an LED once every two seconds:

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 0.5)
p.start(1)
input('Press return to stop:')   # use raw_input for Python 2
p.stop()
GPIO.cleanup()

in our case just use 100 or so instead of 0.5;
duty cycle is by default 50% so no need to change it
however you can chage the frequency with p.ChangeFrequency(freq) # where freq is the new frequency in Hz in your for loop to test different speeds (you can vary freq from 1 to 200 000)

CODE EXAMPLE (not tested) :
Easiest code to drive with pwm :

import RPi.GPIO as GPIO
import time
# Pin Definitions
in1 = 16
def main():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(in1, GPIO.OUT)
    pwm = GPIO.PWM(in1,100)
    pwm.start(50)
    input('Press return to stop:')   # use raw_input for Python 2
    pwm.stop()
    GPIO.cleanup()

if __name__ == '__main__':
    main()

Vary PWM Freq code :

import RPi.GPIO as GPIO
import time
# Pin Definitions
in1 = 16
def main():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(in1, GPIO.OUT)
    pwm = GPIO.PWM(in1,100)
    pwm.start(50)
    for i in range(200000):
        pwm.ChangeFrequency(i)
        print(i)
        time.sleep(0.1)       
    pwm.stop()
    GPIO.cleanup()

if __name__ == '__main__':
    main()

Hi Planktos,
So I actually got it working with the L298N motor driver! I am seeing quite a significant voltage drop on the L298N which I guess is pretty common (L298N Voltage Drop Excessive (Solved!!) - Project Guidance - Arduino Forum). I guess my next step would be to find a good motor driver that is able to drive two motors at around 6V.

1 Like

NICE !
I would advise to get one driver per motor, the DM542 is very good (got 6 of them) and I tryed many other, it’s really good quality stuff and very cheap as well ! But of course you need one that fit well your motors. This is the best site I found to buy motor drivers and related stuff, very good quality and detailed documentation :D

In fact the driver as well as the motor should be adpted to your project, if you could tell me a little bit about it I could advise you better

Also it would be very kind, if one of my post helped you, to mark it as a solution,
Thanks !

Of course!. So I’m just creating a simple drivable robot with two DC motors like the ones seen here: DC Gearbox Motor - TT Motor - 200RPM - 3 to 6VDC : ID 3777 : $2.95 : Adafruit Industries, Unique & fun DIY electronics and kits. I don’t need anything fast or big, so I thought these were a good place to start.

I just ordered this motor driver: Adafruit DRV8833 DC/Stepper Motor Driver Breakout Board : ID 3297 : $5.95 : Adafruit Industries, Unique & fun DIY electronics and kits. Adafruit says these drivers are perfect for low voltage DC motors (6V). It should get here tomorrow, and I have high hopes for it!. I would love any recommendations

Just got my new motor driver which works like a charm. I guess this post is for anyone who has the same problem I had. For some reason the L9110 motor driver did not work at all with the Jetson Nano. I transitioned over to the DRV8833 by Adafruit, which works perfectly. Here is a simple test script I wrote that ran my DRV8833:

import RPi.GPIO as GPIO
import time

# Pin Definitions
enable_driver_pin = 16 # SLP pin
a_in_1 = 33
a_in_2 = 35

b_in_1 = 32
b_in_2 = 18
def main():
    GPIO.setmode(GPIO.BOARD)


    GPIO.setup(enable_driver_pin, GPIO.OUT)
    GPIO.setup(a_in_1, GPIO.OUT)
    GPIO.setup(a_in_2, GPIO.OUT)
    GPIO.setup(b_in_1, GPIO.OUT)
    GPIO.setup(b_in_2, GPIO.OUT)

    a_pwm = GPIO.PWM(a_in_1,50)
    b_pwm= GPIO.PWM(b_in_1,50)

    GPIO.output(enable_driver_pin,GPIO.HIGH)
    GPIO.output(a_in_2,GPIO.LOW)
    GPIO.output(b_in_2,GPIO.LOW)

    a_pwm.start(0)
    b_pwm.start(0)

    for i in range(100):
        print(i)
        a_pwm.ChangeDutyCycle(i)
        b_pwm.ChangeDutyCycle(i)
        time.sleep(0.1)

    for i in range(100):
        print(100 - i)
        a_pwm.ChangeDutyCycle(100 - i)
        b_pwm.ChangeDutyCycle(100 - i)
        time.sleep(0.1)

    GPIO.output(enable_driver_pin,GPIO.LOW)
    GPIO.cleanup()

if __name__ == '__main__':
    main()
2 Likes