Dotnet Iot
Dotnet Iot
f QUICKSTART
Learn
e OVERVIEW
` DEPLOY
p CONCEPT
c HOW-TO GUIDE
i REFERENCE
API Reference
Build devices
d TRAINING
Blink an LED
a DOWNLOAD
System.Device.Gpio on NuGet
Iot.Device.Bindings on NuGet
Video learning
q VIDEO
Resources
b GET STARTED
p CONCEPT
Raspberry Pi documentation
c HOW-TO GUIDE
.NET runs on various platforms and architectures. Common Internet of things (IoT)
boards, such as Raspberry Pi and Hummingboard, are supported. IoT apps typically
interact with specialized hardware, such as sensors, analog-to-digital converters, and
LCD devices. The .NET IoT Libraries enable these scenarios.
Libraries
The .NET IoT Libraries are composed of two NuGet packages:
System.Device.Gpio
Iot.Device.Bindings
System.Device.Gpio
System.Device.Gpio supports various protocols for interacting with low-level hardware
Iot.Device.Bindings
The Iot.Device.Bindings package:
Tip
platforms are Raspberry Pi (2 and greater) and Hummingboard. Other platforms known
to be compatible are BeagleBoard and ODROID.
.NET is not supported on devices prior to ARMv7, including Raspberry Pi Zero and
Raspberry Pi devices prior to Raspberry Pi 2.
Resources
.NET IoT Libraries on GitHub
Quickstart - Use .NET to drive a
Raspberry Pi Sense HAT
Article • 04/08/2023
The Raspberry Pi Sense HAT (Hardware Attached on Top) is an add-on board for
Raspberry Pi. The Sense HAT is equipped with an 8×8 RGB LED matrix, a five-button
joystick, and includes the following sensors:
Gyroscope
Accelerometer
Magnetometer
Temperature
Barometric pressure
Humidity
This quickstart uses .NET to retrieve sensor values from the Sense HAT, respond to
joystick input, and drive the LED matrix.
Prerequisites
Raspberry Pi that supports ARM v7 instructions with Raspberry Pi OS . Raspberry
Pi OS Lite (64-bit) is recommended.
Sense HAT
SSH
I2C
Bash
Bash
. <(wget -q -O - https://aka.ms/dotnet-iot-sensehat-quickstart)
Observe the console output as sensor data is displayed. The LED matrix displays a yellow
pixel on a field of blue. Holding the joystick in any direction moves the yellow pixel in
that direction. Clicking the center joystick button causes the background to switch from
blue to red.
Next steps
Learn to use General Purpose Input/Output to blink an LED
Blink an LED
Article • 04/08/2023
General-purpose I/O (GPIO) pins can be controlled individually. This is useful for
controlling LEDs, relays, and other stateful devices. In this topic, you will use .NET and
your Raspberry Pi's GPIO pins to power an LED and blink it repeatedly.
Prerequisites
ARM-based (ARMv7 or greater) single-board computer (SBC)
5 mm LED
330 Ω resistor
Breadboard
Jumper wires
Raspberry Pi GPIO breakout board (optional/recommended)
.NET SDK 7 or later
7 Note
This tutorial is written assuming the target device is Raspberry Pi. However, this
tutorial can be used for any Linux-based SBC that supports .NET, such as Orange Pi,
ODROID, and more.
Ensure SSH is enabled on your device. For Raspberry Pi, refer to Setting up an SSH Server
in the Raspberry Pi documentation .
Tip
A GPIO breakout board in conjunction with a breadboard is recommended to
streamline connections to the GPIO header.
1. Create a new .NET Console App using either the .NET CLI or Visual Studio. Name it
BlinkTutorial.
.NET CLI
2. Add the System.Device.Gpio package to the project. Use either .NET CLI from the
project directory or Visual Studio.
.NET CLI
C#
using System;
using System.Device.Gpio;
using System.Threading;
4. Build the app. If using the .NET CLI, run dotnet build . To build in Visual Studio,
press Ctrl + Shift + B .
5. Deploy the app to the SBC as a self-contained app. For instructions, see Deploy
.NET apps to Raspberry Pi. Make sure to give the executable execute permission
using chmod +x .
6. Run the app on the Raspberry Pi by switching to the deployment directory and
running the executable.
Bash
./BlinkTutorial
Next steps
Learn how to read binary input using GPIO
Use GPIO for binary input
Article • 04/08/2023
General-purpose I/O (GPIO) pins can be configured to receive electrical signals as input.
At its most basic level, this is useful for scenarios that detect the opening/closing of a
circuit. Such circuits might include push buttons, toggle switches, reed switches,
pressure switches, and other devices that represent binary (on/off) values by completing
a circuit.
In this tutorial, you'll use .NET and your Raspberry Pi's GPIO pins to detect the opening
and closing of a circuit.
Prerequisites
ARM-based (ARMv7 or greater) single-board computer (SBC)
Jumper wires
Breadboard (optional)
Raspberry Pi GPIO breakout board (optional)
.NET SDK 7 or later
7 Note
This tutorial is written assuming the target device is Raspberry Pi. However, this
tutorial can be used for any Linux-based SBC that supports .NET, such as Orange Pi,
ODROID, and more.
Ensure SSH is enabled on your device. For Raspberry Pi, refer to Setting up an SSH Server
in the Raspberry Pi documentation .
The image above depicts a direct connection between a ground pin and pin 21.
Tip
The diagram depicts a breadboard and GPIO breakout for illustrative purposes, but
feel free to just connect a ground pin and pin 21 with a jumper wire on the
Raspberry Pi.
1. Create a new .NET Console App using either the .NET CLI or Visual Studio. Name it
InputTutorial.
.NET CLI
.NET CLI
C#
using System.Device.Gpio;
using System.Threading.Tasks;
Console.WriteLine(
$"Initial status ({DateTime.Now}): {(controller.Read(Pin) ==
PinValue.High ? Alert : Ready)}");
controller.RegisterCallbackForPinValueChangedEvent(
Pin,
PinEventTypes.Falling | PinEventTypes.Rising,
OnPinEvent);
await Task.Delay(Timeout.Infinite);
should detect which hardware platform it's running on and use the logical
pin numbering scheme.
GPIO pin 21 is opened with PinMode.InputPullUp .
This opens the pin with a PullUp resistor engaged. In this mode, when the
pin is connected to ground, it will return PinValue.Low . When the pin is
disconnected from ground and the circuit is open, the pin returns
PinValue.High .
The initial status is written to a console using a ternary expression. The pin's
current state is read with Read() . If it's PinValue.High , it writes the Alert
string to the console. Otherwise, it writes the Ready string.
RegisterCallbackForPinValueChangedEvent() registers a callback function for
both the PinEventTypes.Rising and PinEventTypes.Falling events on the pin.
These events correspond to pin states of PinValue.High and PinValue.Low ,
respectively.
The callback function points to a method called OnPinEvent() . OnPinEvent()
uses another ternary expression that also writes the corresponding Alert or
Ready strings.
The main thread sleeps indefinitely while waiting for pin events.
4. Build the app. If using the .NET CLI, run dotnet build . To build in Visual Studio,
press Ctrl + Shift + B .
5. Deploy the app to the SBC as a self-contained app. For instructions, see Deploy
.NET apps to Raspberry Pi. Make sure to give the executable execute permission
using chmod +x .
6. Run the app on the Raspberry Pi by switching to the deployment directory and
running the executable.
Bash
./InputTutorial
Console
7. Disconnect pin 21 from ground. The console displays text similar to the following:
Console
Console
Congratulations! You've used GPIO to detect input using the System.Device.Gpio NuGet
package! There are many uses for this type of input. This example can be used with any
scenario where a switch connects or breaks a circuit. Here's an example using it with a
magnetic reed switch, which is often used to detect open doors or windows.
Laser tripwire
Extending the previous example concept a bit further, let's take a look at how this could
be applied to creating a laser tripwire. Building a laser tripwire requires the following
additional components:
7 Note
Laser receiver sensor module is the generic name applied to a common module
found at many internet retailers. The device may vary in name or manufacturer, but
should resemble this image.
Pay close attention to the 10K Ω resistors. These implement a voltage divider . This is
because the laser receiver module outputs 5V to indicate the beam is broken. Raspberry
Pi only supports up to 3.3V for GPIO input. Since sending the full 5V to the pin could
damage the Raspberry Pi, the current from the receiver module is passed through a
voltage divider to halve the voltage to 2.5V.
C#
controller.OpenPin(pin, PinMode.InputPullDown);
) Important
Make sure the code deployed on your Raspberry Pi includes this change before
testing a laser tripwire. The program does work without it, but using the wrong
input mode risks damage to your Raspberry Pi!
Next steps
Learn how to read environmental conditions from a sensor
Read environmental conditions from a
sensor
Article • 04/08/2023
One of the most common scenarios for IoT devices is detection of environmental
conditions. A variety of sensors are available to monitor temperature, humidity,
barometric pressure, and more.
In this topic, you will use .NET to read environmental conditions from a sensor.
Prerequisites
ARM-based (ARMv7 or greater) single-board computer (SBC)
BME280 humidity/barometric pressure/temperature sensor breakout
Jumper wires
Breadboard (optional)
Raspberry Pi GPIO breakout board (optional)
.NET SDK 7 or later
7 Note
This tutorial is written assuming the target device is Raspberry Pi. However, this
tutorial can be used for any Linux-based SBC that supports .NET, such as Orange Pi,
ODROID, and more.
) Important
There are many manufacturers of BME280 breakouts. Most designs are similar, and
the manufacturer shouldn't make any difference to the functionality. This tutorial
attempts to account for variations. Ensure your BME280 breakout includes an Inter-
Integrated Circuit (I2C) interface.
Components like BME280 breakouts are often sold with unsoldered pin headers. If
you're uncomfortable with soldering, look for a BME280 breakout board with a pre-
soldered header or a different connector. If you want, consider learning how to
solder! Here's a good beginner's guide to soldering .
Prepare the SBC
Ensure your SBC is configured to support the following services:
SSH
I2C
For many devices, no additional configuration is required. For Raspberry Pi, use the
raspi-config command. For more information on raspi-config , refer to the Raspberry
Pi documentation .
The following are the connections from the Raspberry Pi to the BME280 breakout. Note
that pin labels differ on various BME280 breakouts.
Tip
1. Create a new .NET Console App using either the .NET CLI or Visual Studio. Name it
SensorTutorial.
.NET CLI
2. Add the Iot.Device.Bindings package to the project. Use either .NET CLI from the
project directory or Visual Studio.
.NET CLI
dotnet add package Iot.Device.Bindings --version 2.2.0-*
C#
using System;
using System.Device.I2c;
using System.Threading;
using Iot.Device.Bmxx80;
using Iot.Device.Bmxx80.PowerMode;
while (true)
{
Console.Clear();
bme280.SetPowerMode(Bmx280PowerMode.Forced);
Thread.Sleep(measurementTime);
Console.WriteLine($"Temperature:
{tempValue.DegreesCelsius:0.#}\u00B0C");
Console.WriteLine($"Pressure: {preValue.Hectopascals:#.##} hPa");
Console.WriteLine($"Relative humidity: {humValue.Percent:#.##}%");
Console.WriteLine($"Estimated altitude: {altValue.Meters:#} m");
Thread.Sleep(1000);
}
) Important
Some BME280 breakout manufacturers use the secondary address value.
For those devices, use Bme280.SecondaryI2cAddress .
The time required for the chip to take measurements with the chip's current
(default) settings is retrieved by calling GetMeasurementDuration .
7 Note
estimate.
4. Build the app. If using the .NET CLI, run dotnet build . To build in Visual Studio,
press Ctrl + Shift + B .
5. Deploy the app to the SBC as a self-contained app. For instructions, see Deploy
.NET apps to Raspberry Pi. Make sure to give the executable execute permission
using chmod +x .
6. Run the app on the Raspberry Pi by switching to the deployment directory and
running the executable.
Bash
./SensorTutorial
Next steps
Learn how to display text on an LCD
Display text on an LCD
Article • 04/08/2023
LCD character displays are useful for displaying information without the need for an
external monitor. Common LCD character displays can be connected directly to the
GPIO pins, but such an approach requires the use of up to 10 GPIO pins. For scenarios
that require connecting to a combination of devices, devoting so much of the GPIO
header to a character display is often impractical.
Many manufacturers sell 20x4 LCD character displays with an integrated GPIO expander.
The character display connects directly to the GPIO expander, which then connects to
the Raspberry Pi via the Inter-Integrated Circuit (I2C) serial protocol.
In this topic, you will use .NET to display text on an LCD character display using an I2C
GPIO expander.
Prerequisites
ARM-based (ARMv7 or greater) single-board computer (SBC)
20x4 LCD Character Display with I2C interface
Jumper wires
Breadboard (optional/recommended)
Raspberry Pi GPIO breakout board (optional/recommended)
.NET SDK 7 or later
7 Note
This tutorial is written assuming the target device is Raspberry Pi. However, this
tutorial can be used for any Linux-based SBC that supports .NET, such as Orange Pi,
ODROID, and more.
7 Note
There are many manufacturers of LCD character displays. Most designs are
identical, and the manufacturer shouldn't make any difference to the functionality.
For reference, this tutorial was developed with the SunFounder LCD2004 .
SSH
I2C
For many devices, no additional configuration is required. For Raspberry Pi, use the
raspi-config command. For more information on raspi-config , refer to the Raspberry
Pi documentation .
GND to ground
VCC to 5V
SDA to SDA (GPIO 2)
SCL to SCL (GPIO 3)
Tip
.NET CLI
2. Add the Iot.Device.Bindings package to the project. Use either .NET CLI from the
project directory or Visual Studio.
.NET CLI
C#
using System;
using System.Device.Gpio;
using System.Device.I2c;
using System.Threading;
using Iot.Device.CharacterLcd;
using Iot.Device.Pcx857x;
while (true)
{
lcd.Clear();
lcd.SetCursorPosition(0,currentLine);
lcd.Write(DateTime.Now.ToShortTimeString());
currentLine = (currentLine == 3) ? 0 : currentLine + 1;
Thread.Sleep(1000);
}
In the preceding code:
busId and deviceAddress parameters. This I2cDevice represents the I2C bus.
The using declaration ensures the object is disposed and hardware resources
are released properly.
2 Warning
The device address for the GPIO expander depends on the chip used by
the manufacturer. GPIO expanders equipped with a PCF8574 use the
address 0x27 , while those using PCF8574A chips use 0x3F . Consult your
LCD's documentation.
4. Build the app. If using the .NET CLI, run dotnet build . To build in Visual Studio,
press Ctrl + Shift + B .
5. Deploy the app to the SBC as a self-contained app. For instructions, see Deploy
.NET apps to Raspberry Pi. Make sure to give the executable execute permission
using chmod +x .
6. Run the app on the Raspberry Pi by switching to the deployment directory and
running the executable.
Bash
./LcdTutorial
Observe the LCD character display as the current time displays on each line.
Tip
If the display is lit but you don't see any text, try adjusting the contrast dial on
the back of the display.
Congratulations! You've displayed text on an LCD using a I2C and a GPIO expander!
Next steps
Learn to use General Purpose Input/Output to blink an LED
Read values from an analog-to-digital
converter
Article • 04/08/2023
An analog-to-digital converter (ADC) is a device that can read an analog input voltage
value and convert it into a digital value. ADCs are used for reading values from
thermistors, potentiometers, and other devices that change resistance based on certain
conditions.
In this topic, you will use .NET to read values from an ADC as you modulate the input
voltage with a potentiometer.
Prerequisites
ARM-based (ARMv7 or greater) single-board computer (SBC)
MCP3008 analog-to-digital converter
Three-pin potentiometer
Breadboard
Jumper wires
Raspberry Pi GPIO breakout board (optional/recommended)
.NET SDK 7 or later
7 Note
This tutorial is written assuming the target device is Raspberry Pi. However, this
tutorial can be used for any Linux-based SBC that supports .NET, such as Orange Pi,
ODROID, and more.
SSH
SPI
For many devices, no additional configuration is required. For Raspberry Pi, use the
raspi-config command. For more information on raspi-config , refer to the Raspberry
Pi documentation .
Prepare the hardware
Use the hardware components to build the circuit as depicted in the following diagram:
The MCP3008 uses Serial Peripheral Interface (SPI) to communicate. The following are
the connections from the MCP3008 to the Raspberry Pi and potentiometer:
Supply 3.3V and ground to the outer pins on the potentiometer. Order is unimportant.
Tip
1. Create a new .NET Console App using either the .NET CLI or Visual Studio. Name it
AdcTutorial.
.NET CLI
2. Add the Iot.Device.Bindings package to the project. Use either .NET CLI from the
project directory or Visual Studio.
.NET CLI
C#
using System;
using System.Device.Spi;
using System.Threading;
using Iot.Device.Adc;
4. Build the app. If using the .NET CLI, run dotnet build . To build in Visual Studio,
press Ctrl + Shift + B .
5. Deploy the app to the SBC as a self-contained app. For instructions, see Deploy
.NET apps to Raspberry Pi. Make sure to give the executable execute permission
using chmod +x .
6. Run the app on the Raspberry Pi by switching to the deployment directory and
running the executable.
Bash
./AdcTutorial
Observe the output as you rotate the potentiometer dial. This is due to the
potentiometer varying the voltage supplied to CH0 on the ADC. The ADC
compares the input voltage on CH0 to the reference voltage supplied to VREF to
generate a value.
Next steps
Learn to use General Purpose Input/Output to blink an LED
Deploy .NET apps on ARM single-board
computers
Article • 04/08/2023
1. Ensure SSH is enabled on your device. For Raspberry Pi, refer to Setting up an SSH
Server in the Raspberry Pi documentation .
2. Install .NET on the device using the dotnet-install scripts. Complete the following
steps from a Bash prompt on the device (local or SSH):
Bash
This installs the latest version. If you need a specific version, replace the --
channel STS parameter with --version <VERSION> , where <VERSION> is the
specific build version.
Bash
.NET CLI
dotnet --version
If using Visual Studio, deploy the app to a local folder. Before publishing,
select Edit in the publish profile summary and select the Settings tab. Ensure
that Deployment mode is set to Framework-dependent and Target runtime is
set to Portable.
If using the .NET CLI, use the dotnet publish command. No additional
arguments are required.
4. Using an SFTP client like scp , copy the files from the publish location on the
development computer to a new folder on the SBC.
For example, to use the scp command to copy files from the development
computer to your SBC, open a command prompt and execute the following:
Console
Tip
5. From a Bash prompt on the Raspberry Pi (local or SSH), run the app. To do this, set
the deployment folder as the current directory and execute the following
command (where HelloWorld.dll is the entry point of the app):
.NET CLI
dotnet HelloWorld.dll
1. Ensure SSH is enabled on your device. For Raspberry Pi, refer to Setting up an SSH
Server in the Raspberry Pi documentation .
2. Publish the app on the development computer as follows, depending on
development environment.
If using Visual Studio, deploy the app to a local folder. Before publishing,
select Edit in the publish profile summary and select the Settings tab. Ensure
that Deployment mode is set to Self-contained and Target runtime is set to
linux-arm64.
If using the .NET CLI, use the dotnet publish command with the --runtime
linux-arm64 and --self-contained arguments:
.NET CLI
) Important
If you're using a 32-bit OS, you need to target the linux-arm runtime.
3. Using an SFTP client like scp , copy the files from the publish location on the
development computer to a new folder on the SBC.
For example, to use the scp command to copy files from the development
computer to your SBC, open a command prompt and execute the following:
Console
Where:
<username>@<hostname> .
/home/pi/deployment-location/ is the new folder on the SBC.
Tip
a. Give the executable execute permission (where HelloWorld is the executable file
name).
Bash
chmod +x HelloWorld
Bash
./HelloWorld
Debug .NET apps on ARM single-board
computers
Article • 04/08/2023
Debugging .NET apps running on ARM-based SBCs like Raspberry Pi presents a unique
challenge. If desired, you can install Visual Studio Code and the .NET SDK on the device
and develop locally. However, the device's performance is such that coding and
debugging locally is not ideal. Additionally, the Visual Studio Code extension for C# is
not compatible with 32-bit ARM operating systems. Consequently, functionality like
IntelliSense and debugging in Visual Studio Code on ARM devices is only supported in
64-bit systems.
For these reasons, it's strongly recommended that you develop your app on a
development computer and then deploy the app to the device for remote debugging. If
you wish to develop and debug locally on the device, the following is required:
The rest of this article describes how to debug .NET apps on single-board computers
remotely from a development computer.
) Important
) Important
Bash
The new configuration in launch.json should look similar to one of the following:
Self-contained
JSON
"configurations": [
{
"name": ".NET Remote Launch - Self-contained",
"type": "coreclr",
"request": "launch",
"program": "~/sample/sample",
"args": [],
"cwd": "~/sample",
"stopAtEntry": false,
"console": "internalConsole",
"pipeTransport": {
"pipeCwd": "${workspaceRoot}",
"pipeProgram": "ssh",
"pipeArgs": [
"pi@raspberrypi"
],
"debuggerPath": "~/vsdbg/vsdbg"
}
},
cwd is the working directory to use when launching the app on the device.
The .NET IoT libraries are commonly used to develop code for Raspberry Pi and other
IoT devices. However, you can also use them to develop code for Windows, Linux, and
macOS PCs using a USB-to-serial adapter such as the FTDI FT232H . This article shows
you how to use the .NET IoT libraries to communicate with devices connected to the
FT232H adapter.
Tip
This article uses an FTDI FT232H adapter, but you can use any USB-to-serial
adapter that is supported by the .NET IoT libraries, such as the FT2232H, FT4232H,
and FT4222. Check the list of supported device bindings for more information.
Prerequisites
Ensure you have installed the D2XX drivers for your USB-to-serial adapter, which are
found on the FTDI website .
7 Note
Windows devices may automatically install the drivers when you plug in the
adapter. Check Device Manager for a device named USB Serial Converter listed
under Universal Serial Bus controllers. The device's driver provider should be FTDI.
C#
using Iot.Device.FtCommon;
if (devices.Count == 0)
{
Console.WriteLine("No device connected");
return;
}
In the preceding code, the FtCommon.GetDevices() method returns a list of all connected
FTDI devices.
In the preceding image, the LED circuit is very similar to the original tutorial. The only
difference is that the LED is connected to pin D7 on the FT232H adapter instead of pin
18 on the Raspberry Pi.
The code for the tutorial is also similar to the original tutorial:
C#
using System.Device.Gpio;
using Iot.Device.Ft232H;
using Iot.Device.FtCommon;
The D0 and D1 pins on the FT232H adapter are connected to the SDL and SCA pins
on the BME280 breakout board, respectively.
The I2C selector switch on the BME280 breakout board is set to On.
C#
using System.Device.I2c;
using Iot.Device.Bmxx80;
using Iot.Device.Bmxx80.PowerMode;
using Iot.Device.Ft232H;
using Iot.Device.FtCommon;
while (true)
{
Console.Clear();
bme280.SetPowerMode(Bmx280PowerMode.Forced);
Thread.Sleep(measurementTime);
Console.WriteLine($"Temperature:
{tempValue.DegreesCelsius:0.#}\u00B0C");
Console.WriteLine($"Pressure: {preValue.Hectopascals:#.##} hPa");
Console.WriteLine($"Relative humidity: {humValue.Percent:#.##}%");
Console.WriteLine($"Estimated altitude: {altValue.Meters:#} m");
Thread.Sleep(1000);
}
The D0, D1, D2, and D3 pins on the FT232H adapter are connected to the CLK,
DIN, DOUT,and CS/SHDN pins on the MCP3008, respectively.
The I2C selector switch on the MCP3008 breakout board is set to Off.
C#
using System.Device.Gpio;
using System.Device.Spi;
using Iot.Device.Adc;
using Iot.Device.Ft232H;
using Iot.Device.FtCommon;
6 Collaborate with us on
GitHub .NET feedback
.NET is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
Open a documentation issue
issues and pull requests. For
more information, see our
Provide product feedback
contributor guide.