.Net NanoFramework on a Cheap Yellow Display

I’ve been working with microcontrollers for some time now with a variety of different languages but mostly it has been C and Micropython. And across my career I’ve been working with an even wider range of languages but most recently I’ve been using .Net and C# and enjoying the platform.

So I’ve been on the lookout for a microcontroller that would support C# development. I’ve been aware of the Meadow range of boards from Wilderness labs but their boards are quite expensive with the Meadow F7v2 Feather currently being priced at £41. So when I saw the “cheap yellow display” my first thought was, I wonder if it can support .Net? So I did a web search for microcontrollers and dotNet and discovered the .Net nanoFramework and that supported the ESP32 which was the brains behind this board.

A small gellow board with a number of electronic components including an ESP32 wifi module and SDCard. A RGB LED is showing a blue light. Behind the board is a screen showing a simple piece of code to blink the LED.

Compiling the firmware from source

TLDR: You don’t need to do this.

I did try following the instructions for building the firmware using a dev container and this worked once I’d tidied up CMakePresets.json file which referenced some community builds that were not part of the nf-interpreter repo.

After successfully building an image for ESP32, I was looking for how to install it onto the board when I found the “Nanoff” or nanoFramework Firmware Flasher. Reading the documentation for this suggested that I could flash some “stock” images. So I tried this and it worked first time, so I abandoned the image I’d previously made.

Extensions

Once the board was flashed with some suitable image, I turned my focus to getting some code to compile. There are extensions for Visual Studio Code and for Visual Studio. I tried VS Code first and struggled to get the code to build. The tool was missing Nuget.exe which I installed but then the build process didn’t seem to like the samples I was trying.

So I swapped to Visual Studio and found the error messages and experience a bit more helpful. Apparently the sample was using older libraries than the firmware supported. So after updating all of these I got it to build and deploy. There’s an extra window to see and select the device. And it’s worth turning on the extra info to see what’s happening with the deploy. There’s also a tool to get the device capabilities which will show you what is installed in the firmware. There are a number of core libraries that are installed with the firmware, the rest are installed via package manager as for a regular .Net application.

You can also set breakpoints in the code and step through it line by line. Although I found that adding a few “Debug.Write” statements was also very useful.

Blink

Getting the blink example to work was pretty straight forward, I found the pins for the inbuild LED on CYD repo which I’d by this time discovered was created by Brian Lough (pronounced lock) who I knew for his simple but excellent “Power BLough-R” which lets data through a USB connection but not power. Anyway, the pin number for the CYD RGB LED were there in the schematics but also in the example code.

So after getting the basic blink to work, I ported the “LED Test” code to C#.

Display

Having got blink to work, I presumed that I was past all of my compilation and deployment issues. But this turned out not to be the case. My first problem was that the core display class was one of the libraries that is supplied by the firmware. So I was just about to head back to the dev container to compile a custom firmware, when I spotted that there was already a “ESP32_GenericDisplay_REV0” referenced in the repo for nf-interpreter. So I tried the Nanoff tool with the -target parameter to install that firmware on my board. Which after a reboot, then showed the display library when I inspected the hardware.

The other thing I needed to work out was what kind of display it was. Again Brian’s repo came to the rescue with both good samples and a configuration file showing all of the the pins for the display. It is a ILI9341 TFT display with backlight and SPI interface. These are popular with makers as they have a good size and resolution. Helpfully there was also a ILI9341 driver in the graphics repo for nanoFramework so I didn’t have to resort to reading the data sheet to send the right initialisation commands. To get the SPI bus configured the nanoFramework.Hardware.Esp32 library is needed as this allows the SetPinFunction to be used to configure the pins for the SPI bus.

Some of the samples drew coloured blocks on the display. I started with one of those as a base and eventually found the correct size and orientation settings.

Whilst experimenting, I managed to lock up the device a couple of times by reading beyond the end of an array and by allocating too much memory. The solution seems to be to press and hold reset then unplug and replug the hardware, you can then resend a new image which hopefully doesn’t lock up. I’d since discovered this was throwing an exception so it might be that these can be wrapped with a try catch block to avoid such problems.

But eventually I got the board to display my blocks in full screen.

For my project, I wanted to write some fonts to the screen, so I took at look at the “Primitives” samples. These all created a screen buffer as a bitmap and wrote to it. However when I tried this, I hit the out of memory exception again, so a different approach was required. In the M5Stack samples, I found the answer. There was a simple sample that used DisplayControl.Write with some text and a font file. The M5 boards are a more complete solution of an ESP32 and display and I would expect a similar approach to this one for the CYD would also work for these.

Given that I typically work on backend systems, I’ve not actually used a resource file for developing for many years, possibly going back as far as my final year uni project which was a battery charging test rig with a software UI for controlling it.

The resource file points to a font file which I just copied in from the M5 project. And it displayed on the screen but with a couple of key issues. Firstly the font size was a bit small and the carriage returns were not being correctly recognised. But most importantly, the font was mirrored.

After a lot of head scratching, I made a copy of the driver code and moved the MADCTL_MX entry from to OrientationLandscape. And to fix the CR issue. I simply broke my text into multiple segments and wrote each one out in a different position, using the font height from the M5 example to create my line spacing.

The fonts were loaded from the resource as a tinyfnt file. The samples reference the “Tiny Font Tool” which generates these tinyfnt files. It is possible to control which letters/numbers/symbols will be available to control the size of the file. So I created font files using different sizes and saw how those displayed on the display.

DisplayControl.Write also didn’t honour my colour encoding which was BGR rather than RGB so I wrote a little function to convert the colours.

Finally, I wanted to display a logo. So I tried creating a bitmap from a JPG resource of a 40×40 image. But that blew another memory exception. So I copied an idea I’d seen in a different sample and generated a byte array with my image using Image2CPP and a loop to draw the pixels to the screen one at once. This worked surprisingly well and unless you stepped through the code you couldn’t see it draw to the screen.

Case

Again Brian’s excellent repo has some great examples of cases. I took one that had a simple CYB logos and imported the STL files into FreeCAD. To make this editable needs a few steps but there are several youtube videos with examples. The only “gotcha” as that the refine shape menu is off a “copy” option in the current version of FreeCAD. After importing, I padded the logo to refill the holes and use the refine shape option again to close the gaps. I created my own logo as a small square so I could print that in a separate colour. I found the wall sizes of the case a little thin so on my printer this meant that parts could easily snap off. So if I was to reprint these I’d make the walls a little thicker. I only discovered this after a 5 hour print so not so keen on another revision.

What’s next

I’m afraid I can’t share the final result just yet as it is a surprise for some people. So once I’ve shipped the board then I’ll post some more details.

For the purpose of the project, I was working on, getting the display to work was sufficient. But there’s also a touch sensor on the screen so it might be good to get that operational. I’d also like to get my notes in order to send a PR back to Brian Lough and the CYD repo.

5 thoughts on “.Net NanoFramework on a Cheap Yellow Display

  1. Daniel says:

    Nice work!
    I have done about the same work as you have and Blinky is working. But DisplayControl.Initialize just hangs for me and nothing on the display…
    Would you consider pointing me in the right direction or sharing something soon :)

    const int backLightPin = 21;
    const int chipSelect = 15;
    const int dataCommand = 2;
    const int reset = -1;
    const int screenWidth = 320;
    const int screenHeight = 240;
    Configuration.SetPinFunction(12, DeviceFunction.SPI1_MISO);
    Configuration.SetPinFunction(13, DeviceFunction.SPI1_MOSI);
    Configuration.SetPinFunction(14, DeviceFunction.SPI1_CLOCK);
    DisplayControl.Initialize(new SpiConfiguration(1, chipSelect, dataCommand, reset, backLightPin), new ScreenConfiguration(0, 0, screenWidth, screenHeight));

Leave a Reply

Your email address will not be published. Required fields are marked *

 characters available