未验证 提交 b4f93764 编写于 作者: R Rich Lander 提交者: GitHub

Merge pull request #9 from dotnet/devices

Fill out devices section
......@@ -7,8 +7,14 @@ See the following resources to get started.
* [.NET Core documentation](https://docs.microsoft.com/dotnet/)
* [Install .NET Core on Raspberry Pi](https://github.com/dotnet/core/blob/master/samples/RaspberryPiInstructions.md)
* [.NET Core ARM64 Status](https://github.com/dotnet/announcements/issues/82)
* [.NET Core Docker Samples](https://github.com/dotnet/dotnet-docker/tree/master/samples)
## Raspberry Pi
* [Enable SPI on Raspberry Pi](https://www.raspberrypi-spy.co.uk/2014/08/enabling-the-spi-interface-on-the-raspberry-pi/)
* [Enable headless Raspberry Pi](https://hackernoon.com/raspberry-pi-headless-install-462ccabd75d0)
\ No newline at end of file
* [Enable I2C on Raspberry Pi](https://www.raspberrypi-spy.co.uk/2014/11/enabling-the-i2c-interface-on-the-raspberry-pi/)
* [Enable headless Raspberry Pi](https://hackernoon.com/raspberry-pi-headless-install-462ccabd75d0)
## GPIO
* [Docker Access to Raspberry Pi GPIO Pins](https://stackoverflow.com/questions/30059784/docker-access-to-raspberry-pi-gpio-pins)
......@@ -2,11 +2,31 @@
.NET Core can be used to build applications for [IoT](https://en.wikipedia.org/wiki/Internet_of_things) devices and scenarios. IoT applications typically interact with sensors, displays and input devices that require the use of [GPIO pins](https://en.wikipedia.org/wiki/General-purpose_input/output), serial ports or similar hardware.
This repository contains the [System.Devices.Gpio](https://dotnet.myget.org/feed/dotnet-corefxlab/package/nuget/System.Devices.Gpio) library and implementations for various boards like [Raspberry Pi](https://www.raspberrypi.org/) and [Hummingboard](https://www.solid-run.com/nxp-family/hummingboard/).
This repository contains the [System.Device.Gpio](https://dotnet.myget.org/feed/dotnet-corefxlab/package/nuget/System.Devices.Gpio) library and implementations for various boards like [Raspberry Pi](https://www.raspberrypi.org/) and [Hummingboard](https://www.solid-run.com/nxp-family/hummingboard/).
It also contains a growing set of community-maintained bindings for IoT components, like the [Mcp3008](https://www.adafruit.com/product/856) ([bindings](src/Mcp3008/Mcp3008.cs)), for example.
It also contains a growing set of community-maintained [device bindings](src/devices/README.md) for IoT components.
Note: System.Device.Gpio is in early preview. It is not yet supported and will continue to change.
Note: System.Device.Gpio is in early preview. It is not yet supported and will continue to change. It is currently published to myget (requires use of [nuget.config](samples/nuget.config)).
## Roadmap
We have the following deliverables on our intermediate-term roadmap (not in order of completion):
* [x] Support protocols: GPIO, SPI, and I2C.
* [ ] Support protocols: PWM.
* [ ] Support protocols: serial port.
* [ ] Support protocols: I2S.
* [x] Support Linux.
* [ ] Support Windows 10 IoT Core.
* [ ] Stabilize System.Device.* API
* [ ] Publish System.Device.* API to NuGet.org
* [ ] Provide dockerfiles for all samples
* [ ] Publish Docker images for a subset of samples
* [ ] Support x64
* [x] Support ARM32
* [ ] Support ARM64
* [ ] Provide device bindings for LED matrices
* [ ] Provide device bindings for LCD panels
## Install .NET Core
......@@ -19,7 +39,9 @@ Please contribute. We are primarily interested in the following:
* Improving quality and capability of the drivers for supported boards.
* Implementations for additional boards
* .NET bindings for a wide variety of sensors, chips, displays and other components.
* [.NET device bindings](src/devices) for a wide variety of sensors, chips, displays and other components.
* Links to blog posts or tweets that showcase .NET Core being used for great IoT scenarios (file an issue).
* Request a device binding or protocol that you need for your project (file an issue).
## License
......
......@@ -12,13 +12,13 @@ The following samples demonstrate various scenarios:
## Libraries
These samples use the [System.Devices.Gpio](https://dotnet.myget.org/feed/dotnet-corefxlab/package/nuget/System.Devices.Gpio) library. It will be supported on Linux and Windows IoT Core. At present, the library works on Linux. The library is currently in early preview, based on [source in dotnet/corefxlab](https://github.com/dotnet/corefxlab/tree/master/src/System.Devices.Gpio).
These samples use the [System.Device.Gpio](https://dotnet.myget.org/feed/dotnet-corefxlab/package/nuget/System.Devices.Gpio) library. It will be supported on Linux and Windows IoT Core. At present, the library works on Linux. The library is currently in early preview, based on [source in dotnet/corefxlab](https://github.com/dotnet/corefxlab/tree/master/src/System.Devices.Gpio).
There are many libraries that are important beyond GPIO, I2C and related fundamental protocols. We are working on a plan where the .NET Team and the community can work together to build up a shared repository of implementations.
## Breadboard layouts
The samples expect the device pins to be connected in particular way to function, typically on a breadboard. Each example includes a [Fritzing](http://fritzing.org/home/) diagram of the required breadboard layout, such as the following one (taken from the [More blinking lights](led-more-blinking-lights/README.md) sample).
The samples expect the device pins to be connected in particular way to function, typically on a breadboard. Each example includes a [Fritzing](http://fritzing.org/home/) diagram of the required breadboard layout, such as the following one (taken from the [More blinking lights](led-more-blinking-lights/README.md) sample).
![Rasperry Pi Breadboard diagram](led-more-blinking-lights/rpi-more-blinking-lights_bb.png)
......
# directories
**/bin/
**/obj/
**/out/
# files
Dockerfile*
**/*.trx
**/*.md
**/*.ps1
**/*.cmd
**/*.sh
\ No newline at end of file
FROM microsoft/dotnet:2.1-sdk-stretch-arm32v7 AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.config .
COPY *.csproj .
RUN dotnet restore
# copy and build app
COPY . .
RUN dotnet publish -c release -o out
FROM microsoft/dotnet:2.1-runtime-stretch-slim-arm32v7 AS runtime
WORKDIR /app
COPY --from=build /app/out ./
ENTRYPOINT ["dotnet", "led-blink.dll"]
......@@ -2,7 +2,29 @@
This [sample](Program.cs) demonstrates blinking an LED at a given interval. It repeatedly toggles a GPIO pin on and off, which powers the LED. This sample also demonstrates the most basic usage of the [.NET Core GPIO library](https://dotnet.myget.org/feed/dotnet-corefxlab/package/nuget/System.Devices.Gpio).
### Code
## Run the sample
This sample can be built and run with .NET Core 2.1. Use the following commands from the root of the repo:
```console
cd samples
cd led-blink
dotnet build -c release -o out
sudo dotnet out/led-blink.dll
```
## Run the sample with Docker
This sample can be built and run with Docker. Use the following commands from the root of the repo:
```console
cd samples
cd led-blink
docker build -t led-blink .
docker run --rm -it -v /sys:/sys led-blink
```
## Code
The following code provides write access to a GPIO pin (GPIO 17 in this case):
......@@ -25,7 +47,7 @@ while (true)
}
```
### Breadboard layout
## Breadboard layout
The following [fritzing diagram](rpi-led.fzz) demonstrates how you should wire your device in order to run the [program](Program.cs). It uses the GND and GPIO 17 pins on the Raspberry Pi.
......
......@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-180912-2" />
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-181011-1" />
</ItemGroup>
</Project>
using System;
using System.Devices.Gpio;
using System.Devices.Spi;
public class Mcp3008
{
private SpiDevice _spiDevice;
private GpioPin _CLK;
private GpioPin _MISO;
private GpioPin _MOSI;
private GpioPin _CS;
public Mcp3008(SpiDevice spiDevice)
{
_spiDevice = spiDevice;
}
public Mcp3008(GpioController controller, int CLK, int MISO, int MOSI, int CS)
{
_CLK = controller.OpenPin(CLK, PinMode.Output);
_MISO = controller.OpenPin(MISO, PinMode.Input);
_MOSI = controller.OpenPin(MOSI, PinMode.Output);
_CS = controller.OpenPin(CS, PinMode.Output);
}
public int Read(int adc_channel)
{
if (adc_channel < 0 && adc_channel > 7)
{
throw new ArgumentException("ADC channel must be within 0-7 range.");
}
if (_spiDevice != null)
{
return ReadSpi(adc_channel);
}
else
{
return ReadGpio(adc_channel);
}
}
private int ReadGpio(int adc_channel)
{
//port of https://gist.github.com/ladyada/3151375
while (true)
{
var commandout = 0;
var trim_pot = 0;
_CS.Write(PinValue.High);
_CLK.Write(PinValue.Low);
_CS.Write(PinValue.Low);
commandout |= 0x18;
commandout <<= 3;
for (var i = 0; i < 5; i++)
{
if ((commandout & 0x80) > 0)
{
_MOSI.Write(PinValue.High);
}
else
{
_MOSI.Write(PinValue.Low);
}
commandout <<= 1;
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
}
for (var i = 0; i < 12; i++)
{
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
trim_pot <<= 1;
if (_MISO.Read() == PinValue.High)
{
trim_pot |= 0x1;
}
}
_CS.Write(PinValue.High);
trim_pot >>= 1;
//var pot_adjust = Math.Abs(trim_pot - last_read);
return trim_pot;
}
}
private int ReadSpi(int adc_channel)
{
// ported code from:
// https://github.com/adafruit/Adafruit_Python_MCP3008/blob/master/Adafruit_MCP3008/MCP3008.py
int command = 0b11 << 6; //Start bit, single channel read
command |= (adc_channel & 0x07) << 3; // Channel number (in 3 bits)
var input = new Byte[] { (Byte)command, 0, 0 };
var output = new Byte[3];
_spiDevice.TransferFullDuplex(input, output);
var result = (output[0] & 0x01) << 9;
result |= (output[1] & 0xFF) << 1;
result |= (output[2] & 0x80) >> 7;
result = result & 0x3FF;
return result;
}
}
\ No newline at end of file
......@@ -15,6 +15,8 @@ namespace led_more_blinking_lights
var pinTwo = 21;
var pinThree = 20;
var pinFour = 26;
var buttonSleep = 50;
var volumeSleep = 50;
// volume support
var initialSleep = 100;
......@@ -93,7 +95,7 @@ namespace led_more_blinking_lights
if (update)
{
sleep = value;
Thread.Sleep(50);
Thread.Sleep(volumeSleep);
}
}
}
......@@ -104,7 +106,7 @@ namespace led_more_blinking_lights
ledOne.Write(PinValue.High);
ledTwo.Write(PinValue.High);
ledThree.Write(PinValue.High);
Thread.Sleep(50);
Thread.Sleep(buttonSleep);
}
Console.WriteLine($"Sleep: {sleep}");
......
using System;
using System.Devices.Spi;
using Iot.Device;
public class Volume
{
......
......@@ -7,7 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-180912-2" />
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-181011-1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\devices\Mcp3008\Mcp3008.csproj" />
</ItemGroup>
</Project>
using System;
using System.Devices.Gpio;
using System.Devices.Spi;
public class Mcp3008
{
private SpiDevice _spiDevice;
private GpioPin _CLK;
private GpioPin _MISO;
private GpioPin _MOSI;
private GpioPin _CS;
public Mcp3008(SpiDevice spiDevice)
{
_spiDevice = spiDevice;
}
public Mcp3008(GpioController controller, int CLK, int MISO, int MOSI, int CS)
{
_CLK = controller.OpenPin(CLK, PinMode.Output);
_MISO = controller.OpenPin(MISO, PinMode.Input);
_MOSI = controller.OpenPin(MOSI, PinMode.Output);
_CS = controller.OpenPin(CS, PinMode.Output);
}
public int Read(int adc_channel)
{
if (adc_channel < 0 && adc_channel > 7)
{
throw new ArgumentException("ADC channel must be within 0-7 range.");
}
if (_spiDevice != null)
{
return ReadSpi(adc_channel);
}
else
{
return ReadGpio(adc_channel);
}
}
private int ReadGpio(int adc_channel)
{
//port of https://gist.github.com/ladyada/3151375
while (true)
{
var commandout = 0;
var trim_pot = 0;
_CS.Write(PinValue.High);
_CLK.Write(PinValue.Low);
_CS.Write(PinValue.Low);
commandout |= 0x18;
commandout <<= 3;
for (var i = 0; i < 5; i++)
{
if ((commandout & 0x80) > 0)
{
_MOSI.Write(PinValue.High);
}
else
{
_MOSI.Write(PinValue.Low);
}
commandout <<= 1;
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
}
for (var i = 0; i < 12; i++)
{
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
trim_pot <<= 1;
if (_MISO.Read() == PinValue.High)
{
trim_pot |= 0x1;
}
}
_CS.Write(PinValue.High);
trim_pot >>= 1;
//var pot_adjust = Math.Abs(trim_pot - last_read);
return trim_pot;
}
}
private int ReadSpi(int adc_channel)
{
// ported code from:
// https://github.com/adafruit/Adafruit_Python_MCP3008/blob/master/Adafruit_MCP3008/MCP3008.py
int command = 0b11 << 6; //Start bit, single channel read
command |= (adc_channel & 0x07) << 3; // Channel number (in 3 bits)
var input = new Byte[] { (Byte)command, 0, 0 };
var output = new Byte[3];
_spiDevice.TransferFullDuplex(input, output);
var result = (output[0] & 0x01) << 9;
result |= (output[1] & 0xFF) << 1;
result |= (output[2] & 0x80) >> 7;
result = result & 0x3FF;
return result;
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
using System.Devices.Gpio;
using System.Devices.Spi;
using System.Threading;
using Iot.Device;
namespace trimpot
{
......
......@@ -3,11 +3,14 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>led_pwm</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-180912-2" />
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-181011-1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\devices\Mcp3008\Mcp3008.csproj" />
</ItemGroup>
</Project>
using System;
using System.Devices.Gpio;
using System.Devices.Spi;
public class Mcp3008
{
private SpiDevice _spiDevice;
private GpioPin _CLK;
private GpioPin _MISO;
private GpioPin _MOSI;
private GpioPin _CS;
public Mcp3008(SpiDevice spiDevice)
{
_spiDevice = spiDevice;
}
public Mcp3008(GpioController controller, int CLK, int MISO, int MOSI, int CS)
{
_CLK = controller.OpenPin(CLK, PinMode.Output);
_MISO = controller.OpenPin(MISO, PinMode.Input);
_MOSI = controller.OpenPin(MOSI, PinMode.Output);
_CS = controller.OpenPin(CS, PinMode.Output);
}
public int Read(int adc_channel)
{
if (adc_channel < 0 && adc_channel > 7)
{
throw new ArgumentException("ADC channel must be within 0-7 range.");
}
if (_spiDevice != null)
{
return ReadSpi(adc_channel);
}
else
{
return ReadGpio(adc_channel);
}
}
private int ReadGpio(int adc_channel)
{
//port of https://gist.github.com/ladyada/3151375
while (true)
{
var commandout = 0;
var trim_pot = 0;
_CS.Write(PinValue.High);
_CLK.Write(PinValue.Low);
_CS.Write(PinValue.Low);
commandout |= 0x18;
commandout <<= 3;
for (var i = 0; i < 5; i++)
{
if ((commandout & 0x80) > 0)
{
_MOSI.Write(PinValue.High);
}
else
{
_MOSI.Write(PinValue.Low);
}
commandout <<= 1;
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
}
for (var i = 0; i < 12; i++)
{
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
trim_pot <<= 1;
if (_MISO.Read() == PinValue.High)
{
trim_pot |= 0x1;
}
}
_CS.Write(PinValue.High);
trim_pot >>= 1;
//var pot_adjust = Math.Abs(trim_pot - last_read);
return trim_pot;
}
}
private int ReadSpi(int adc_channel)
{
// ported code from:
// https://github.com/adafruit/Adafruit_Python_MCP3008/blob/master/Adafruit_MCP3008/MCP3008.py
int command = 0b11 << 6; //Start bit, single channel read
command |= (adc_channel & 0x07) << 3; // Channel number (in 3 bits)
var input = new Byte[] { (Byte)command, 0, 0 };
var output = new Byte[3];
_spiDevice.TransferFullDuplex(input, output);
var result = (output[0] & 0x01) << 9;
result |= (output[1] & 0xFF) << 1;
result |= (output[2] & 0x80) >> 7;
result = result & 0x3FF;
return result;
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<NoWarn>$(NoWarn);CS8321</NoWarn>
<DeterministicSourcePaths>false</DeterministicSourcePaths>
<IsPackable>false</IsPackable>
</PropertyGroup>
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Target Name="Test" />
</Project>
using System;
using System.Devices.Gpio;
using System.Devices.Spi;
namespace Iot.Device
{
public class Mcp3008
{
private SpiDevice _spiDevice;
private GpioPin _CLK;
private GpioPin _MISO;
private GpioPin _MOSI;
private GpioPin _CS;
public Mcp3008(SpiDevice spiDevice)
{
_spiDevice = spiDevice;
}
public Mcp3008(GpioController controller, int CLK, int MISO, int MOSI, int CS)
{
_CLK = controller.OpenPin(CLK, PinMode.Output);
_MISO = controller.OpenPin(MISO, PinMode.Input);
_MOSI = controller.OpenPin(MOSI, PinMode.Output);
_CS = controller.OpenPin(CS, PinMode.Output);
}
public int Read(int adc_channel)
{
if (adc_channel < 0 && adc_channel > 7)
{
throw new ArgumentException("ADC channel must be within 0-7 range.");
}
if (_spiDevice != null)
{
return ReadSpi(adc_channel);
}
else
{
return ReadGpio(adc_channel);
}
}
// port of https://gist.github.com/ladyada/3151375
private int ReadGpio(int adc_channel)
{
while (true)
{
var commandout = 0;
var trim_pot = 0;
_CS.Write(PinValue.High);
_CLK.Write(PinValue.Low);
_CS.Write(PinValue.Low);
commandout |= 0x18;
commandout <<= 3;
for (var i = 0; i < 5; i++)
{
if ((commandout & 0x80) > 0)
{
_MOSI.Write(PinValue.High);
}
else
{
_MOSI.Write(PinValue.Low);
}
commandout <<= 1;
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
}
for (var i = 0; i < 12; i++)
{
_CLK.Write(PinValue.High);
_CLK.Write(PinValue.Low);
trim_pot <<= 1;
if (_MISO.Read() == PinValue.High)
{
trim_pot |= 0x1;
}
}
_CS.Write(PinValue.High);
trim_pot >>= 1;
return trim_pot;
}
}
// ported code from:
// https://github.com/adafruit/Adafruit_Python_MCP3008/blob/master/Adafruit_MCP3008/MCP3008.py
private int ReadSpi(int adc_channel)
{
int command = 0b11 << 6; //Start bit, single channel read
command |= (adc_channel & 0x07) << 3; // Channel number (in 3 bits)
var input = new Byte[] { (Byte)command, 0, 0 };
var output = new Byte[3];
_spiDevice.TransferFullDuplex(input, output);
var result = (output[0] & 0x01) << 9;
result |= (output[1] & 0xFF) << 1;
result |= (output[2] & 0x80) >> 7;
result = result & 0x3FF;
return result;
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Devices.Gpio" Version="0.1.0-preview2-181011-1" />
</ItemGroup>
</Project>
# Using MCP3008 (10-bit Analog to Digital Converter)
Some devices like the Rasperry Pi cannot read analog values directly so rely on [analog to digital converters](https://en.wikipedia.org/wiki/Analog-to-digital_converter), like the [MCP3008 ADC](https://www.adafruit.com/product/856). The MCP3008 supports the SPI interface. The 10-bit chip can be accessed as an [SPI device](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface) or manually via raw GPIO pins.
You can use [Mcp3008.cs](Mcp3008.cs) in your project to access analog devices. [Reading Analog Input from a Potentiometer](../../../samples/trimpot/README.md) demonstrates a concrete example using this class.
The following fritzing diagram illustrates one way to wire up the Mcp3008, with a Raspberry Pi and a potentiometer.
![Raspberry Pi Breadboard diagram](../../../samples/trimpot/rpi-trimpot_spi.png)
\ No newline at end of file
# Device Bindings
This directory is intended for device bindings, for sensors, displays, human interface devices and anything else that requires software to control. We want to establish a rich set of quality .NET bindings to make it straightforward to use .NET to connect devices together to produce weird and wonderful IoT applications.
Our vision: the majority of .NET bindings are written completely in .NET languages to enable portability, use of a single tool chain and complete debugability from application to binding to driver.
## Binding Index
* [Mcp3008](Mcp3008)
## Binding Distribution
We are currently encouraging source distribution of device bindings. The [trimpot sample](../../samples/trimpot/trimpot.csproj) references the [Mcp3008](Mcp3008/Mcp3008.csproj) within this repo. You can clone this repo and use the sample project reference model to a device binding or copy bindings directly into your project.
We may publish NuGet packages of device bindings at a later date.
## Contributing a binding
Anyone can contribute a binding. Please do! Bindings should following the model that is used for the [Mcp3008](Mcp3008) implementation.
Bindings must:
* include a .NET Core project file
* include a descriptive README, with a fritzing diagram
* include a buildable sample (either beside the binding or a [sample](../../samples))
* use the System.Device API
We are currently not accepting samples that rely on native libraries for hardware interaction. This is for two reasons: we want feedback on the System.Device API and we want to encourage the use of 100% portable .NET solutions. If a native library is used to enable precise timing, please file an issue so that we can discuss your proposed contribution further.
We will only accept samples that use the MIT or compatible licenses (BSD, Apache 2, ...). We will not accept samples that use GPL code or were based on an existing GPL implementation. It is critical that these samples can be used for commercial applications without any concern for licensing.
......@@ -5,4 +5,4 @@
<add key="corefxlab" value="https://dotnet.myget.org/F/dotnet-corefxlab/api/v3/index.json" />
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
</configuration>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册