Name: raspberryio
Owner: Unosquare Labs
Description: The Raspberry Pi's IO Functionality in an easy-to-use API for Mono/.NET/C#
Created: 2016-11-20 14:47:41.0
Updated: 2018-05-24 22:22:28.0
Pushed: 2018-05-10 20:57:03.0
Homepage: https://unosquare.github.io/raspberryio
Size: 8998
Language: C#
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
:star: Please star this project if you find it useful!
The Raspberry Pi's IO Functionality in an easy-to-use API for .NET (Mono/.NET Core). Our mission is to make .NET a first-class citizen in the Python-centric community of Raspberry Pi developers.
This library enables developers to use the various Raspberry Pi's hardware modules:
Please note you program needs to be run with `sudo
. Example ``
sudo mono myprogram.exe``` in order to work correctly.
This library depends on the wonderful `WiringPi
library available [here](http://wiringpi.com/). You do not need to install this library yourself. The ``
RaspberryIO``` assembly will automatically extract the compiled binary of the library in the same path as the entry assembly.
We offer an additional package with helpful classes to use peripherals, many of them are from pull requests from our contributors. The current set of peripherals supported are:
Install basic Raspberry.IO package:
Install-Package Unosquare.Raspberry.IO
Install Raspberry.IO Peripherals package:
Install-Package Unosquare.RaspberryIO.Peripherals
It is recommended that you install the latest available release of Mono because what is available in the Raspbian repo is quite old (3.X). These commands were tested using Raspbian Jessie. The version of Mono that is installed at the time of this writing is:
JIT compiler version 5.4.1.6 (tarball Wed Nov 8 21:42:16 UTC 2017)
The commands to get Mono installed are the following:
apt-get update
apt-get upgrade
apt-get install mono-complete
apt-get install dirmngr
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
"deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
apt-get update
apt-get dist-upgrade
apt-get update
apt-get upgrade
apt-get install mono-complete
apt-get install dirmngr
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
"deb http://download.mono-project.com/repo/debian stretch main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
apt-get update
apt-get dist-upgrade
Now, verify your version of Mono by running `mono --version
`. Version 4.6 and above should be good enough.
In order to setup Wi-Fi, run: sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
A good file should look like this:
try=US
_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
te_config=1
ork={
ssid="your_real_wifi_ssid"
scan_ssid=1
psk="your_real_password"
And then restart the services as follows:
systemctl daemon-reload
systemctl restart dhcpcd
You can also configure most boot options by running: sudo raspi-config
This project can also run in .NET Core 2.
Run the following commands to install .NET Core 2.
date Ubuntu 16.04
apt-get -y update
stall the packages necessary for .NET Core
apt-get -y install libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libcurl4-openssl-dev libssl-dev uuid-dev
wnload the latest binaries for .NET Core 2
https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz
ke a directory for .NET Core to live in
r ~/dotnet
zip the binaries into the directory you just created
-xvf dotnet-runtime-latest-linux-arm.tar.gz -C ~/dotnet
w add the path to the dotnet executable to the environment path
is ensures the next time you log in, the dotnet exe is on your path
home/pi/dotnet
"PATH=\$PATH:/home/pi/dotnet" >> dotnetcore.sh
mv dotnetcore.sh /etc/profile.d
en run the command below to add the path to the dotnet executable to the current session
=$PATH:/home/ubuntu/dotnet
nally, you can:
nano /etc/sudoers
d append to the secure_path option:
me/pi/dotnet
is will allow you to run dotnet in su mode
After that, you can reboot the raspberry. To check if dotnet is installed just run “dotnet” and a message should show. If you run into issues with error messages such as framework not found '2.0.0', it must be because the latest version might not be a stable version and the runtime is not rolled forward utomatically in this case. A simple solution is to create a 2.0.0 runtime symlink based on the current version. See the following link for detailed info: https://github.com/dotnet/cli/issues/7543
ocalhost~$ dotnet
e: dotnet [options]
e: dotnet [path-to-application]
ons:
|--help Display help.
version Display version.
-to-application:
e path to an application .dll file to execute.
DeployHost>172.16.17.54</SshDeployHost>
DeployTargetPath>/home/pi/Playground</SshDeployTargetPath>
DeployUsername>pi</SshDeployUsername>
DeployPassword>raspberry</SshDeployPassword>
dotnet sshdeploy push
in the same folder where Unosquare.RaspberryIO.Playground.csproj resides and if everything executes correctly you should see an output like this:Deployment Tool [Version 0.1.6.0]
015 - 2017 Unosquare SA de CV. All Rights Reserved.
additional help, please visit https://github.com/unosquare/sshdeploy
oying...
iguration Debug
ework netcoreapp2.0
ce Path C:\raspberryio\src\Unosquare.RaspberryIO.Playground\bin\Debug\netcoreapp2.0\publish
uded Files .ready|.vshost.exe|.vshost.exe.config
et Address 192.16.17.54:22
name pi
et Path /home/pi/Playground
n Target NO
Deployment
Deployment
ecting to host 192.16.17.54:22 via SSH.
ecting to host 192.16.17.54:22 via SFTP.
oying 8 files.
shed deployment in 1.25 seconds.
leted.
netcoreapp2.0
but you can change this by either modifying the RuntimeIdentifier property inside the csproj file or supplying it as a parameter like thisdotnet sshdeploy -f net452
. More information about dotnet-sshdeploy see thistu@ubuntu:~/publish$ sudo chmod u+x *
tu@ubuntu:~/publish$ ./Unosquare.RaspberryIO.Playground
The `Pi.Camera
module uses ``
raspivid` and
raspistill``
to access the camera so they must be installed in order for your program to work properly. `raspistill
arguments are specified in an instance of the ``
CameraStillSettings` class, while the
raspivid``
arguments are specified in an instance of the `CameraVideoSettings
` class.
The `Pi.Camera.CaptureImage*
methods simply return an array of bytes containing the captured image. There are synchronous and asynchronous falvors of these methods so you can use the familiar ``
async` and
await``
pattern to capture your images. All `raspistill
arguments (except for those that control user interaction such as ``
-k`) are available via the
CameraStillSettings``
. To start, create a new instance of the `CameraStillSettings
class and pass it on to your choice of the ``
Pi.Camera.CaptureImage*``` methods. There are shortcut methods available that simply take a JPEG image at the given Width and Height. By default, the shortcut methods set the JPEG quality at 90%.
Example using a shortcut method:
ic void TestCaptureImage()
var pictureBytes = Pi.Camera.CaptureImageJpeg(640, 480);
var targetPath = "/home/pi/picture.jpg";
if (File.Exists(targetPath))
File.Delete(targetPath);
File.WriteAllBytes(targetPath, pictureBytes);
Console.WriteLine($"Took picture -- Byte count: {pictureBytes.Length}");
Example using a CaptureImage method:
ODO: example code here
Capturing video streams is somewhat different but it is still very easy to do. The concept behind it is to Open a video stream providing your own callback. When opening the stream `Raspberry IO
` will spawn a separate thread and will not block the execution of your code, but it will continually call your callback method containing the bytes that are being read from the camera until the Close method is called or until the timeout is reached.
Example of capturing a stream of H.264 video
ic void TestCaptureVideo()
// Setup our working variables
var videoByteCount = 0;
var videoEventCount = 0;
var startTime = DateTime.UtcNow;
// Configure video settings
var videoSettings = new CameraVideoSettings()
{
CaptureTimeoutMilliseconds = 0,
CaptureDisplayPreview = false,
ImageFlipVertically = true,
CaptureExposure = CameraExposureMode.Night,
CaptureWidth = 1920,
CaptureHeight = 1080
};
try
{
// Start the video recording
Pi.Camera.OpenVideoStream(videoSettings,
onDataCallback: (data) => { videoByteCount += data.Length; videoEventCount++; },
onExitCallback: null);
// Wait for user interaction
startTime = DateTime.UtcNow;
Console.WriteLine("Press any key to stop reading the video stream . . .");
Console.ReadKey(true);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType()}: {ex.Message}");
}
finally
{
// Always close the video stream to ensure raspivid quits
Pi.Camera.CloseVideoStream();
// Output the stats
var megaBytesReceived = (videoByteCount / (1024f * 1024f)).ToString("0.000");
var recordedSeconds = DateTime.UtcNow.Subtract(startTime).TotalSeconds.ToString("0.000");
Console.WriteLine($"Capture Stopped. Received {megaBytesReceived} Mbytes in {videoEventCount} callbacks in {recordedSeconds} seconds");
}
se note ```Pi.Info``` depends on ```Wiring Pi```, and the ```/proc/cpuinfo``` and ```/proc/meminfo``` files.
sing the GPIO Pins
reference for the B plus (B+) - Header P1
M | wPi | Name | Mode | V | L | R | V | Mode | Name | wPi | BCM |
- | --- | ------- | ---- | --- | ------ | ------ | --- | ---- | ------- | --- | --- |
| | 3.3v | | | **01** | **02** | | | 5v | | |
2 | 8 | SDA.1 | ALT0 | 1 | **03** | **04** | | | 5V | | |
3 | 9 | SCL.1 | ALT0 | 1 | **05** | **06** | | | 0v | | |
4 | 7 | GPIO. 7 | IN | 1 | **07** | **08** | 1 | ALT0 | TxD | 15 | 14 |
| | 0v | | | **09** | **10** | 1 | ALT0 | RxD | 16 | 15 |
7 | 0 | GPIO. 0 | IN | 0 | **11** | **12** | 0 | IN | GPIO. 1 | 1 | 18 |
7 | 2 | GPIO. 2 | IN | 0 | **13** | **14** | | | 0v | | |
2 | 3 | GPIO. 3 | IN | 0 | **15** | **16** | 0 | IN | GPIO. 4 | 4 | 23 |
| | 3.3v | | | **17** | **18** | 0 | IN | GPIO. 5 | 5 | 24 |
0 | 12 | MOSI | IN | 0 | **19** | **20** | | | 0v | | |
9 | 13 | MISO | IN | 0 | **21** | **22** | 0 | IN | GPIO. 6 | 6 | 25 |
1 | 14 | SCLK | IN | 0 | **23** | **24** | 1 | IN | CE0 | 10 | 8 |
| | 0v | | | **25** | **26** | 1 | IN | CE1 | 11 | 7 |
0 | 30 | SDA.0 | IN | 1 | **27** | **28** | 1 | IN | SCL.0 | 31 | 1 |
5 | 21 | GPIO.21 | IN | 1 | **29** | **30** | | | 0v | | |
6 | 22 | GPIO.22 | IN | 1 | **31** | **32** | 0 | IN | GPIO.26 | 26 | 12 |
3 | 23 | GPIO.23 | IN | 0 | **33** | **34** | | | 0v | | |
9 | 24 | GPIO.24 | IN | 0 | **35** | **36** | 0 | IN | GPIO.27 | 27 | 16 |
6 | 25 | GPIO.25 | IN | 0 | **37** | **38** | 0 | IN | GPIO.28 | 28 | 20 |
| | 0v | | | **39** | **40** | 0 | IN | GPIO.29 | 29 | 21 |
wait for a second, Where are Wiring Pi (wPi) pins 17 through 20? The above diagram shows the pins of GPIO Header P1. There is an additional GPIO header on the Pi called P5. [More info available here](http://www.raspberrypi-spy.co.uk/2012/09/raspberry-pi-p5-header/)
rder to access the pins, use ```Pi.Gpio```. The pins can have multiple behaviors and fortunately ```Pi.Gpio``` can be iterated, addressed by index, addressed by Wiring Pi pin number and provides the pins as publicly accessible properties.
is an example of addressing the pins in all the various ways:
public static void TestLedBlinking() {
// Get a reference to the pin you need to use.
// All 3 methods below are exactly equivalent
var blinkingPin = Pi.Gpio[0];
blinkingPin = Pi.Gpio[WiringPiPin.Pin00];
blinkingPin = Pi.Gpio.Pin00;
// Configure the pin as an output
blinkingPin.PinMode = GpioPinDriveMode.Output;
// perform writes to the pin by toggling the isOn variable
var isOn = false;
for (var i = 0; i < 20; i++)
{
isOn = !isOn;
blinkingPin.Write(isOn);
System.Threading.Thread.Sleep(500);
}
}
Pin Information
pins have handy properties and methods that you can use to drive them. For example, you can examine the ```Capabilities``` property to find out which features are available on the pin. You can also use the ```PinMode``` property to get or set the operating mode of the pin. Please note that the value of the ```PinMode``` property is by default set to _Input_ and it will return the last mode you set the property to.
Digital Read and Write
s very easy to read and write values to the pins. In general, it is a 2-step process.
t the pin mode
ad or write the bit value
ing the value of a pin example:
Pi.Gpio.Pin02.PinMode = GpioPinDriveMode.Input; // The below lines are reoughly equivalent var isOn = Pi.Gpio.Pin02.Read(); // Reads as a boolean var pinValue = Pi.Gpio.Pin02.ReadValue(); // Reads as a GpioPinValue
ing to a pin example
Pi.Gpio.Pin02.PinMode = GpioPinDriveMode.Output; // The below lines are reoughly equivalent Pi.Gpio.Pin02.Write(true); // Writes a boolean Pi.Gpio.Pin02.Write(GpioPinValue.High); // Writes a pin value
Analog (Level) Read and Write
Hardware PWM
Software PWM
Tone Generation
can emit tones by using SoftToneFrequency. Example:
// Get a reference to the pin var passiveBuzzer = Pi.Gpio[WiringPiPin.Pin01]; // Set the frequency to Alto Do (523Hz) passiveBuzzer.SoftToneFrequency = 523 // Wait 1 second System.Threading.Thread.Sleep(1000); // And stop passiveBuzzer.SoftToneFrequency = 0;
Interrupts and Callbacks
ster an Interrupt Callback example:
using System; using Unosquare.RaspberryIO; using Unosquare.RaspberryIO.Gpio;
class Program { // Define the implementation of the delegate; static void ISRCallback() {
Console.WriteLine("Pin Activated...");
}
static void Main(string[] args) {
Console.WriteLine("Gpio Interrupts");
var pin = Pi.Gpio.Pin00;
pin.PinMode = GpioPinDriveMode.Input;
pin.RegisterInterruptCallback(EdgeDetection.FallingEdge, ISRCallback);
Console.ReadKey();
} }
sing the SPI Bus
ally liked the following description from [Neil's Log Book](http://nrqm.ca/nrf24l01/serial-peripheral-interface/): _The SPI (Serial Peripheral Interface) protocol behaves like a ring buffer so that whenever the master sends a byte to the slave, the slave sends a byte back to the master. The slave can use this behavior to return a status byte, a response to a previous byte, or null data (the master may choose to read the returned byte or ignore it). The bus operates on a 4-wire interface._
In order to use an SPI channel you MUST always set the `Channel0Frequency
or ``
Channel1Frequency` (depending on the channel you want to use) before calling the
SendReceive``
method. If the property is not set beforehand the SPI channel will fail initialization. See an example below:
Example of using the SPI Bus
pi.Channel0Frequency = SpiChannel.MinFrequency;
request = System.Text.Encoding.ASCII.GetBytes("HELLO!");
response = Pi.Spi.Channel0.SendReceive(request);
The Inter IC Bus (I2C) is a cousin of the SPI bus but it is somewhat more complex and it does not work as a ring buffer like the SPI bus. It also connects all of its slave devices in series and depends on 2 lines only. There is a nice tutorial on setting up and using the I2C bus at Robot Electronics. From their site: The physical bus is just two wires, called SCL and SDA. SCL is the clock line. It is used to synchronize all data transfers over the I2C bus. SDA is the data line. The SCL & SDA lines are connected to all devices on the I2C bus. There needs to be a third wire which is just the ground or 0 volts. There may also be a 5volt wire is power is being distributed to the devices. Both SCL and SDA lines are “open drain” drivers. What this means is that the chip can drive its output low, but it cannot drive it high. For the line to be able to go high you must provide pull-up resistors to the 5v supply. There should be a resistor from the SCL line to the 5v line and another from the SDA line to the 5v line. You only need one set of pull-up resistors for the whole I2C bus, not for each device.
rder to detect I2C devices, you could use the ```i2cdetect``` system command. Just remember that on a Rev 1 Raspberry Pi it's device 0, and on a Rev. 2 it's device 1. e.g.
i2cdetect -y 0 # Rev 1 i2cdetect -y 1 # Rev 2
ple of using the I2C Bus
// Register a device on the bus var myDevice = Pi.I2C.AddDevice(0x20);
// Simple Write and Read (there are algo register read and write methods) myDevice.Write(0x44); var response = myDevice.Read();
// List registered devices on the I2C Bus foreach (var device in Pi.I2C.Devices) {
Console.WriteLine($"Registered I2C Device: {device.DeviceId}");
}
iming and Threading
erial Ports (UART)
e is the serial port API? Well, it is something we will most likely add in the future. For now, you can simply use the built-in ```SerialPort``` class the .NET framework provides.
imilar Projects
href="https://github.com/raspberry-sharp/raspberry-sharp-io">Raspberry# IO</a>
href="https://github.com/danriches/WiringPi.Net">WiringPi.Net</a>
href="https://github.com/andycb/PiSharp">PiSharp</a>