Blog >
Nowadays, using the .NET ecosystem, we can develop software for a variety of platforms, from the basic application of creating web application backends, through desktop applications, to mobile applications for Android and iOS. However, is it possible to write software in .NET for embedded systems, where hardware resources in the form of available memory and processor computing power are sometimes severely limited?
Programming embedded systems based on 8- or 32-bit microcontrollers may be associated with the need to use lower-level languages than C#, such as C/C++. However, it turns out that with the .NET nanoFrameworkwe can, using C#, develop software that runs on such popular microcontroller families as ESP32 or STM32.
In this article, I will present an example of using the nanoFramework and ESP32 to build a simple weather station module to measure temperature, pressure and humidity.
The nanoFramework is a platform that enables you to write code in C# that runs on multiple microcontroller families. The key module is nanoCLR, a Common Language Runtime (CLR) implementation of the C# language virtual machine designed specifically for microcontrollers.
nanoCLR implements only part of the C# language standard and its standard library API mainly due to the very limited hardware resources available to microcontrollers. However, these shortcomings are not a major limitation. The programmer can still use facilities such as, for example, the automatic memory deallocation mechanism (garbage collection) or the syntax associated with the object-oriented programming paradigm (classes, structures, polymorphism, etc.). The idea is that this speeds up software development compared to using C/C++, especially when the programmer does not have much experience in programming embedded systems.
The ESP32 is a 32-bit microcontroller manufactured by Espressif Systems since 2016. It is the successor to the 8-bit ESP8266 microcontroller, which, like its predecessor, quickly became very popular due to the good price/performance ratio offered. Among other things, the microcontroller has been designed for wearable electronics applications, as well as for Internet of Things solutions.
One of its main advantages is the integrated Bluetooth Low Energy and WiFi interface. This enables easy integration of devices based on this microcontroller into Internet of Things solutions. The ESP32 is widely available on the market in the form of prototype boards with an integrated USB interface.
These types of modules are ideal for prototyping due to the ease of powering and programming the microcontroller via the USB interface and the derivation of all input-output ports in the form of GPIO pins.
The easiest way to work with nanoFramework is to use the Visual Studio IDE. The developers of the framework provide a corresponding plug-in available in the Visual Studio Market Place This plug-in makes it convenient to upload code to the microcontroller and debug it. We also need the nanoff tool which allows the appropriate version of nanoFramework to be loaded into the microcontroller's memory.
If you have a prototype board with an ESP32 microcontroller (e.g. ESP-WROOM-32, available at many electronic component shops), you can get started. After connecting it to the computer via USB, check in the device manager which port number has been assigned to it:
In the example above, we see that the port number is COM4. We then use the nanoff tool to upload the latest version of nanoframework to the microcontroller using the command:
nanoff --update --target ESP32_PSRAM_REV0 --serialport COM4
If the operation is successful, a message is displayed:
Once the nanoFramework has been uploaded to the microcontroller, it should be detected in Visual Studio from the 'Device Explorer' section, which is available under 'View' -> 'Other Windows' after installing the plugin:
We can then create a new project from within the Visual Studio wizard:
The new project will, by default, have a Hello world application implementation:
We can now upload the project to the microcontroller and run in debugging mode in the same way as any other project in Visual Studio. If the operation goes correctly, we will see "Hello from nanoFramework" in the debugging console output:
In order for our microcontroller to measure temperature, pressure and humidity, we need suitable sensors and their connection to the microcontroller via its input/output ports. A very popular sensor that can measure these 3 parameters simultaneously is the BME280 from Bosch. It is widely available on the market, also in the form of a prototype board:
The BME280 uses the I2C or SPI bus to communicate with the microcontroller. The schematic for connecting this sensor to the ESP32 microcontroller prototype board via the I2C bus can look as follows:
The data line (SDA, connection marked in green) is connected to port 2 and the clock signal line (SCL, connection marked in blue) to port 22 of the microcontroller. The sensor is supplied with 3.3V derived from the corresponding pin of the prototyping board (connection marked in red).
To establish communication between the ESP32 and the BME280, we need a suitable driver. However, we do not need to implement our own solution based on the BME280 documentation because a ready-made driver for this sensor is available in the Nuget package Iot.Device.Bmxx80. After adding this package to our project in Visual Studio, we can configure communication with the sensor:
First, we need to configure specific microcontroller pins (in this case pins 21 and 22) as data (SDA) and clock signal (SCL) ports of the I2C bus. Next, we create the device configuration for the I2C bus and pass it to the constructor of the Bme280 class representing the BME280 sensor driver. Finally, in an infinite loop, we read the measured temperature, pressure and humidity values from the sensor every 5 seconds and send the measurement values as a formatted string to the standard output.
After uploading this simple program to the microcontroller's memory and running it in debug mode, the microcontroller will start writing the measurement results to the standard output every 5 seconds:
The biggest advantage of nanoFramework is the low entry threshold for developers who have a good understanding of C# and the .NET ecosystem but no experience of programming microcontrollers using the most commonly used languages in this case, C and C++. This allows the developer to focus mainly on implementing business logic using the high-level C# language, rather than delving into the nuances of the SDK for a specific microcontroller.
The disadvantages of the nanoFramework in particular include the fact that it adds a sizable additional layer of abstraction to the software running on the microcontroller. When using the C/C++ languages, the code is compiled directly into machine code executed by the microcontroller's CPU. In the case of nanoFramework, code written in C# is not compiled into machine code, but into Common Intermediate Language (CIL) code, which is then executed by the virtual machine. This can have a significant impact on performance when the code is executed on a microcontroller, an environment inherently equipped with very limited resources (RAM, CPU performance).
The example of using nanoFramework presented in the article is very simple. Can this platform be used to implement a much more complex solution? Expanding on the original idea, in the next article in this series I will present the capabilities of nanoFramework and ESP32 for integration with the Azure IoT Hub service. This will allow the implementation of two-way communication of the microcontroller with any other services running in the Azure cloud.
Comments
Good insights on .NET. I’m curious if it’s suitable for low-power devices.