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

  1. Flash the .wic.gz to an SD card: sudo dd if=core-image-minimal-raspberrypi5.wic of=/dev/sdX bs=4M status=progress
  2. Boot the Pi.
  3. 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 IoTC++
Dev SpeedFast, modern libsSlower, lower-level
PerformanceGood, but slightly higher RAMOptimal
Libraries (GPIO/Sensor)System.Device.Gpio, IoT libswiringPi, libgpiod
Yocto IntegrationNeeds custom layer + runtimeEasy native build
PortabilityHigh (cross-platform .NET)Board-dependent
DebuggingVS Code + CLI supportGDB, 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

🛠 Building and Deploying a .NET IoT App with Yocto on Raspberry Pi (and C++ Comparison)

Johannes Rest


.NET Architekt und Entwickler


Beitragsnavigation


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert