Is there a way to specifically set values to an LED pin using the library?

Viewed 388

My friend is using the GPIO library; .NET IoT 1.3

He was trying to control the brightness/strength of the LED, but the library seems to only have a way to turn the LEDs on and off.

Here is some code I've quickly sprung up as to show what I mean

using System;
using System.Device.Gpio;
using System.Threading;

int pin = 17;
using var controller = new GpioController();
controller.OpenPin(pin, PinMode.Output);
controller.Write(pin, PinValue.High)

Whereas, PinValue, according to the documentation has the values "High" and "Low". But seemingly no way to adjust it specifically.

https://docs.microsoft.com/en-us/dotnet/api/system.device.gpio.pinvalue?view=iot-dotnet-1.3

Now, in Python it's very simple to control LED brightness; using the GPIO Zero library:

from gpiozero import LED
from signal import pause

led = LED(17)

led.value = 0.5

pause()

Is there any way, without modifying memory, to achieve this using the given .NET Library?

2 Answers

Well, this is interesting because all 17 of the GPIO pins on the Raspberry Pi are digital and not analogue. Which means they can only send down 2 values. A zero or a one.

I have been looking at the C# implementaion and you are right in that the class GpioPinValue is an enum with only 2 options so when you call write to write to a port you can only write High (1) or Low (0).

.NET Core IoT Library

I even took a look at Microsofts new IoT library for .NET Core that can be found here: https://github.com/dotnet/iot

Looking at the source code for the GpioController.cs class this new framework takes in a PinValue.cs object that you can use to write too.

public virtual void Write(int pinNumber, PinValue value)

But even in the new code, the PinValue object has a private byte field which you dont have access to and a private constructor. It also declares 2 public fields. 1 for Low and 1 for high as you can see here:

public readonly struct PinValue : IEquatable<PinValue>
{
    // This isn't bool so the struct will retain blittable. This
    // allows arrays of PinValue and structs that contain PinValue to
    // be stack allocated.
    private readonly byte _value;

    private PinValue(byte value) => _value = value;

    /// <summary>
    /// The value of the pin is high.
    /// </summary>
    public static PinValue High => new PinValue(1);

    /// <summary>
    /// The value of the pin is low.
    /// </summary>
    public static PinValue Low => new PinValue(0);

So on the face of it, I cant see how you can write a value between 0 and 1 (eg 0.5) to one of those GPIO ports.

If that Python code sample actually works on a Raspberry Pi it would be interesting to see if anyone can explain what its doing!

You can do that, but not with GPIO. You need a PWM pin and a PWM object. Unlike gpizero, Iot does not automatically switch to PWM if you write a value other than 0 or 1. The Raspberry Pi has only 2 PWM channels, so you can only control 2 LEDs this way. The pins are usually (logical) 12 and 13, but can be switched to 18 and 19.

Here is a link describing the usage of PWM with the IOT library.

Very simplistic example:

static void Main(string[] args)
        {
            Console.WriteLine("Hello PWM!");
            var pwm = PwmChannel.Create(0, 0, 400, 0.5);
            pwm.Start();
            Console.ReadKey();
        }

This will set the led on pin 12 to 50% brightness, given the following entry in /boot/config.txt:

dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4
Related