Nano PWM C++

Trying to do PWM with Jetson Nano.

Using the library at https://github.com/pjueon/JetsonGPIO . Seems to work ok for GPIOs and for PWM0 (pin 33) (at least to instantiate the PWM control code). If I try to instantiate a PWM instance for Pin 32, my application immediately crashes with:

[Exception] Can’t open /export (catched from: PWM::PWM())
terminate called after throwing an instance of ‘std::runtime_error’
what(): Can’t open /export
Aborted (core dumped)

I’ve enabled both PWM channels using the jetson-io.py tool, I’ve installed the JetsonGPIO library, the /sys/kernel/debug/pinctrl/700008d4.pinmux/pinmux-pins file shows the following:
root@jetson-robot:/sys/kernel/debug/pinctrl/700008d4.pinmux# cat pinmux-pins | grep -i pwm
pin 38 (PE6): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function pwm2 group pe6
pin 168 (LCD_BL_PWM PV0): 700008d4.pinmux (GPIO UNCLAIMED) (HOG) function pwm0 group lcd_bl_pwm_pv0
pin 217 (DVFS_PWM PBB1): (MUX UNCLAIMED) (GPIO UNCLAIMED)

output from sudo cat /sys/kernel/debug/pwm is:

platform/70110000.pwm, 1 PWM device
pwm-0 (pwm-regulator ): requested enabled period: 2500 ns duty: 0 ns polarity: normal

platform/7000a000.pwm, 4 PWM devices
pwm-0 (sysfs ): requested period: 0 ns duty: 0 ns polarity: normal
pwm-1 (pwm-regulator ): requested enabled period: 8000 ns duty: 1440 ns polarity: normal
pwm-2 ((null) ): period: 20000000 ns duty: 10000000 ns polarity: normal
pwm-3 (pwm-fan ): requested enabled period: 45334 ns duty: 0 ns polarity: normal

Any ideas on how to troubleshoot? My project needs the two different frequency PWM outputs.

Thanks!

hello nvidia5,

the pin LCD_BL_PWM is default configure as GPIO pin,
could you please access Pinmux spreadsheet through download center.
please also refer to Configuring the 40-pin Expansion Header, and you’ll need to configure the pin as PWM for verification.
thanks

Ok, so am I incorrect in believing that this configuration is supposed to be handled by jetson-io.py – as the second link you posted says?

I’ve configured it as a pwm pin using the procedure in that link.

Any other ideas?

@JerryChang – am I incorrect in my understanding here?

please check the last paragraph of https://github.com/pjueon/JetsonGPIO,

The system pinmux must be configured to connect the hardware PWM controlller(s) to the relevant pins. If the pinmux is not configured, PWM signals will not reach the pins! The JetsonGPIO library does not dynamically modify the pinmux configuration to achieve this. Read the L4T documentation for details on how to configure the pinmux.

you should have pinmux configuration to set the pin as PWM, then you’ll able to use it.
thanks

I’m aware of that.

The document you’re quoting is seven months old, before jetson-io.py and the latest version of the jetson nano software was released.

The question I’m asking is did not the jetson-io.py replace the pinmux spreadsheet configuration method as it seems to be from your second link posted above? If not, what’s the purpose of jetson-io.py?

hello Josh1745,

pinmux spreadsheet shows the default pin configurations; you’ll need to have customization and then flash the new configuration to the developer kit if you have different pin configurations.
Jetson-IO could overwrite the pin configuration dynamically.
thanks

if Jetson-io overwrites the pin configuration dynamically, why doesn’t the second PWM pin work when it’s told to configure it as a pwm pin?

The reason I’m really asking is that the pinmux configuration procedure documented in your documentation doesn’t work, so I’ve got to find another way.

hello Josh1745,

could you please refer to Control PWM through sysfs to configure PWM0, this process should be similar in Nano.

FYI,
here also a discussion thread Topic 107310, which show the steps to control the PWM.
thanks

Thanks for the links. I’ve been through all of that already.

Here’s the output when I run through trying to manually export both PWM pins:

josh@jetson-robot:/sys/class/pwm$ ls
pwmchip0 pwmchip4
josh@jetson-robot:/sys/class/pwm$ ls pwmchip0/
device export npwm power subsystem uevent unexport
josh@jetson-robot:/sys/class/pwm$ cd pwmchip0/
josh@jetson-robot:/sys/class/pwm/pwmchip0$ echo 0 > export
josh@jetson-robot:/sys/class/pwm/pwmchip0$ ls
device export npwm power pwm0 subsystem uevent unexport
josh@jetson-robot:/sys/class/pwm/pwmchip0$ cd …
josh@jetson-robot:/sys/class/pwm$ cd pwmchip4/
josh@jetson-robot:/sys/class/pwm/pwmchip4$ ls
device export npwm power subsystem uevent unexport
josh@jetson-robot:/sys/class/pwm/pwmchip4$ echo 0 > export
-bash: echo: write error: Device or resource busy
josh@jetson-robot:/sys/class/pwm/pwmchip4$

Hi Josh1745,

You can only access pwmchip0 (@7000a000).
pwmchip4(@70110000) is not expected to be used by user.

“The Pulse Width Modulator controller is a four channel frequency divider whose pulse width varies. Each channel has a programmable frequency divider and a programmable pulse width generator”

As per the above statement, individual 4 channels of pwm@pwmchip0 can be used (based on availability) by exporting them.
i.e. echo <0/1/2/3> > /sys/class/pwm/pwmchip0/export

Please try with above and let us know what problem do you face on your configuration.

Thanks & Regards,
Sandipan

1 Like

Sandipan – thank you very much for that clarification. I understand now, and I can at least manually set the parameters and activate the second PWM line.

Greatly appreciated!

In addition to the misconception I had here that was explained above by Sandipan, the library I referenced in the OP is broken. I’ve fixed the library and the working library is at this link:

1 Like

@Josh1745 were you successful in using jetson-io.py to activate hardware PWM on pin 32, or does this still require the more cumbersome route through the Pinmux spreadsheet modification? I’ve spent hours trying to get PWM to work on the Nano, and while using jetson-io.py appears to activate the PWM, its behavior appears to be erratic at best when in operation: I was hoping to use it to control backlight dimming at 200 Hz of a connected LCD / TFT panel. The following works perfectly when run on a Raspberry Pi, but using the same on the Nano after it was configured for PWM on Pin 32 through jetson-io.py, I get very irregular flickering on the LCD panel, and no dimming at all:

cd /sys/class/pwm/pwmchip0
echo 0 > export
sleep 1
cd pwm0
echo 5000000 > period
echo 2500000 > duty_cycle
echo 1 > enable

I have also tried to go the Pinmux spreadsheet route as described in the customizing_the_jetson_nano_40-pin_expansion_header_v1.2.pdf document (and also here: https://www.seeedstudio.com/blog/2020/05/27/configure-pwm-output-on-jetson-nano-m), on JetPack 4.4, but this appears to always hang when flashing the Nano, after these lines in the output of flash.sh:

[   0.7724 ] Retrieving storage infomation
[   0.7960 ] Applet is not running on device. Continue with Bootloader

Before I keep trying to get the flashing to work, I’d like to find out if this is actually supposed to produce a different result than using jetson-io.py on JetPack 4.4 / L4T R32, revision 4.3?

What am I not getting right? Or is PWM on the Nano simply unreliable or broken?

@juerg

So here’s the deal. I don’t know exactly how the dev kit is built, but I do know the gpios (including PWM) have essentially no ability to power anything.

First, you don’t need to do the pinmux spreadsheet. You can just use the jetson-io.py and that works fine. I’ve connected the pwm pins directly to a high impedance (digilent logic analyzer), and they do exactly what they’re supposed to once configured using the jetson-io.py file.

However, what you have to do is provide a buffer on the output of the GPIO that has extremely high impedance so that it doesn’t load the pin AT ALL. I chose an op amp, specifically this one – NCV2902DTBR2G – and configured it as a unity-gain amp (connected the output directly to the inverting input).

I just tested this this afternoon, and it is generating PWM and seems to sort of work. I need to put it on the logic analyzer, which I will do either later tonight or tomorrow, and see if it’s working right or if I need to add pull-ups or something else – I might also just need to adjust some values in my code as well, it’s a rather complex application with a bunch of levels of abstraction.

Another thing to look at – I’m not sure that 250000 is the right value for duty cycle. Try 50 just for good measure. I think that duty cycle is just an integer between 0 and 100. I’ll try that when I get my digilent out later and see – I know in the library I use that’s what it is anyway.

1 Like

@Josh1745 great, thank you for looking into this! I’d be very interested to hear what the logic analyzer will show. Regarding the duty cycle: I’m pretty sure it is the correct value for 50% When working with the file system, the values provided are in nanoseconds. And it produces the desired result on the Raspberry Pi.

@juerg – I’ve tested this with a logic analyzer, the solution I showed earlier works and is rock solid. Basically just need a high impedance buffer on the output of the pwm line before it goes into anything else.

1 Like

@Josh1745 thank you for looking into this! I will try this approach with the high impedance buffer and report back here once I get to it. It’ll be in about 2 weeks, after the holidays.

1 Like