Introduction
In this post, we’ll go from zero to running a custom .NET IoT application on the latest Raspberry Pi 5, built with the power of Yocto Linux. We’ll write the application in C# with .NET, build a minimal image with Yocto, deploy and run the app — and then reimplement the same logic in C++ to see the differences.
🌱 Why Yocto and .NET?
- Yocto gives you a custom Linux image, tailored for your hardware and software needs.
- .NET (8 or 9) allows modern, high-level development, even for small devices like the Raspberry Pi.
- The combination is powerful for industrial IoT, kiosks, controllers, and edge AI.
🧰 Requirements
- Raspberry Pi 5 (or 4)
- Host machine (Linux preferred) with ~50 GB disk space
- Basic Yocto and .NET knowledge
- Installed:
repo,git,docker(optional for container builds),bitbake,.NET SDK, C++ compiler
⚙️ 1. Yocto Setup for Raspberry Pi 5
We’ll use Kirkstone or newer release of Yocto, as it’s stable and supports recent kernels.
Clone Yocto + Layers
mkdir yocto-dotnet && cd yocto-dotnet
repo init -u https://github.com/yoctoproject/manifest -b kirkstone
repo sync
Add Layers
Clone layers:
git clone https://github.com/agherzan/meta-raspberrypi.git
git clone https://github.com/meta-dotnet/meta-dotnet.git
git clone https://git.openembedded.org/meta-openembedded
Configure Yocto
Create build/conf/local.conf and set:
MACHINE = "raspberrypi5"
DISTRO_FEATURES:append = " systemd"
IMAGE_INSTALL:append = " coreclr dotnet-runtime"
Add layers in bblayers.conf:
BBLAYERS += "${TOPDIR}/../meta-raspberrypi"
BBLAYERS += "${TOPDIR}/../meta-dotnet"
BBLAYERS += "${TOPDIR}/../meta-openembedded/meta-oe"
Build the Image
source oe-init-build-env
bitbake core-image-minimal
You’ll get a .wic.gz image for Raspberry Pi, ready to flash.
🧑💻 2. Writing a .NET App
Let’s build a simple app that reads temperature from a DHT22 sensor (via GPIO), logs it, and blinks an LED.
.NET Code
// Program.cs
using System.Device.Gpio;
using System.Device.Gpio.Drivers;
using Iot.Device.Dhtxx;
var ledPin = 18;
var dhtPin = 4;
using var controller = new GpioController();
controller.OpenPin(ledPin, PinMode.Output);
var dht = new Dht22(dhtPin, controller);
while (true)
{
if (dht.TryReadTemperature(out var temperature) &&
dht.TryReadHumidity(out var humidity))
{
Console.WriteLine($"Temp: {temperature}, Humidity: {humidity}");
}
controller.Write(ledPin, PinValue.High);
await Task.Delay(500);
controller.Write(ledPin, PinValue.Low);
await Task.Delay(500);
}
Build the App
dotnet publish -r linux-arm64 -c Release -o out
Result: a self-contained app in out/.
📦 3. Creating a Yocto Recipe for the App
Create a layer for your app:
bitbake-layers create-layer ../meta-myapp
bitbake-layers add-layer ../meta-myapp
Recipe myapp_1.0.bb
SUMMARY = "My .NET IoT App"
LICENSE = "MIT"
SRC_URI = "file://out"
S = "${WORKDIR}/out"
do_install() {
install -d ${D}${bindir}/myapp
install -m 0755 ${S}/* ${D}${bindir}/myapp/
}
FILES:${PN} += "${bindir}/myapp"
Add the app to your image:
IMAGE_INSTALL:append = " myapp"
Rebuild:
bitbake core-image-minimal
🚀 4. Deploy and Run
- Flash the
.wic.gzto an SD card:sudo dd if=core-image-minimal-raspberrypi5.wic of=/dev/sdX bs=4M status=progress - Boot the Pi.
- Run the app:
/usr/bin/myapp/MyApp
It should read sensors and blink the LED!
⚙️ 5. C++ Equivalent
Here’s the equivalent logic in modern C++ using wiringPi or libgpiod.
main.cpp
#include <wiringPi.h>
#include <iostream>
#include <chrono>
#include <thread>
int main() {
wiringPiSetupGpio();
int ledPin = 18;
pinMode(ledPin, OUTPUT);
while (true) {
std::cout << "Blink\n";
digitalWrite(ledPin, HIGH);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
digitalWrite(ledPin, LOW);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
Build with CMake
g++ main.cpp -lwiringPi -o myapp
To deploy in Yocto, follow similar steps: create a layer, recipe, and install the binary.
🧾 Summary
| Feature | .NET IoT | C++ |
|---|---|---|
| Dev Speed | Fast, modern libs | Slower, lower-level |
| Performance | Good, but slightly higher RAM | Optimal |
| Libraries (GPIO/Sensor) | System.Device.Gpio, IoT libs | wiringPi, libgpiod |
| Yocto Integration | Needs custom layer + runtime | Easy native build |
| Portability | High (cross-platform .NET) | Board-dependent |
| Debugging | VS Code + CLI support | GDB, logs |
🏁 Final Thoughts
Yocto + .NET on Raspberry Pi brings modern language features to embedded Linux without losing control over the system image. If your team prefers rapid development and C# experience, it’s a strong choice. C++ still shines for ultra-low-latency, low-resource systems.
Next Steps:
- Add logging and remote monitoring
- Package updates via OTA
- Experiment with containerized deployment
Let me know if you’d like this as a downloadable Markdown or want it split into multiple posts.
Views: 18
