Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetson Orin Nano PWM only works on Pin 33 #105

Open
mattwilliamson opened this issue Jan 17, 2024 · 17 comments
Open

Jetson Orin Nano PWM only works on Pin 33 #105

mattwilliamson opened this issue Jan 17, 2024 · 17 comments

Comments

@mattwilliamson
Copy link

Hello,

Pin 33 works with PWM. Pin 32 and pin 15 do not. It's just either on or off. I'm using a L293 motor controller and if I switch the pins for left and right motors, the other motor exhibits the same behavior.

Jetson Orin Nano
Jetpack 5.1.2 L4T 35.4.1
Jetson.GPIO.VERSION '2.1.6'

>>> GPIO.JETSON_INFO
{'P1_REVISION': 1, 'RAM': '32768M, 65536M', 'REVISION': 'Unknown', 'TYPE': 'JETSON_ORIN_NANO', 'MANUFACTURER': 'NVIDIA', 'PROCESSOR': 'A78AE'}

Here's my sample code:

import Jetson.GPIO as GPIO
import time

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

# Enable, forward, backward
lpin = [32, 38, 37]
rpin = [33, 35, 36]
hz = 50

GPIO.setup(lpin[0], GPIO.OUT)
GPIO.setup(rpin[0], GPIO.OUT)
GPIO.setup(lpin[1],GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(rpin[1],GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(lpin[2], GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(rpin[2], GPIO.OUT, initial=GPIO.LOW)

lpwm = GPIO.PWM(lpin[0], hz)
rpwm = GPIO.PWM(rpin[0], hz)

lpwm.start(0)
rpwm.start(0)

#

def forward(left_speed=100, right_speed=100):
    lpwm.ChangeDutyCycle(left_speed)
    rpwm.ChangeDutyCycle(right_speed)
    GPIO.output(lpin[1],GPIO.HIGH)
    GPIO.output(rpin[1],GPIO.HIGH)
    GPIO.output(lpin[2],GPIO.LOW)
    GPIO.output(rpin[2],GPIO.LOW)


for i in range(0, 100, 1):
    print(i)
    forward(i, 0)
    time.sleep(.1)

Some more info for you:

At 50% duty cycle on pin 32 and 33:

matt@deepdrive:~$ sudo cat /sys/kernel/debug/pwm
platform/39c0000.tachometer, 1 PWM device
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal

platform/32e0000.pwm, 1 PWM device
 pwm-0   (sysfs               ): requested enabled period: 20000000 ns duty: 0 ns polarity: normal

platform/32c0000.pwm, 1 PWM device
 pwm-0   (sysfs               ): requested enabled period: 20000000 ns duty: 10000000 ns polarity: normal

platform/32a0000.pwm, 1 PWM device
 pwm-0   (pwm-fan             ): requested enabled period: 45334 ns duty: 14045 ns polarity: normal

platform/3280000.pwm, 1 PWM device
 pwm-0   (sysfs               ): requested enabled period: 20000000 ns duty: 0 ns polarity: normal
@mattwilliamson
Copy link
Author

Once python is running with GPIO, this seems to be able to control the duty cycle in another shell:

echo 0 > /sys/class/pwm/pwmchip3/export
echo 20000000 > /sys/class/pwm/pwmchip3/pwm0/period
echo 10000000 > /sys/class/pwm/pwmchip3/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip3/pwm0/enable

@anhmiuhv
Copy link
Collaborator

Did you change the pinmux so they are pwm?

@mattwilliamson
Copy link
Author

Yep. I don't think the /sys/class/pwm/pwmchip3/pwm0/duty_cycle would have worked without that.

Screenshot 2024-01-17 at 11 09 07 AM

@anhmiuhv
Copy link
Collaborator

Does the code run without crashing and the output signal is correct for pin 33 but the
output signal is not correct for pin 15 and 32?

@anhmiuhv
Copy link
Collaborator

anhmiuhv commented Jan 17, 2024

Once python is running with GPIO, this seems to be able to control the duty cycle in another shell:

echo 0 > /sys/class/pwm/pwmchip3/export
echo 20000000 > /sys/class/pwm/pwmchip3/pwm0/period
echo 10000000 > /sys/class/pwm/pwmchip3/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip3/pwm0/enable

Yes actually this is how the underlying python code control GPIO PWM. You can do this to control it manually

@mattwilliamson
Copy link
Author

Does the code run without crashing and the output signal is correct for pin 33 but the output signal is not correct for pin 15 and 32?

Yes, that's correct.

@mattwilliamson
Copy link
Author

There's no software PWM support, right? I'm just thinking of workarounds until this can get fixed.

@anhmiuhv
Copy link
Collaborator

No software PWM support. Maybe you can use external servo driver like this
https://www.amazon.com/16-Channel-12-bit-Servo-Driver-Interface/dp/B00EIB0U7A

@anhmiuhv
Copy link
Collaborator

Can you show me the output of

sudo busybox devmem 0x02440020
sudo busybox devmem 0x02434080

@mattwilliamson
Copy link
Author

$ sudo busybox devmem 0x02440020
0x00000404
$ sudo busybox devmem 0x02434080
0x00000404

@anhmiuhv
Copy link
Collaborator

I cannot reproduce this on my hardware. I will let our hardware engineer know to look into this further.

@mattwilliamson
Copy link
Author

If you have instructions on how you got yours working, I could double check that I'm doing it correctly.

@anhmiuhv
Copy link
Collaborator

anhmiuhv commented Jan 21, 2024

I tested PWM using https://github.com/NVIDIA/jetson-gpio/blob/master/samples/test_all_apis.py
To run it you need to connect pin 33 - 19 and pin 11 - 13, and set up pin 15,32,33 as PWM . I modify the test

so that "33" is replaced with 15 and 32, and reconnect the jumper wire correspondingly to see if PWM work correctly for those pin

@mattwilliamson
Copy link
Author

Nice! I will try it in the morning.

@mattwilliamson
Copy link
Author

Here is one thing to note:

>>> GPIO.cleanup()
OSError: [Errno 9] Bad file descriptor

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/matt/src/deepdrive/venv/lib/python3.8/site-packages/Jetson/GPIO/gpio.py", line 381, in cleanup
    _cleanup_all()
  File "/home/matt/src/deepdrive/venv/lib/python3.8/site-packages/Jetson/GPIO/gpio.py", line 273, in _cleanup_all
    _cleanup_one(ch_info)
  File "/home/matt/src/deepdrive/venv/lib/python3.8/site-packages/Jetson/GPIO/gpio.py", line 248, in _cleanup_one
    _unexport_pwm(ch_info)
  File "/home/matt/src/deepdrive/venv/lib/python3.8/site-packages/Jetson/GPIO/gpio.py", line 201, in _unexport_pwm
    ch_info.f_duty_cycle.close()
OSError: [Errno 9] Bad file descriptor

@mattwilliamson
Copy link
Author

test_all_apis.py passed with pin32.

Am I correct in that to test pin 15, I connect pin 15 to 19 instead of 33 - 19?

If I do that, I see this:

Testing test_warnings_off
Testing test_warnings_on
Testing test_setup_one_board
Testing test_setup_one_bcm
Testing test_setup_one_cvm
Testing test_setup_one_tegra_soc
Testing test_setup_twice
Testing test_setup_one_out_no_init
Testing test_setup_one_out_high
Testing test_setup_one_out_low
Testing test_setup_many_out_no_init
Testing test_setup_many_out_one_init
Testing test_setup_many_out_many_init
Testing test_setup_one_in
Testing test_setup_one_in_pull
/home/matt/src/deepdrive/venv/lib/python3.8/site-packages/Jetson/GPIO/gpio.py:345: UserWarning: Jetson.GPIO ignores setup()'s pull_up_down parameter
  warnings.warn("Jetson.GPIO ignores setup()'s pull_up_down parameter")
Testing test_setup_many_in
Testing test_setup_all
Testing test_cleanup_one
Testing test_cleanup_many
Testing test_cleanup_all
Testing test_input
Testing test_output_one
Testing test_output_many_one_value
Testing test_output_many_many_value
Testing test_out_in_init_high
Testing test_out_in_init_low
Testing test_gpio_function_unexported
Testing test_gpio_function_in
Testing test_gpio_function_out
Testing test_wait_for_edge_timeout
Testing test_wait_for_edge_rising
Testing test_wait_for_edge_falling
Testing test_event_detected_falling
Testing test_event_detected_rising
Testing test_event_detected_both
Testing test_event_callbacks
Testing test_multi_events_detected_diff_edge
Testing test_multi_events_detected_same_edge
Testing test_pwm_multi_duty
Traceback (most recent call last):
  File "test_all_apis.py", line 1084, in <module>
    test()
  File "test_all_apis.py", line 1009, in test_pwm_multi_duty
    assert min_ct <= count <= max_ct
AssertionError

@mattwilliamson
Copy link
Author

Oh it seems that I figured it out. It's quite interesting. Order matters. If I do all the pin setup one at a time it is working.

This will NOT WORK:

GPIO.setup(lpin[0], GPIO.OUT)
GPIO.setup(rpin[0], GPIO.OUT)

GPIO.setup(lpin[1],GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(rpin[1],GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(lpin[2], GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(rpin[2], GPIO.OUT, initial=GPIO.LOW)

lpwm = GPIO.PWM(lpin[0], hz)
rpwm = GPIO.PWM(rpin[0], hz)

lpwm.start(0)
rpwm.start(0)

This WILL work:

GPIO.setup(lpin[1],GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(rpin[1],GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(lpin[2], GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(rpin[2], GPIO.OUT, initial=GPIO.LOW)

# Setup this pin and pwm first
GPIO.setup(lpin[0], GPIO.OUT)
lpwm = GPIO.PWM(lpin[0], hz)
lpwm.start(0)

# then this one
GPIO.setup(rpin[0], GPIO.OUT)
rpwm = GPIO.PWM(rpin[0], hz)
rpwm.start(0)

I'm not sure if it's a bug or if it's a hardware limitation that should be documented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants