Jetson Nano (Waveshare) PWM GPIO

Due to supply shortage we have been forced to buy the Jetson Nano from Waveshare with the eMMC module.

We can flash it trough the SDKmanager but we are not able to access the PWM-pins on the Jetson. running sudo /opt/nvidia/jetson-io/ doesn’t give us access to configure the 40 pin header. This board is an “alternative” and support is lacking.

This is a long shot but have anyone else had success accessing the PWM-pins om a similar board?

On the board with the dev kit from nvidia we access the PWM-pins through python and Jetson.GPIO with no issues. Could we access them on a lower level? Anyone have any tips, would be greatly appreciated!

Hi there

Not sure but If you are willing to program in C/C++ maybe you could have a go with my library? The way I did it, it doesn’t use the kernel driver for the PWM, it is a beta yet but it should work with any Nano. I put an example of how to use the PWM as well on git and I am keen for people to beta test the thing.

Thanks I will have a go at it. Not quite competent troubleshooting compile errors on c though.

Get an error when trying to compile.

user@ubuntu:~/dev/JETGPIO$ make
gcc -c -Wall -Werror -fpic jetgpio.c
gcc -shared -o jetgpio.o

user@ubuntu:~/dev/JETGPIO$ sudo make install
install -m 0755 /usr/lib
install -m 0644 jetgpio.h /usr/include
ldconfig -p | grep (libc6,AArch64) => /usr/lib/

user@ubuntu:~/dev/JETGPIO$ gcc jetgpio_example.c -o jetgpio_example
/tmp/ccQ3ZfK4.o: In function `main':
jetgpio_example.c:(.text+0x10): undefined reference to `gpioInitialise'
jetgpio_example.c:(.text+0x54): undefined reference to `gpioSetMode'
jetgpio_example.c:(.text+0x98): undefined reference to `gpioSetMode'
jetgpio_example.c:(.text+0xdc): undefined reference to `gpioSetPWMfrequency'
jetgpio_example.c:(.text+0x120): undefined reference to `gpioPWM'
jetgpio_example.c:(.text+0x170): undefined reference to `gpioWrite'
jetgpio_example.c:(.text+0x180): undefined reference to `gpioRead'
jetgpio_example.c:(.text+0x1a8): undefined reference to `gpioWrite'
jetgpio_example.c:(.text+0x1b8): undefined reference to `gpioRead'
jetgpio_example.c:(.text+0x1f0): undefined reference to `gpioTerminate'
collect2: error: ld returned 1 exit status

Some part I am missing?

Yes, compile with this instead: gcc -Wall -g -o jetgpio_example jetgpio_example.c -I./ -ljetgpio
if you have a look at the code there is a comment at the top of: jetgpio_example.c, then to execute: sudo ./jetgpio_example

This example will generate a 10khz PWM signal with a duty cycle of approx. 78% at pin 32 (LCD_BL_PWM) let me know how it goes

Thanks, I saw that. Sloppy of me to miss it. Been trying to fool around with it dimming LEDs. I am able to increment the dutycycle to increase brightness of the LEDs but I am not able to lower the brightness.

The increase in brightness is not linear either and skips a few steps in the while-loop. I’m probably doing it wrong.

int PWMstat = gpioSetPWMfrequency(32, 1000);
int PWMstat2 = gpioPWM(32, 0);

int x = 0;
int level = 0;
int status;

// Increase brightness 
while (x<=256) {
    level = x;
    printf("level: %d - ",level);
    status = gpioPWM(32, x);
    printf("status: %d\n",status);

x = 256;

// Decrease brightness returns status 1 but does not lower the brightness
while (x>=0) {
    level = x;
    printf("Setting level: %d",level);
    status = gpioPWM(32, x);
    printf("status: %d\n",status);

Also it does not seem to work for PWM pin 33. Nothing happens when I try to set the frequency or duty cycle.

Thanks for that, your code is absolutely fine, you just helped me to find a bug, I found it so hopefully will have this sorted out by tomorrow, it should be quick. If you want you can download the lib again like in 24h (same make and sudo make install that will overwrite the current version) and your code should work fine this time. Thanks again for your feedback

OK Stefan, both issues are sorted out, pin 33 also works as expected. If you are kind enough to download again, and reinstall the library this time your code will work as expected.
Only thing, try to put a gpioTerminate(); at the end of your program so the library recovers the registers to their previous state before exiting.

Thanks a lot for this repo. We manage to successfully use it to control LEDs through PWM in our application. Greatly appreciated and good work!

However we need to control the LEDs through a sustained period. Do you think there is a problem omitting the gpioTerminate()? If we call this function the defaults to HIGH on both PWM-pins.

I am going to explain a bit how both: gpioInitialise() and gpioTerminate() work. The first one is going to make a backup of the pins status at the time this function is called (whatever that status is), gpioTerminate() will return the system to the point it was before by using that backup. So the idea is Initialise makes a backup when you start the library and Terminate recovers that backup and takes the pins to their previous state.

What might happen is, let’s say you have a program like yours setting up the PWM, if you interrupt that program e.g. Control-C when the pin is HIGH, if you don’t reboot the nano the pin will remain HIGH and Terminate() will recover the system to that point when you execute your program next time (it is not going to know the difference, remember that for whatever the reason on a clean/default image some pins are HIGH by default).

Something you can do to verify this is:

  1. Reboot your nano (pins 32 & 33 should be LOW now)
  2. Compile & execute a program just calling Initialise() and Terminate() something like this:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <jetgpio.h>

int main(int argc, char *argv)
int Init;

Init = gpioInitialise();

// Terminating library



Pins should be LOW after executing this, if that is not the case, please let me know because that would be very weird.

So in short gpioTerminate() it is not going to setup your pins HIGH, it should be called always to make sure that the pins’s state goes back to before using the library functions.

If you program in C any interruption (like a user doing a Control-C on keyboard) should be captured by using signal() and the function handler should execute gpioTerminate() to ’ clean’ everything before exiting. If using C++ then you should use try catch.

Please reboot your nano and run that little test calling only gpioInitialise() and gpioTerminate() and let me know what happens.

Again, an option would be for the library itself to capture any interruption but I left it to the user as this would have other implications, also Terminate could be resetting the CPU registers but by doing that this could have an impact on other software, those are all design decisions and there is not a clear cut answer to that depending on the situation one could be better than the other.

Thanks for your feedback again and let me know how it goes, my apologies for not having proper documentation yet but I do this on my spare time, that will come.

Also I uploaded a small program (basically your example) but using signal() called “test_PWM.c” to my github , if you compile and execute this one and you do a CONTROL-C while executing you will see how the pin goes to LOW. This is to illustrate how to manage exceptions and how it could be done. Again let me know how it goes.

Thanks for the feedback. However the pins for PWM (32,33) are set to high by default when rebooting or power cycle. I tried googling to change this default behaviour but could not find any “easy” information on this.

For our application we control intensity of led strips that are on 24/7. We use normal white lights at a certain intensity during daytime and infra red lights at a certain intensity during the night. Either white or infra red lights is always on at a certain intensity. The system can be run on batteries and solar power so it’s not so good that the both pin 32 and 33 is set to high or 100% during boot. This drains the batteries pretty quickly.

My approach at the moment is using your program in our application that on the start of our application check if it’s night or day, set the lights accordingly without gpioTerminate(). When day becomes night and vice versa we repeat the process.

Could there be other implications omitting the gpioTerminate()?

I understand, on my nano 32 & 33 are set to tristate on boot (low basically). The implications are just that, by not using gpioterminate() the pins will remain at whatever the state they were when you stop your program or the program finishes execution. So for instance if your program crashes for some reason when pwm @ 33 is 90% it will continue to do that until the nano reboots. You should check the Nvidia docs on how to change the default behaviour of pins (change the kernel tree), for instance articles like this: About change gpio by change pinmuxfile or this one: Changing Device Tree and Compiling Kernel for NVIDIA Jetson Xavier NX | by Hao Ye | Medium.
Finally remember that my library is a BETA, that means that it hasn’t been tested enough to be considered safe to use on critical/industrial applications, if you use it, please test your program thoroughly before putting the system in production.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.