The goal of this API is to allow .NET Core developers to access low-level hardware controllers on IoT devices such as Raspberry Pi, Hummingboard, Odroid, DragonBoard, etc. This will allow applications to read/write data from/to sensors, LED's, motors, and other kinds of peripherals connected to such a device. This API should support the most common low-level device protocols, including General Purpose IO (GPIO) pins, serial communication protocols like SPI and I2C, Pulse Width Modulation (PWM), and Analog-to-Digital Converters (ADC).
(NOTE: italicsized namespace are not yet addressed in this document.)
System.Device.Gpio
: Will contain the types that allow access to the GPIO pins in order to opening and closing pins, reading and writing values to them, and subscribing for event notifications.System.Device.Pwm
: Will contain the types that allow access to PWM (Pulse Width Modulation). This will allow developers to send square waves over a pin in order to simulate analog values from digital outputs.System.Device.I2c
: Will contain the types that allow developers to communicate with devices that use the I2C protocol to transfer data.System.Device.Spi
: Will contain the types that allow developers to communicate with devices that use the SPI protocol to transfer data.System.Device.Adc
: Will contain the types that allow developers to communicate with analog-to-digital converter devices.
Iteration 1 proposed a pin-object based API. Iteration 2 proposed an integer-based API, with no pin object. This iteration proposes a "best of both" API. It is pin-object based, but also provides the simplicity of the integer based API. Because the pin objects are public, the disposable (lifetime) issues are moved from the controller to the pins.
- Allows the application or library developer the flexibility to use whichever model is best for their implementation. Library developers would be encouraged to use the pin-object model due to better performance, since it is direct to the pin implementation (no validation or dictionary lookups).
- Begins with a pin-object model, which models the actual objects involved, as well as a more direct mapping to how each driver will implement the model, and then the pin integers can also be used as wrappers around the pin object.
- By having the pin objects be disposable and public, the developer is only concerned about the lifetime of the pin object.
- The lifetime of the controller singleton model goes away, since it would no longer need to be disposable.
- Would it really be so confusing to a developer to have this flexibility???
These examples do not deal with Controller lifetime (Singleton, Disposable).
const int led = 5;
var controller = GpioController.Default;
controller[led].OpenPin(PinMode.Output);
for (int i = 0; i < 5; ++i)
{
controller[led].Write(PinValue.High);
Thread.Sleep(TimeSpan.FromSeconds(1));
controller[led].Write(PinValue.Low);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
controller[led].ClosePin();
const int led = 5;
var controller = GpioController.Default;
controller.OpenPin(led, PinMode.Output);
for (int i = 0; i < 5; ++i)
{
controller.Write(led, PinValue.High);
Thread.Sleep(TimeSpan.FromSeconds(1));
controller.Write(led, PinValue.Low);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
controller.ClosePin(led);
var controller = GpioController.Default;
using (GpioPin led = controller.OpenPin(5, PinMode.Output))
{
for (int i = 0; i < 5; ++i)
{
led.Write(PinValue.High);
Thread.Sleep(TimeSpan.FromSeconds(1));
led.Write(PinValue.Low);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
const int button = 4;
var controller = GpioController.Default;
controller[button].OpenPin(PinMode.Input);
for (int i = 0; i < 5; ++i)
{
Console.WriteLine($"Button value is: {controller[button].Read()}");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
controller[button].ClosePin();
const int button = 4;
var controller = GpioController.Default;
controller.OpenPin(button, PinMode.Input);
for (int i = 0; i < 5; ++i)
{
Console.WriteLine($"Button value is: {controller.Read(button)}");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
controller.ClosePin(button);
using (GpioPin button = GpioController.Default.OpenPin(4, PinMode.Input))
{
for (int i = 0; i < 5; ++i)
{
Console.WriteLine($"Button value is: {button.Read()}");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
const int button = 6;
var controller = GpioController.Default;
controller[button].OpenPin(PinMode.Input);
controller[button].DebounceTimeout = TimeSpan.FromMilliseconds(10);
WaitForEventResult result = controller[button].WaitForEvent(PinEventTypes.Falling | PinEventTypes.Rising, TimeSpan.FromSeconds(5).Milliseconds);
Console.WriteLine((result.TimedOut) ? "Timed out waiting for an event" : "Succesfully got an Event!");
controller[button].ClosePin(button, PinMode.Input);
const int button = 6;
var controller = GpioController.Default;
controller.OpenPin(button, PinMode.Input);
controller.SetDebounceTimeout(TimeSpan.FromMilliseconds(10));
WaitForEventResult result = controller.WaitForEvent(button, PinEventTypes.Falling | PinEventTypes.Rising, TimeSpan.FromSeconds(5).Milliseconds);
Console.WriteLine((result.TimedOut) ? "Timed out waiting for an event" : "Succesfully got an Event!");
controller.ClosePin(button, PinMode.Input);
using (GpioPin button = GpioController.Default.OpenPin(button, PinMode.Input))
{
button.DebounceTimeout = TimeSpan.FromMilliseconds(10);
WaitForEventResult result = button.WaitForEvent(PinEventTypes.Falling | PinEventTypes.Rising, TimeSpan.FromSeconds(5).Milliseconds);
Console.WriteLine((result.TimedOut) ? "Timed out waiting for an event" : "Succesfully got an Event!");
}