NameError: name 'open' is not defined with Jetson.GPIO on the xavier nx

Hello, I get the NamerError when I try servo control on the Jetson Xavier nx series using pwm. The motor does not turn. nothing happens. The full trace is pasted below. Motor attached to pin 32. The python function is also provided below. How can I resolve this? or what am I doing wrong?

Note: If i comment out the

GPIO.output

The motor turns momentarily, but gives some funny sound and warms up.

The script:

import Jetson.GPIO as GPIO
from time import sleep

# helper function to map angles to PWs
def set_angle(angle, lower_lim, output_pin, pwm):
        duty = angle / 18.0 + lower_lim
        GPIO.output(output_pin, True)
        pwm.ChangeDutyCycle(duty)
        # wait 15ms
        sleep(0.015)
        GPIO.output(output_pin, False)
        pwm.ChangeDutyCycle(0)
        sleep(0.015)


GPIO.setmode(GPIO.BOARD)
output_pin = 32

# set pin 32 as an output pin
GPIO.setup(output_pin, GPIO.OUT, initial=GPIO.HIGH)

# setting up PWM on pin #32 at 50Hz
pwm = GPIO.PWM(output_pin, 50)

# starting with duty cycle = 0 so no angles are set on startup
pwm.start(0)

lower_lim = 5

set_angle(45, lower_lim, output_pin, pwm)

pwm.stop()
GPIO.cleanup()

The Error trace

Traceback (most recent call last):
  File "better_servo_test.py", line 31, in <module>
    set_angle(45, lower_lim, output_pin, pwm)
  File "better_servo_test.py", line 8, in set_angle
    GPIO.output(output_pin, True)
  File "/usr/local/lib/python3.6/dist-packages/Jetson.GPIO-2.0.17-py3.6.egg/Jetson/GPIO/gpio.py", line 451, in output
RuntimeError: The GPIO channel has not been set up as an OUTPUT
Exception ignored in: <bound method PWM.__del__ of <Jetson.GPIO.gpio.PWM object at 0x7f9fb65a58>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/Jetson.GPIO-2.0.17-py3.6.egg/Jetson/GPIO/gpio.py", line 644, in __del__
  File "/usr/local/lib/python3.6/dist-packages/Jetson.GPIO-2.0.17-py3.6.egg/Jetson/GPIO/gpio.py", line 660, in stop
  File "/usr/local/lib/python3.6/dist-packages/Jetson.GPIO-2.0.17-py3.6.egg/Jetson/GPIO/gpio.py", line 278, in _disable_pwm
NameError: name 'open' is not defined

I run it both as: sudo python3 better_servo_test.py
also as: python3 better_servo_test.py

My goal is to eventually use this setup to move the motor back and forth between 0 and 180 degrees. 0 maps to 1ms, while 180 degrees maps to 2ms. An alternative solution is also greatly appreciated. Thanks.

why don’t you refer to simple_pwm.py for using PWM?

Hello, I did but the motor is not responding as expected, so I expected i might be missing something which is why I posted here to help me figure out what. Below is the modified example to the simple_pwm for my case:

import Jetson.GPIO as GPIO

import time

control = [5,5.5,6,6.5,7,7.5,8,8.5,9,9.5,10]

#control = [5, 7.5, 10]

servo = 32

GPIO.setmode(GPIO.BOARD)

GPIO.setup(servo, GPIO.OUT)
# in servo motor,
# 1ms pulse for 0 degree (LEFT)
# 1.5ms pulse for 90 degree (MIDDLE)
# 2ms pulse for 180 degree (RIGHT)

# so for 50hz, one frequency is 20ms
# duty cycle for 0 degree = (1/20)*100 = 5%
# duty cycle for 90 degree = (1.5/20)*100 = 7.5%
# duty cycle for 180 degree = (2/20)*100 = 10%

p=GPIO.PWM(servo,50) # 50hz frequency

p.start(2.5) # starting duty cycle ( it set the servo to 0 degree )

try:
        while True:
                for x in range(len(control)):
                        p.ChangeDutyCycle(control[x])
                        time.sleep(0.015)
                        print(control[x])

                for x in range(len(control) - 2, 0, -1):
                        p.ChangeDutyCycle(control[x])
                        time.sleep(0.015)
                        print(control[x])

except KeyboardInterrupt:
        p.stop()
        GPIO.cleanup()

With this configuration: I expect it to turn left and right almost none stop through the angles, 0, 180. But it only occassionally turns about 45 degrees, gives a long pause, then goes back to zero then, pause then go back to about 45 degrees and so on.
What is the system file path corresponding to pwm on pin 32, so i can try the debug you suggested here directly? Then I will update you about situation, or if you already have an idea why i get this behavior?
thanks.

hello user105768,

may I know what’s your actual use-case,
would you like the motor rotate at 0 degree, pause for a while, then rotate to 180 degree continuously?
please refer to external wiki page as see-also, Duty cycle - Wikipedia
thanks

Yes please, I want the motor to rotate from : 0, 1, 2, 3, 4, 5 …, 180 degrees, The rotate from 180 degrees back to 0 continuously as smoothly as possible. I tried the same logic in arduino using this sketch and it works perfectly. Now i want to implement it on python via the jetson nx. This is the motor am testing on. I dont know why it wont sweep smoothly.
When I try to change dutyCycle independently step by step on terminal, say I do

pwm.ChangeDutyCycle(10) # I expect it to go to one end and stay there

But it wont stay there. It will rotate abit then begin shaking till i do

pwm.ChangeDutyCycle(0)
Then it stops

hello user105768,

you may check that external wiki page, it’ll output the wave consistently. please consider the duty cycle here as the rotation speed, and you should have implementation to control the rotate behavior. you may have a try to invert the signal while it reach 180 degree.

sorry, I am now quite a bit confused. If the dutyCycle is the rotation speed, then what is the rotation angle? and how do I control the rotation angle? But indeed if it is the rotation speed, then the behavior of the motor makes some sense. But then what is the rotation angle and how do I control it in order to have the motor to sweep through the angles from 0 to 180 and back? I thought varying the Duty cycle was the way to change the angle? but if that gives the speed, then I have no definite idea how to control the angle. Please can you at least show me with this example how to set angle, pause a bit then change the angle? I have looked at the external page:
and i did the calculations shown in the code snipet in the post according to that - thinking that duty cycle here was the way to vary the angle of the motor. Like:

0 degrees = 5% duty cycle and
180 degrees = 10% duty cycle.
Where is my mistake?

hello user105768,

I need to revise that, it’s different pulse widths correspond to different angles.
please also check this training video, Jetson Nano I2C PWM Servo Motors - YouTube

hello, I saw the video u reference but it does not help much since all the important work is done by the ardafruit board and I can not see how they did that. Since i have one motor, or even two at most I honestly feel there’s no need for anymore external hardware just to be able to do this.
Ok, so what is the correct way to vary the pulse widths consistently using the jetson gpio library? Or any stand alone python library - preferably python2 . I think i can handle the rest from there. I am open to all suggestions.

hello user105768,

you have the servo rotates but not act with the correct degree, right?
there should be limit of the servo. (i.e. min, max), please also consider that for mapping the values into the degree.

yes, it rotates. But i can not control the angle. I considered it but that does not seem to matter. Ok lets say for angles between 55 and 120. How should i configure this to have consistent and controlled rotation?

Maybe it is worth mentioning. I connected GND to Pin 6, Voltage to Pin 1 and the servo signal pin to 32. As these seem fine after checking the header pin configuration.

hello user105768,

this is default as GPIO, had you done pin mux configuration to configure it as PWM?
you may refer to Configuring Jetson Expansion Header, and using the Jetson-IO to modify the pin by device tree overlay.
thanks

Hello, I used Jetson-IO, selected pin 32 as PWM and rebooted the device.
Is there something extra that I have to do before or after that?
When I check pin configuration, it sometimes shows it as pwm8 sometimes as gp? is this ok?

hello user105768,

may I know the steps how your examine the pin configuration?

  • first to set the pin as pwm, I ran:

sudo /opt/nvidia/jetson-io/jetson-io.py

then i set pin 32 as pwm from the header-pin configuration table.
Then to examine the pin configuration steps:
I run the command:

sudo /opt/nvidia/jetson-io/config-by-pin.py -p 32

Sometimes this gives gp as result, but when i run it again(without changing anything) a few times it then gives pwm8.

Also i use this command sometimes to examine pin configuration:

sudo /opt/nvidia/jetson-io/jetson-io.py

hello user105768,

it’s using the device tree overlay, (i.e. *.dtbo) the system need to reboot after you configure the pin as PWM.
please check pinmux changes session, if you need to fully configure the pin.

hello. Thanks, I am trying to do this but i have a few questions:

  1. where do i execute these changes. I downloaded the excel sheet but when i click the dropdown to change the customer usage for the GPIO07 to PWM, I dont see that option or any other options: All i see is:

#REF!

and no other options. What should i do?
Also, where do I find the file:

Linux_for_Tegra/kernel/pinmux/t19x/

I can not see such a location on my jetson. Thanks.

hello user105768,

that’s the path of your host machine, i.e. desktop.
if you download the JetPack release via SDKmanager, it’ll also install all the necessary tools, binaries to your local host.
thanks

Hello @JerryChang, I already have JetPack installed. I did not use the sdkmanager. I have jetpack 4.5.1.
I still can not locate this path:

Linux_for_Tegra/kernel/pinmux/t19x/

Now with my current settings, how best should i proceed?

hello user105768,

the installation path is looking like this… ~/nvidia/nvidia_sdk/JetPack_<version>_<platform>/Linux_for_Tegra/
please check with $ tree -d -L 1 and please share the results for reference,
thanks