Creating nodes for the Nvidia Jetson Nano

Moving my original post and progress to the correct category...

I'm using node-red-node-pi-gpio as a starting place but I've had to make a lot of modifications for a number of reasons:

  1. The sysfs method of interfacing with GPIO has long since been deprecated in the kernel (circa 4.8) and is not available on Fedora. Therefore I'm porting things to use the libgpiod library.

  2. Due to #1, I'm going to call the binaries directly (gpioget, gpioset, gpiomon) so all the python stuff is gone. One nice thing about the python library is it mapped the IO pin number to the correct GPIO BCM. libgpiod doesn't do this so I must map things myself.

The nice thing about this overall approach is that it can be easily ported to any GPIO device supported by libgpiod.

I've created the following logic to call gpiomon with the correct BCM number but it's not working. I am not a javascript programmer by any means so a lot of this is guessing and googling.

    var pin2bcm = {
        "3":"2", "5":"3", "7":"4", "8":"14", "10":"15", "11":"17", "12":"18", "13":"27", "15":"22",
        "16":"23", "18":"24", "19":"10", "21":"9", "22":"25", "23":"11", "24":"8", "26":"7",
        "29":"5", "31":"6", "32":"12", "33":"13", "35":"19", "36":"16", "37":"26", "38":"20", "40":"21"
    }

Which now that I look at the github version has since been added with the exact same name. Funny.

I've got the inputs mostly working because gpiomon doesn't exit so the functionality is similar to the rpi-gpio, however, function GPIOOutNode(n) also wants a process that doesn't exit, but gpioget returns the state and exits.

This of course triggers node.on("close"... and the status goes to not-running.

Before I roto-rooter the logic, can someone point me to a best practice for how to handle this situation?

Basically, as long as it exits 0 then the command was successful.

Thanks,
Richard

I dont see why it wouldn't work (but then you haven't showed how you are using it or what value is being used to perform the lookup).

this works...

const pin2bcm = {
        "3": 2, "5": 3, "7": 4, "8": 14, "10": 15, "11": 17, "12": 18, "13": 27, "15": 22,
        "16": 23, "18": 24, "19": 10, "21": 9, "22": 25, "23": 11, "24": 8, "26": 7,
        "29": 5, "31": 6, "32": 12, "33": 13, "35": 19, "36": 16, "37": 26, "38": 20, "40": 21
    };
let pin = 29; //testing
let bcm = pin2bcm[pin];
if (!bcm) {
  throw new Error(`pin ${pin} not found`);
}

Demo...

Sorry, I had drafted the message when it still wasn't working but later figured it out. I thought I had corrected my draft but I missed a few points.

Basically I had a fancy for loop to determine which pin mapped to what bcm because google failed to provide me with the simple answer:

this.bcm = pin2bcm[n.pin];

Monitoring inputs is kinda working. I still have to add logic around parsing the stdout from gpiomon.

The bigger problem is the second half... How to convert a node, in the case the output node, that's designed to spawn a process that doesn't "run and exit" to one that does.

Currently you can check the box to get the initial value, and then of course you can change its state via node.on("input".... With the current script I would need to have duplicate spawns for each case so I'm trying to write a function so it's only in one place.

        function gpioset() {
            if (node.set && (node.out === "out")) {
                node.child = spawn(gpioSetCmd, [gpiochip, node.bcm+"="+node.level]);
                node.status({fill:"green",shape:"dot",text:node.level});
            } else {
                node.child = spawn(gpioSetCmd, [gpiochip, node.bcm+"="+node.level]); //node.freq]);
                node.status({fill:"yellow",shape:"dot",text:"jetson-gpio.status.ok"});
            }
        }

I can't decide if I should add any arguments to the function, really everything I need is within scope of the parent GPIOOutNode(n) function.

Something else is troubling me too. In the above function I've started the process of converting it from the python Rpi library to gpioset, but the logic of the if/else clause, which is original to node-red-node-rpi-gpio, confuses me. To me it looks like if you don't have the "Initialize pin state" (node.set) option checked it assumes you're dealing with a PWM output.

So what happens if you want a DO (not pwm) and not set the initial state?

Well dang. Never mind. gpioset only holds the output while it's running and then returns it to the default. All the work I've done is mostly worthless.

So now that I have to basically start over, should I still try to remove the dependency on Python? Or just try to work through nrgpio.py and port it from RPi.GPIO to gpiod?

From a selfish standpoint I would like to see python removed.

It is an extra layer, two really if you count the shell script that launches it, but it also is where a lot of the I/O logic happens, such as software PWM.

If I go the direct route via the gpio commands, I'll be limited to basic digital input and output, which may be a good starting place.

What would really be helpful is a direct javascript extension library. Then I wouldn't even need libgpiod-utils.

Not sure if either of these help - or provide pointers - there is this awesome library that wraps a lot of things - pigpio - npm
BUT the way it works currently requires it to run as root - and I can't see a way around that...

The other one we do use is the js-pigpiod for the pi-gpiod nodes - but that uses the pigpiod backend - so that part runs as root and the link is via network - it also seems to be quite resource heavy on the CPU even for modest update speeds.

Also note - in the normal pi-gpio library I do have beta 2.0 branch where I am looking at moving the underlying calls to use the BCM mode (leaving the UI the same) - so that it then works with the Pi compute modules that don't have direct pins in the same way.

The "right" answer would be to try and build javascript bindings using SWIG on top of libgpiod...

http://www.swig.org/Doc3.0/Javascript.html

This is quite a bit out of my league though. I'm a hacker, not a professional programmer.

Ok, beware it's ugly, but I have something kinda working. I have not done any actual hardware tests yet, just tried to make sure node-red doesn't bomb out and doing a ps aux | grep gpio seems to show the correct output. Documentation still needs a lot of work.

2 Likes

I did some cleanup. Removed the mouse and keyboard stuff, that's better handled by other modules. And changed the kill method of gpioset so it works correctly instead of node-red timing out on stop/restart.

Ok, I have everything cleaned up in my github repo. @dceejay, do you actually have a Jetson Nano to test with?

Or you could try "porting" it back to the Pi? I think all you should have to do is change the gpiochip variable to what the Pi uses.

My next step is to pull the Nano out of the data closet (as the original purpose was to troubleshoot some Fedora packaging issues specific to aarch64) and put it back on the workbench so I can get to the GPIO for testing.

From my research the GPIO in the nano doesn't supply as much current as the Pi and won't run a LED directly (or it will, but dimly). Guess I need to dig out some LEDs and an optocoupler.

Hi. Sorry no I don’t have a nano at all. Happy to look at code if you like

Sure, that would be great. I don't think the PWM solution is going to work but I haven't had a chance to try it yet.

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