Raspberry Build HAT: Controlling LEGO Engines with .NET
In this beginner-friendly guide, you’ll learn how to control LEGO motors connected to a Raspberry Pi via the official Raspberry Pi Build HAT — using a simple, pure .NET application. We’ll use the Iot.Device.BuildHat NuGet package, which provides a friendly .NET API for the Build HAT. No Python required. We’ll also publish the app as a self-contained .NET 9 binary for linux-arm64 so you do not need to install .NET on the Raspberry Pi. This approach is easy to set up, reliable, and a great starting point for your own robotics projects.
Hardware
To get started with controlling LEGO engines using the Raspberry Pi and .NET, you’ll need the following hardware components:
- Raspberry Pi, this sample uses a Raspberry Pi 4 B, but its should also work with the Pi 5
- It’s recommended to cool your Raspberry Pi, especially when using it for extended periods.
- A Raspberry Pi Build HAT Module
- A compatible LEGO motor (e.g., LEGO Vestas 10268)
Raspberry Configuration
We’ll prepare the Raspberry Pi for I2C (required by the Build HAT). You do not need to install .NET on the Pi because we’ll publish a self-contained binary for linux-arm64.
- Flash Raspberry Pi OS
- Use Raspberry Pi Imager to install a recent Raspberry Pi OS (64-bit recommended).
- Enable SSH, set a hostname, and Wi‑Fi if you prefer headless setup.
2. Update system packages
sudo apt update && sudo apt full-upgrade -y
sudo reboot3. Enable I2C (required by the Build HAT)
sudo raspi-config
# Interface Options -> I2C -> Enable
sudo reboot4. No .NET runtime needed on the Pi
We’ll build and publish a self-contained .NET 9 linux-arm64 binary on your development machine (Windows, macOS, or Linux) and just copy the single file to the Pi.
5. Attach the Build HAT and motor
- Power off the Pi.
- Seat the Build HAT on the Pi’s GPIO header.
- Connect your LEGO motor to port A on the HAT.
- If needed, connect external power to the HAT.
- Power on the Pi again.
.NET Code
This section covers the .NET code needed to control the LEGO motors via the Build HAT.
Step 1: Create the .NET 9 console app (on your dev machine)
Create a new .NET 9 console app (on the Pi or locally and copy over):
dotnet new console -n BuildHatControlAdd the NuGet package and replace Program.cs with the following minimal example. The package name is Iot.Device.Bindings.
Get BEN ABT’s stories in your inbox
Join Medium for free to get updates from this writer.
Configure now your project to run on the Raspberry Pi and Arm64
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Iot.Device.Bindings" Version="4.0.1" />
</ItemGroup>
<PropertyGroup Label="Build">
<RuntimeIdentifiers>linux-arm64</RuntimeIdentifiers>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishReadyToRunShowWarnings>false</PublishReadyToRunShowWarnings>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
</Project>Replace Program.cs with the following:
using System;
using System.Device.I2c;
using System.Threading;
using Iot.Device.BuildHat;
// First, connect to your Build HAT
// the serial port to use, in our case serial0
Brick brick = new Brick("/dev/serial0");
// the sensor port is the port where the motor is connected, in this case, we use Port A
string sensorPort = "0";
// now, we need to send commands to the motor
// first, we send a power limit: this means we want to define the limit of the motor's power
brick.SendRawCommand($"port {sensorPort} ; plimit 1\r");
// second, we send the bias: Motor commands are amplified by 0.1 upwards or, in the case of negative commands, attenuated by 0.1. This can be helpful, for example, if the motor tends to “stick” in one direction or reacts unevenly.
brick.SendRawCommand($"port {sensorPort} ; bias 0\r");
// now we can start the engine:
double speed = 0.70; // this means. 70%
brick.SendRawCommand($"port {sensorPort} ; pwm ; set {speed.ToString(CultureInfo.InvariantCulture)}\r");
Console.WriteLine("Engine started, wroooooom!");Step 2: Publish a self-contained linux-arm64 binary
From the BuildHatControl folder on your dev machine, publish for the Raspberry Pi as a single-file, self-contained binary:
dotnet publish -c Release -r linux-arm64 --self-contained true -p:PublishSingleFile=trueThe output will be in bin/Release/net9.0/linux-arm64/publish/ and include a single executable named BuildHatControl, your project name.
Notes:
- linux-arm64 assumes you run 64‑bit Raspberry Pi OS. If you’re on 32‑bit OS, use
-r linux-arminstead and rebuild (also adjust your profile file!).
Step 3: Copy to the Raspberry Pi and run
Copy the published file to the Pi (replace pi@raspberrypi and the path as needed):
scp bin/Release/net9.0/linux-arm64/publish/BuildHatControl pi@raspberrypi:/home/pi/buildhat/BuildHatControlYou can also use a UI app like WinSCP.
SSH into the Pi, make it executable, and run:
chmod +x /home/pi/buildhat/BuildHatControl
chmod 755 /home/pi/buildhat/BuildHatControl
cd /home/pi/buildhat
./BuildHatControlYou should see the motor spin!
How it works (in short)
- The Build HAT exposes ports (A–D) for LEGO motors/sensors and communicates with the Pi over I2C.
- The
Iot.Device.BuildHatpackage wraps that protocol in a friendly .NET API. - Everything stays in C#, making integration with other .NET components straightforward.
Beyond hobby?
If you’re moving beyond hobby projects and care about reliability, read the follow-up on unit testing with the Raspberry Pi Build HAT: Raspberry Build HAT: Unit Testing Strategies with .NET
Conclusion
You’ve built a beginner‑friendly, pure .NET setup that controls LEGO motors with the Raspberry Pi Build HAT:
- The Raspberry Pi handles hardware access; the Build HAT speaks to LEGO motors.
- The
Iot.Device.BuildHatpackage provides a reliable control surface. - Your .NET code orchestrates actions, integrates with other systems, and provides structure.
From here you can extend this sample with sensors, ramping/acceleration profiles, or position control — and wrap it in richer .NET services, Web APIs or UI apps. Have fun building! 🚀
Author
BEN ABT
Ben is a Principal Software Engineer at Medialesson.de, with a strong focus on .NET and Microsoft Azure. In his professional role, he designs and builds highly scalable platforms for hybrid and cloud-based scenarios. He also advises companies and C-levels on migrating to the sovereign cloud.
He runs myCSharp.de, the largest and most active German-speaking C# community forum, actively contributes to both his own and external open-source projects, and regularly shares his knowledge through his blog, at community events, conferences, and as a writer for technical magazines.










