dotnet / iot

This repo includes .NET Core implementations for various IoT boards, chips, displays and PCBs.
MIT License
2.17k stars 585 forks source link

Additional Hardware - Nvidia Jetson Family #1957

Open skywalkerisnull opened 2 years ago

skywalkerisnull commented 2 years ago

We are developing a number of solutions using the Nvidia Jetson platform: https://developer.nvidia.com/embedded/jetson-modules we have deployed systems from the Nano, through to the AGX and are in the process of designing custom carrier boards for our production versions that will be the NX and the AGX form factors of the Orin series.

One component of our solution has a Blazor Server side service running that will need to interact with the GPIO to control relays, but also gather information from a series of environmental sensors such as temp, humidity, GNSS etc.

I note that on the roadmap, there is a Custom Hardware. The current Jetson Nano has a very similar GPIO pinout to the Raspberry Pi, but it is not quite the same: Jetson Nano 2GB Developer Kit User Guide. A python library already exists that may be possible to use to more easily get the details from.

The following require an account with Nvidia to access:

Jetson Xavier NX: https://developer.nvidia.com/embedded/downloads#?search=Jetson%20Xavier%20NX Jetson Orin NX: https://developer.nvidia.com/embedded/downloads#?search=Jetson%20Orin%20NX Jetson Xavier AGX: https://developer.nvidia.com/embedded/downloads#?search=Jetson%20Xavier%20AGX Jetson Orin AGX: https://developer.nvidia.com/embedded/downloads#?search=Jetson%20AGX%20Orin

raffaeler commented 2 years ago

I never had a Jetson in my hands and I am not familiar with it. Are you interested in contributing by creating a "driver" (a class in this repo) for the Jetson family? If you are already using the hardware, it should not be too hard taking the Raspberry PI driver, and adjust the Gpios and peripherals.

pgrawehr commented 2 years ago

Just to clarify: This device group is a set of single-board-computers with an ARM64 CPU, normally running linux. Is that correct?

Our linux drivers are actually quite generic. Have you tested that accessing the GPIO pins doesn't just work out of the box? Does the OS provide the low-level devices (does /sys/class/gpio/ exist)?

skywalkerisnull commented 2 years ago

@raffaeler We can assist with the development of a set of drivers for the models (each model has a slightly different set of GPIO and SPIO configuration) that we are using and contribute them back. Currently in the planning stages of what parts of the software will be ported over to dotnet from existing python prototype we have, and what GPIO/SPIO that we need to interact with via the Blazor application.

@pgrawehr it is an ARM64 platform running a modified flavour of Ubuntu from Nvidia, we have not yet tested if this library will work for us as is. Yes we can access /sys/class/gpio/

@avaki11

pgrawehr commented 2 years ago

@skywalkerisnull Ok, then you should be able to at least test most things with the sysfs or libgpiod drivers. They might not provide all features, but for testing, it should be fine.

raffaeler commented 2 years ago

@skywalkerisnull from what I read here libgpiod exists and is the preferred way to access the I/Os from a performance perspective. Once you get the libgpiod support for your board, the remaining work is straightforward. Basically it's just a matter of providing the correct pin numbering/mapping and few other things as for the link I posted before. Given the Nvidia link I posted here is dated 2y ago, there is the possibility that Nvidia provides a better deployment option for libgpiod.

Said that, this repository lives mostly thanks to the contributions from the community. I am not a Microsoft employee, but just a member of the community and part of the triage team together with @pgrawehr and other Microsoft folks.

We are more than glad to accept contributions from people who is working on other boards/hardware and that is able to test appropriately the code. I really hope you can open a PR and contribute one or more Jetson board in this repository. Thank you

avaki11 commented 1 year ago

@krwq @raffaeler @pgrawehr I am currently testing out dotnet iot library with a sample that blinks an LED. As you can see in the code below libgpiod has been installed and is running. But for some reason when I hits using var controller = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver()); I get no error message and my program is exited. The error message was found through debug console by running using var controller = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver()); Error message:

Loaded '/home/test/.dotnet/shared/Microsoft.NETCore.App/7.0.0/System.Diagnostics.Process.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Loaded '/home/test/.dotnet/shared/Microsoft.NETCore.App/7.0.0/System.ComponentModel.Primitives.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Loaded '/home/test/.dotnet/shared/Microsoft.NETCore.App/7.0.0/System.Memory.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Loaded '/home/test/.dotnet/shared/Microsoft.NETCore.App/7.0.0/System.Collections.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Loaded '/home/test/.dotnet/shared/Microsoft.NETCore.App/7.0.0/System.Collections.Concurrent.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
The target process exited with code 0 (0x00000000) while evaluating the function 'System.Device.Gpio.Drivers.LibGpiodDriver.LibGpiodDriver'.
Error processing 'evaluate' request. The process has been terminated.
using System.Device.Gpio;
using System.Device.Gpio.Drivers;

namespace GpioApp
{
    class Program
    {
        static void Main(string[] margs)
        {
            Console.WriteLine("Blinking LED. Press Ctrl+C to end.");
            int ledPin = 17;
            using var controller = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
            controller.OpenPin(ledPin, PinMode.Output);
            var loopCount = 1;
            while (true)
            { 
                Console.WriteLine($"loop {loopCount++}");
                controller.Write(ledPin, PinValue.High);
                Thread.Sleep(200);
                controller.Write(ledPin, PinValue.Low);
                Thread.Sleep(1000);
            }
        }
    }
}

libgpiod has been installed with the package manager:

>sudo apt install gpiod libgpiod-dev libgpiod2
Reading package lists... Done
Building dependency tree       
Reading state information... Done
gpiod is already the newest version (1.4.1-4).
libgpiod-dev is already the newest version (1.4.1-4).
libgpiod2 is already the newest version (1.4.1-4).
0 to upgrade, 0 to newly install, 0 to remove and 87 not to upgrade
pgrawehr commented 1 year ago

@avaki11 That looks like some problem with the use of libgpiod on that system. This behavior is typical for an access violation in an unmanaged library, but it's a bit weird we're getting a zero exit code in that case. Can you try to run the program using the native debugger? Maybe this gets some more information.

avaki11 commented 1 year ago

@pgrawehr As for now we have moved away from using new LibGpiodDriver() to using new SysFsDriver() This fixed the zero exit issue.

asheesh1996 commented 1 year ago

Hi, I am also trying to use jetson nano GPIO pins and as @avaki11 mentioned I was able to use Gpio Pins for motor control

GpioController gpioController = new GpioController(System.Device.Gpio.PinNumberingScheme.Logical, new SysFsDriver());

var motor = DCMotor.Create(76,51, gpioController, true, true);

//raspberry pi config

//var motor =  DCMotor.Create(19,16, null, true, true);

I followed the pin mapping given at Nvidia documentation page.

I want to know if there is a way to make a generic interface to use common pin mapping for raspberry pi boards and jetson boards?

pgrawehr commented 1 year ago

@asheesh1996 The pin mapping is very different from the RPI, it seems. Of course, it would be possible to create a Board class that defines a corresponding mapping, but since the capabilities are also very different (how many of each type of pins are available) I guess that would cause a lot of confusion. But of course yes, it's possible to create a mapping, but which one best suits the needs is unclear to me.

raffaeler commented 1 year ago

I am not sure that a board-neutral abstraction over pins would be a good idea. Every board has different flavors of pins:

@asheesh1996 I would instead suggest to you to create you own level of abstraction (a dictionay could easily do it) to remap the pins according to your specific needs/project.

asheesh1996 commented 1 year ago

Thanks @pgrawehr and @raffaeler for inputs, my major use cases with GPIO pins of jetson is using I2C and PWM. My target was to use my same working codebase(tested on pi4) on jetson, with doing minimal changes.After hearing your insights, I believe, it's better to make a pin mapping and move forward.

pgrawehr commented 1 year ago

@asheesh1996 If your main use case is I2C and PWM, you could of course create a jetson-board. That would declare the default pins for I2C, PWM (and SPI), and would make the use of these devices transparent. You can look at RaspberryPiBoard class and implement something accordingly. If you want a mapping that makes the jetson's GPIO header look like an RPI one, you can do that as well, but I would at least add a parameter for that.

krwq commented 1 year ago

@asheesh1996/@avaki11/@skywalkerisnull did you have any luck on using Jetson with .NET IoT? We don't currently have hardware to try this out so we'd need your help to get that to work

asheesh1996 commented 9 months ago

@asheesh1996/@avaki11/@skywalkerisnull did you have any luck on using Jetson with .NET IoT? We don't currently have hardware to try this out so we'd need your help to get that to work

Hi @krwq, sorry for the delayed response I was able to run the .NET IOT codebase on Jetson Nano and Jetson Xavier using the SysFysDriver.

You can refer the earlier message https://github.com/dotnet/iot/issues/1957#issuecomment-1327749091 it worked for me and I can help you out with testing if needed.

pgrawehr commented 9 months ago

@asheesh1996 Nice you got it to work. You might want to try libgpiod as well, as this is (if it works) a lot faster. But depending on your application, speed might not be an issue. (e.g. if you're just switching LEDs or Relays, sysfs is still more than fast enough)

If you were able to sort out the pin mapping, you could write a board-specific implementation for the Board class. That's where we define for specific boards how many pins there are and what capabilities they have.