A first project in nanoFramework is the minimal application that verifies the environment, firmware, and board are working.
In the desktop programming world, “Hello World” means printing text on the screen. In the electronics world, the equivalent is making an LED blink. It’s the definitive test that the hardware works, the compiler compiles, and the code is executing.
In this post, we’ll create our first project from scratch. We’ll see that, although the final code is simple, the structure surrounding the project is much more professional and organized than a simple Arduino .ino sketch.
Create the Solution in Visual Studio
First, create the project. Open Visual Studio and select “Create a new project”.
In the template search box, type nanoFramework. If you installed the extension correctly, you’ll see several options. We will choose Blank Application (nanoFramework).
Give it a name (e.g., HolaMundoNano) and a location. When you click “Create”, Visual Studio will generate the file structure.
Solution Structure
If you are coming from Arduino, the structure might seem strange at first. We don’t have a single code file, but rather a solution .sln containing a project .csproj.
Let’s look at the Solution Explorer:
Properties/AssemblyInfo.cs
Assembly information (version, author, copyright).
References
No #include here. Here you add references to compiled libraries (DLLs).
packages.config
The file that manages NuGet packages. It indicates which external libraries we are using and their versions.
Program.cs
Our main code file. This is the entry point.
Unlike Arduino, where setup() and loop() are hidden in the core, in C# we have a Main() function. We have total control over the execution flow from millisecond zero.
Console Hello World
Before turning on lights, let’s say hello. Open the Program.cs file. You’ll see something like this:
using System;
using System.Diagnostics;
using System.Threading;
namespace HolaMundoNano
{
public class Program
{
public static void Main()
{
Debug.WriteLine("Hello from nanoFramework!");
Thread.Sleep(Timeout.Infinite);
}
}
}Notice Debug.WriteLine. This is important.
In Arduino, we used Serial.print and needed to initialize the serial port (Serial.begin). Not here.
nanoFramework redirects debug output directly to Visual Studio’s Output window over the same USB cable, without you having to manually configure UART ports.
- Make sure your board is connected and selected in the Device Explorer.
- Press F5 (or the “Start” button).
Visual Studio will compile the code, upload it to the microcontroller, and attach the debugger. In the Output window, you’ll see:
Hello from nanoFramework!
Blinky: Make an LED Blink
Now for the good part. We want to control a GPIO pin.
In “full” .NET or Arduino, hardware functions are usually included. In nanoFramework, to save memory, the core is minimal. If you want to use GPIO, you must install the corresponding library.
Install the NuGet Package
Right-click on your project (in the Solution Explorer) -> Manage NuGet Packages.
Go to the Browse tab.
Search for: nanoFramework.System.Device.Gpio.
Install the latest stable version.
Get used to this. Want to use I2C? NuGet. Want to connect to Wi-Fi? NuGet. This keeps your firmware lightweight, including only what you actually use.
The Code
Now let’s modify Program.cs to make the board’s built-in LED blink.
On most ESP32 DevKit boards, the built-in blue LED is on GPIO 2.
using System;
using System.Device.Gpio; // <--- Important: The hardware namespace
using System.Threading;
namespace HolaMundoNano
{
public class Program
{
public static void Main()
{
// 1. Define the pin (GPIO 2 is common on ESP32)
int pinNumber = 2;
// 2. Instantiate the controller
GpioController gpio = new GpioController();
// 3. Open the pin and configure it as OUTPUT
GpioPin led = gpio.OpenPin(pinNumber, PinMode.Output);
// 4. Infinite loop (equivalent to Arduino's loop)
while (true)
{
// Turn on (Write receives a PinValue)
led.Write(PinValue.High);
Console.WriteLine("LED On");
// Wait 1000ms (1 second)
Thread.Sleep(1000);
// Turn off
led.Write(PinValue.Low);
Console.WriteLine("LED Off");
Thread.Sleep(1000);
}
}
}
}Notice the object orientation:
GpioController: We don’t manipulate registers directly. We create an object that represents the chip’s input/output controller.OpenPin: We ask the controller to “reserve” pin 2 for us. This returns aGpioPinobject.led.Write(...): We act on theledobject, not a global number.Thread.Sleep(1000): This stops the current thread for 1000ms. Unlikedelay()in Arduino, which blocks the processor, in a multithreaded system this simply “sleeps” this task, allowing the system to do other things (like maintaining a Wi-Fi connection) in the background.
Deployment and Debugging
Press F5 again.
You’ll see the LED on your board start blinking. But that’s not the best part. The best part is this:
Go to the line led.Write(PinValue.High);.
Click on the left margin to set a red dot (Breakpoint).
The LED will stop blinking and Visual Studio will light up. The program has paused on the chip.
Hover your mouse over the pinNumber variable. You’ll see its value!
You can press F10 to step through and see how each line executes. This is what differentiates a toy from a professional tool. Being able to debug hardware step by step will save you hundreds of hours of frustration guessing why something doesn’t work.
We have created a solution, installed a library via NuGet, and written object-oriented code to handle basic hardware.
The structure might seem more verbose than digitalWrite(2, HIGH), but it is infinitely more scalable. When you have 50 sensors and 3 execution threads, you’ll appreciate this order.