Stephen Smith's Blog

Musings on Machine Learning…

Archive for the ‘Microcontrollers’ Category

Assembly Language Tutorial Three for MagPi Magazine

leave a comment »

Assembly Language Tutorial Three for MagPi Magazine

I’m in the process of writing a series of Assembly Language tutorials for MagPi Magazine. The third one appeared in issue #118 on page 52.

The PDF version of the magazine is free to download, but MagPi always appreciates any donations.

This article looks at writing Assembly Language code for the Raspberry Pi Pico. The Pico is Raspberry’s entry into the microcontroller market and includes a dual core ARM-M0+ CPU. This CPU runs ARM’s thumb instruction set, a subset of the full ARM 32-bit instruction set. This article shows how to create a project, include Assembly Language source code and then run or debug the program on the Raspberry Pi Pico.

This tutorial can only give so much detail. If you want more detail, you can always consider my book RP2040 Assembly Language Programming.

Written by smist08

May 26, 2022 at 1:51 pm

RP2040 Assembly Language Programming

with 13 comments

Introduction

My third book on ARM Assembly Language programming has recently started shipping from Apress/Springer, just in time for Christmas. This one is “RP2040 Assembly Language Programming” and goes into detail on how to program Raspberry’s RP2040 SoC. This chip is used in the Raspberry Pi Pico along with boards from several other manufacturers such as Seeed Studios, AdaFruit, Arduino and Pimoroni.

Flavours of ARM Assembly Language

ARM has ambitions to provide CPUs from the cheapest microcontrollers costing less than a dollar all the way up to supercomputers costing millions of dollars. Along the road to this, there are now three distinct flavours of ARM Assembly Language:

  1. A Series 32-bit
  2. M Series 32-bit
  3. 64-bit

Let’s look at each of these in turn.

A Series 32-bit

For A Series, each instruction is 32-bits in length and as the processors have evolved they added features to support virtual memory, advanced security and other features to support advanced operating systems like Linux, iOS and Android. This is the Assembly Language used in 32-bit phones, tablets and the Raspberry Pi OS. This is covered in my book “Raspberry Pi Assembly Language Programming”.

M Series 32-bit

The full A series instruction set didn’t work well in microcontroller environments. Using 32-bits for each instruction was considered wasteful as well as supporting all the features for advanced operating systems made the CPUs too expensive. To solve the memory problem, ARM introduced a mode to A series 32-bit where each instruction was 16-bits, this saved memory, but the processors were still too expensive. When ARM introduced their M series, or microcontroller processors, they made this 16-bit instruction format the native format and removed most of the advanced operating system features. The RP2040 SoC used in the Raspberry Pi Pico is one of these M Series CPUs using dual core ARM Cortex M0+ CPUs. This is the subject of my current book “RP2040 Assembly Language Programming”.

64-bit

Like Intel and AMD, ARM made the transition from 32-bit to 64-bit processors. As part of this they cleaned up the instruction set, added registers and created a third variant of ARM Assembly Language. iOS and Android are now fully 64-bit and you can run 64-bit versions of Linux on newer Raspberry Pis. The ARM 64-bit instruction set is the topic of my book: “Programming with 64-Bit ARM Assembly Language”.

ARM 64-bit CPUs can run the 32-bit instruction set, and then the M series instruction set is a subset of the A series 32-bit instruction set. Each one is a full featured rich instruction set and deserves a book of its own. If you want to learn all three, I recommend buying all three of my books.

More Than ARM CPUs

The RP2040 is a System on a Chip (SoC), it includes the two M-series ARM CPU cores; but, it also includes many built in hardware interfaces, memory and other components. RP2040 boards don’t need much beyond the RP2040 chip besides a method to interface other components.

“RP2040 Assembly Language Programming” includes coverage of how to use the various hardware registers to control the built-in hardware controllers, as well as the innovative Programmable I/O (PIO) hardware coprocessors. These PIO coprocessors have their own Assembly Language and are capable of some very sophisticated communications protocols, even VGA.

Where to Buy

“RP2040 Assembly Language Programming” is available from most booksellers including:

Currently if you search for “RP2040” in books on any of these sites, my book comes up first.

Summary

The Raspberry Pi Pico and the RP2040 chip aren’t the first ARM M-series based microcontrollers, but with their release, suddenly the popularity and acceptance of ARM processors in the microcontroller space has exploded. The instruction set for ARM’s M-series processors is simple, clean and a great example of a RISC instruction set. Whether you are into more advanced microcontroller applications or learning Assembly Language for the first time, this is a great place to start.

Written by smist08

November 5, 2021 at 10:42 am

Playing with the Wio Terminal’s Grove Connectors

leave a comment »

Introduction

When I first reviewed Seeed Studio’s Wio Terminal, I didn’t have any Grove devices to make use of its two Grove connector ports. Since then I received a Seeed Studio Raspberry Pi Pico Grove Starter Kit and that provided me with 13 Grove devices to play with.

The Wio Terminal exposes a standard Raspberry Pi 40 pin header on its back, but some of these leads are wired to two Grove ports on the bottom of the terminal. This gives you one I2C grove port and another port that can be used as either a digital or analy port. There is no UART grove port, but you can use one of them for PWM which isn’t standard but can be configured. If you are using both the 40-pin connector and the Grove ports, then you need to be careful to avoid conflicts, as these are all wired up to the same pins in the SoC.

In this article, I’ll connect the mini PIR (Passive Infra-Red) motion sensor to the digital port. We use the Wio Terminal’s built in display to indicate whether movement is detected or not. The Wio Terminal is nice, in that you don’t need to use another port to connect a display.

Connecting it Up

 The PIR sensor plugs into the right Grove port, which is the one that supports general digital or analog devices. Below is a picture of this in action.

The sensor is quite sensitive, in this case it’s showing the motion of my cell phone taking the picture. At first I didn’t think it was working, since it kept indicating movement, until I realized it was sitting on the table and picking up the vibrations as I typed. To work well, the PIR sensor needs to be secure, so it doesn’t vibrate or move, otherwise it will report on movement of the sensor rather than objects in the room. This sensor works best for objects about two meters away. If you want something for your yard you might consider the Seeed’s non-mini PIR motion sensor. This sensor is good if you want a motion sensitive halloween display to scare the neighborhood kids, motion activated XMas displays or notification if someone comes right up to your door.

The Code

For this project, I’m using Arduino, since I find that environment is the best one for the Wio Terminal. Accessing the PIR motion sensor is easy, it sets the digital pin high if motion is detected and low if nothing is happening. This doesn’t require any special libraries or classes, being such a simple device. Notice the definition of D0, which is used to specify the primary digital pin in the Grove connector, or you could use the pin number which is 13 in this case. This is documented on the Wio Terminal wiki.

For the Wio’s display we use the TFT library like we did in our first impressions article, except we are displaying text rather than graphics. When I first coded this, the flashing was terrible, but after a bit of research on Seeed’s wiki, I discovered I needed to use a sprite to avoid the flashing. With the sprite you do all the drawing to the sprite and then update the display in one quick pushSprite statement. The TFT library for the Wio Terminal is quite powerful, but lacks a good technical reference, so you have to look at the code, or at least the TFT_eSPI.h header file which is quite long, or watch through some tutorial videos. The tutorials have a lot of good information, but are quite long, making them a bit time consuming to refer back to. 

#define PIR_MOTION_SENSOR D0
#include"TFT_eSPI.h"
TFT_eSPI tft;
TFT_eSprite spr = TFT_eSprite(&tft);
void setup()
{
    tft.begin();
    tft.setRotation(3);
    spr.createSprite(TFT_HEIGHT, TFT_WIDTH);
    spr.setTextColor(TFT_WHITE);
    spr.setTextSize(2);
    pinMode(PIR_MOTION_SENSOR, INPUT);
}
void loop()
{
    spr.fillSprite(TFT_BLACK);
    if(digitalRead(PIR_MOTION_SENSOR))//if it detects the moving people?
    {
             spr.drawString("Movement detected", 30, 60);
    }
    else
    {
         spr.drawString("Watching", 30, 60);
    }
    spr.pushSprite(0,0);
    delay(200);
}

Summary

The Wio Terminal is a great way to play in the Arduino world without requiring any soldering or breadboarding. The terminal has lots of useful built-in functionality, and allows you to easily connect up sensors and devices in a plug and play manner. This is great for the classroom where you might not want to supervise a large group of kids playing with soldering irons. The mini PIR sensor was fun to play with and getting the Arduino code working was easy. I find I get projects up and running much quicker with the Wio Terminal, since there is a lot built in, and I don’t get wiring problems, since the Grove connectors have been reliable.

Written by smist08

October 15, 2021 at 11:14 am

Playing with the Seeed Studio Grove Starter Kit for the Raspberry Pi Pico

with 3 comments

Introduction

Seeed Studios sent me one of their Grove Starter Kits for the Raspberry Pi Pico to review. The goal of this kit is to make working with microcontrollers accessible for educational purposes. No soldering is required, everything snaps together and away you go. This starter kit comes with a carrier board for the Raspberry Pi Pico (sold separately), a number of connector cables and a selection of devices you can connect up.

What is Grove?

Grove is a standardized connector to allow you to connect devices to a microcontroller using a standard cable using four wires. This is similar to how you can connect devices to your laptop via USB cables. Modern microcontrollers like the various Arduino boards and the Raspberry Pi Pico have pins for multiple communications protocols as well as some general purpose digital and analog connections. The Grove connectors standardize how to wire up a number of these including:

  1. UART for standard serial communications
  2. I2C for synchronous serial communications
  3. Digital includes a wire for power, ground and primary and secondary digital signals
  4. Analog includes a wire for power, ground and primary and secondary analog signals

Seeed manufactures carrier boards for several common microcontroller boards. In this case the Raspberry Pi Pico.

The Raspberry Pi Pico fits into the inside pins in the two rows of pin receptors. You can use the outside rows to bypass the Grove connectors and wire the Pico to a breadboard as normal. The Grove ports provide three analog ports, three digital ports, two UARTs and two I2C. There are also breakouts for SPI and debug. Note that the Raspberry Pi Pico I have doesn’t have headers for the debug ports, so doesn’t make use of the debug receptors on this carrier. If you want to avoid soldering altogether, you need to purchase a Pico with pre-soldered headers such as this one.

The carrier board doesn’t have any active components, the PCB routes the pins on the Pico to the correct parts of each Grove connector. 

If you are familiar with the Raspberry Pi Pico, you might know that most of the pins have multiple functions so you can make maximum use of the various pins. The Grove configuration is hardwired for one configuration and if you want to do something different then you need to connect to a breadboard or do some soldering. However, the Grove ecosystem provides lots of devices to connect up here and if you are living in the Grove world then this isn’t a problem.

Sample Program

Seeed’s web page to introduce the Starter Kit has lots of sample projects and I thought as a quick test, I’d wire up the temperature and humidity sensor along with the two line LCD display, I ran into an immediate problem that the sample project on the website was for a different LCD display than included in the kit. However modifying the code for the correct LCD display was fairly easy, mostly looking at one of the other sample projects. I suspect the components might be swapped in and out as supply and demand changes and the web site has trouble keeping up to date.

The direct support for Grove is via MicroPython, with Seeed promising to support Arduino C support sometime soon. You could program this with the RP2040 SDK, since there is direct support for all these devices, but the emphasis here is on educational settings and MicroPython. You need to have the Raspberry Pi Pico connected to a host computer via a micro-USB cable, I used my Windows 10 laptop for this. You write your program in the Thonny Python IDE, which has good support for the Pico, including installing the MicroPython runtime. The Pico version of MicroPython has good low level device support for the RP2040, which means it already knows how to talk to I2C, UARTs, digital and analog devices. Seeed provides MicroPython classes that provide a higher level interface to the various Grove devices included in the starter kit. Below is the source code for reading the temperature and humidity and displaying it on the LCD. The lcd1602.py and dht11.py files are the high level Python classes that Seeed provides for the LCD and digital humidity/temperature sensor.

from lcd1602 import LCD1602
from dht11 import *
from machine import Pin, I2C
from time import sleep

i2c = I2C(1,scl=Pin(7), sda=Pin(6), freq=400000)
d = LCD1602(i2c, 2, 16)
dht2 = DHT(18) #temperature and humidity sensor connect to D18 port

while True:  
    temp,humid = dht2.readTempHumid() #temp:  humid:
    d.home()
    d.print(“Temp:  ” + str(temp)) #display temperature on line 1
    d.setCursor(0, 1)
    d.print(“Humid: ” + str(humid))
    sleep(0.5)

To get this project going, you connect the devices, using the Grove connector cables, enter this small Python program and away you go. Who knew building a microprocessor project and programming it could be so easy?

Summary

Building and programming microprocessor projects can be intimidating, involving soldering small fiddly wires and then writing programs in C and Assembly Language. Seeed simplifies this process by replacing soldering with simple standard connectors and then combines this with simplifying MicroPython high level classes to make the programming simpler. For learning and prototyping DIY projects this is great. This opens the educational potential to younger children, where you might be scared to give them a soldering iron. Further, you are less likely to get parts broken or lost. The Raspberry Pi Pico with its powerful RP2040 CPU runs MicroPython effortlessly and there is plenty of memory for quite large projects.

Written by smist08

October 12, 2021 at 10:08 am

ARM’s True RISC Processors

leave a comment »

Introduction

I recently completed my book, “RP2040 Assembly Language Programming” and was thinking about the differences in the three main instruction sets available on ARM Processors:

  1. The “thumb” instructions used in ARM’s 32-bit microcontrollers are covered in “RP2040 Assembly Language Programming”.
  2. The full 32-bit A-series instruction set as used by the Raspberry Pi OS is covered in my book “Raspberry Pi Assembly Language Programming”.
  3. The 64-bit instruction set used on all smartphones and tablets covered in my book “Programming with 64-Bit ARM Assembly Language”.

ARM is advertised as Reduced Instruction Set Computer (RISC) as opposed to Intel x86 chips which are Complex Instruction Set Computers (CISC). However, as ARM instroduces v9 of their full chip architecture, the instruction set has gotten pretty complex. Writing the RP2040 book and writing the included source code was nice in that the microcontroller version of the instruction set really is reduced and much simpler than the other two full versions. In this article, we’ll look at a bit of history of the various ARM instruction sets and why ARM is still considered a RISC processor.

A Bit of History

Originally, ARM was developed as a replacement to the 6502 processor used in the BBC Microcomputer, developed by Acorn. The early versions were specialty chips and it wasn’t until ARM was selected by Apple to use ARM in their Newton PDAs that ARM was spun off as a separate company starting with their 32-bit RISC CPUs. They reached the next level of success as Apple continued to use them in their iPods and then they hit it big when they were used in the iPhone and after that pretty much every smartphone and tablet that reached any level of success.

The original 32-bit instruction set used 32-bits to contain each machine instruction, which worked great as long as you had sufficient memory. In the microcontroller world there were complaints that for devices with only 4k of memory, these instructions were too big. To answer this, ARM added “thumb” instructions which were 16-bits in length, using half the memory of hte full instructions. The processor was still 32-bits, since the registers were 32-bits in size and all integer arithmetic was 32-bit. The “thumb” instruction set is a subset of the full 32-bit instruction set and the processor can switch between regular and thumb mode on select branch instructions. This allowed the microcontroller people to use the “thumb” subset to develop compact applications for their use. Even on computers with larger memory, “thumb” instructions can be useful since loading 16-bit instructions means you can load two instructions for each memory read and save contention on the memory bus and allowing twice as many instructions to fit in the instruction cache, improving performance.

The first “thumb” instruction set wasn’t complete which meant programs had to revert to full instructions to complete a number of functions. To address this ARM developed “thumb-2” to allow complete functionality without switching back. The various “thumb” instruction sets are all 32-bit, the 64-bit version of the ARM instruction set has no “thumb” subset.

Enter Microcontrollers

ARM has alway had the ambition to provide CPU chips covering the whole market from inexpensive small microcontrollers all the way up to the most powerful datacenter server chips. The full 32-bit ARM processors were a bit too expensive and complicated for the microcontroller market. To address this market, ARM developed the M-series CPUs where they chose to make the full instruction set of these devices, the “thumb” instruction set. This made these CPUs far simpler and required fewer transistors to create. This laid the way for powerful ARM 32-bit CPUs for the microcontroller market costing under $1 each.

For instance, the ARM Cortex-M0+ used in the Raspberry Pi Pico has 85 instructions. This sounds like a lot, but it counts things like adding a register to a register different from adding an immediate operand to a register. This is far fewer instructions than in an ARM full A-series processor, which is far fewer than the instructions in an x86 processor.

Some of the features that are dropped from the M-series processors are:

  • Virtual memory
  • Hardware memory protection
  • Virtualization
  • Conditional instructions
  • Not all instructions can address all the registers
  • Immediate operands are much smaller and shifting isn’t supported
  • The addressing modes are far simpler
  • Instructions either set or don’t set the conditional flags, there is no extra bit to control this

Most microcontrollers run a single program that has access to all the memory, so these aren’t an issue. However, the lack of hardware hasn’t stopped people adding software support and implementing Linux and other OS’s running on these microcontrollers.

Are ARM Processors Still RISC?

A full ARM A-Series processor like those found in the Raspberry Pi, Apple’s iPhone 7 iPad along with dozens of Android and ChromeOS devices, all run the full 64-bit instruction set, as well as the full 32-bit instruction set including the “thumb” instruction. They support virtual memory, virtualization, FPUs, vector processors, advanced security and everything else you would expect in a modern processor. That is a lot for something that is billed as “reduced”. Basically an ARM CPU has the same transistor budget as an x86 processor, so they use every transistor to do something useful. So why are ARM processors still considered RISC? The parts of RISC that all ARM processors retain is:

  • The instructions are a fixed length.
  • They are a load/store architecture (no instructions like add memory to register). An instruction either loads/stores from memory or performs an arithmetic operation on the registers.
  • Most instructions execute in a single clock cycle.
  • They have a large set of registers, though Intel processors now also have a large set of registers.

Even with all this functionality, ARM processors use far less power than x86 processors, this is mainly due to the simplifications that fixed length instructions and a load/store architecture provide. Intel processor now execute a RISC processor at their core, but then have to add another layer to translate each x86 instruction into their internal RISC instructions, that all uses transistors and power when executing,

So yes, even though the number of instructions in an ARM CPU has multiplied greatly over the nine generations of the chips, the core ideas are still RISC.

Summary

The line of M-series ARM CPUs are far simpler to program than the full A-Series. There is no virtual memory support, so you can access hardware addresses directly, reading and writing anywhere without worries about security or memory protection. The instruction set is simpler and nothing is wasted. Having written three books on ARM Assembly Language Programming, I think learning Assembly Language for a microcontroller is a great way to start. You have full control of the hardware and don’t have to worry about interacting with an operating system. I think you get a much better feel for how the hardware works as well as a real feel for programming for RISC based processors. If you are interested in this, I hope you check out my forthcoming book: “RP2040 Assembly Language Programming”.

Written by smist08

October 2, 2021 at 10:31 am

ArduPy on the Wio Terminal

with one comment

Introduction

Last week, we introduced Seeed Studio’s Wio Terminal and wrote a small program in C using the Arduino IDE. This week, we’ll replicate the same program in Python using ArduPy, Seeed’s version of MicroPython for the Wio Terminal and Seeeduino XIAO. In this article we’ll look at what’s involved in working with ArduPy along with some of its features and limitations.

The Koch Snowflake in ArduPy on the Wio Terminal

What is ArduPy?

ArduPy is an open source adaptation of MicroPython that uses the Arduino API to talk to the underlying device. The goal is to make adding MicroPython support easier for hardware manufacturers, so that if you develop Arduino support for your device, then you get MicroPython support for free. There are a large number of great microcontrollers out there and for board and system manufacturers, and the most time consuming part of getting a new board to market is developing the SDK. Further, great boards run the risk of failing in the market if the software support isn’t there. Similarly, a programmer buying a new board, really likes to be able to use familiar software and not to have to learn a whole new SDK and development system from scratch.

When you develop an Arduino program, you include the libraries used and the program then runs on the device. In the case of ArduPy, the Python runtime is the running Arduino program, but what libraries does it contain? Seeed developed a utility, aip, to rebuild the ArduPy runtime and include additional libraries. This lets you save memory by not including a bunch of libraries you aren’t using, but still have the ability to find and include the libraries you need.

The downside of ArduPy is that currently there isn’t Python IDE integration. As a partial workaround there is REPL support (Read Evaluate Print Loop), which lets you see the output of print statements and execute statements in isolation.

You need to flash the ArduPy runtime to the device, after that the device will boot with a shared drive that you can save a file boot.py that is run everytime the device boots, or main.py which is run every time it is saved.

Our Koch Snowflake Program Again

We described the Koch Snowflake last time and implemented it in C. The following is a Python program, where I took the C program and edited the syntax into shape for Python. I left in a print statement so we can see the output in REPL. The screenshot above shows the program running.

from machine import LCD
import math

lcd = LCD()                            # Initialize LCD and turn the backlight
lcd.fillScreen(lcd.color.BLACK)        # Fill the LCD screen with color black
lcd.setTextSize(2)                     # Setting font size to 2
lcd.setTextColor(lcd.color.GREEN)      # Setting test color to Green

turtleX = 0.0
turtleY = 0.0
turtleHeading = 0.0

DEG2RAD = 0.0174532925

level = 3
size = 200
turtleX = 320/8
turtleY = 240/4

def KochSnowflakeSide(level, size):
  print(“KochSnowFlakeSide ” + str(level) + ” ” + str(size))
  if level == 0:
      forward( size )
  else:
      KochSnowflakeSide( level-1, size / 3 )
      turn( 60 )
      KochSnowflakeSide( level-1, size / 3)
      turn( -120 )
      KochSnowflakeSide( level-1, size / 3)
      turn(60)
      KochSnowflakeSide( level-1, size / 3)

def forward(amount):
  global turtleX, turtleY

  newX = turtleX + math.cos(turtleHeading * DEG2RAD) * amount
  newY = turtleY + math.sin(turtleHeading * DEG2RAD) * amount
  lcd.drawLine(int(turtleX), int(turtleY), int(newX), int(newY), lcd.color.WHITE)
  turtleX = newX
  turtleY = newY

def turn(degrees):
  global turtleHeading
  turtleHeading += degrees

turn( 60 )
KochSnowflakeSide( level , size)
turn( -120 )
KochSnowflakeSide( level, size)
turn( -120 )
KochSnowflakeSide( level, size)
turn( 180 )

Developing and Debugging

Seeed’s instructions are good on how to set up a Wio Terminal for ArduPy, but die out a bit on how to actually develop programs for it. Fortunately, they have a good set of video tutorials that are necessary to watch. I didn’t see the tutorials until after I got my program working, and they would have saved me a fair bit of time.

I started by developing my program in a text editor and then saving it as main.py on the Wio. The program did nothing. I copied the program to Thonny, a Python IDE, which reported the most blatant syntax errors that I fixed. I started debugging by outputting strings to the Wio screen, which showed me how far the program ran before hitting an error. Repeating this, I got the program working. Then I found the video tutorials.

The key is to use REPL, which is accessed via a serial port simulated on the USB connection to your host computer. The tutorial recommended using putty, which I did from my Raspberry Pi. With this you can see the output from print statements and you can execute Python commands. Below is a screenshot of running the program with the included print statement.

I tried copy and pasting the entire Python program into putty/REPL, but copy/paste doesn’t work well in putty and it messes up all the indentation, which is crucial for any Python program. When I write my next ArduPy program, I’m going to find a better terminal program than putty, crucially, one where cut/paste works properly.

Using putty/REPL isn’t as good as debugging in a proper Python IDE, but I found I was able to get my work done, and after all we are programming a microcontroller here, not a full featured laptop.

Summary

ArduPy is an interesting take on MicroPython. The library support for the Wio Terminal is good and it does seem to work. Being able to use an IDE would be nice, but you can get by with REPL. Most people find learning Python easier than learning C, and I think this is a good fit for anyone approaching microcontrollers without any prior programming experience.

Written by smist08

September 3, 2021 at 10:45 am

Wio Terminal First Impressions

with 5 comments

Introduction

I received a Seeed Studio Wio Terminal, an interesting device that contains an Arduino style microcontroller, but packaged with a 320×240 2.4” color screen, buttons, bluetooth, WiFi, microphone, buzzer, microSD card slot, light sensor and infrared emitter. The packaging means you can work with it, without any soldering or breadboarding. It also has two Grove ports and Raspberry Pi compatible 40-pin GPIO pins.

It is built around a ATSAMD51 microcontroller containing a 32-bit ARM Cortex-M4 processor with a Floating Point Unit (FPU), running at 120 MHz. For memory there is 192KB RAM and 4MB flash.

To program the Wio Terminal, the current options are:

  1. Arduino – Use the Arduino IDE and supplied libraries for the integrated devices.
  2. MicroPython – There is a special MicroPython build for device support.
  3. Codecraft’s TinkerGen cloud development which includes TinyML support.

In this article we’ll look at the Arduino support and a simple fractal program to see what is involved. Below is a picture of the Wio Terminal with our fractal Koch snowflake. The screen is better than shown, as there was some interference between my phone’s shutterspeed and the screen refresh rate.

Koch Snowflake on a Wio Terminal

Koch Snowflakes

Koch snowflakes are simple fractals that are a good way to give an idea of how fractals can build complexity out of simplicity. Basically you start with a base shape, in this case a triangle, then you replace each line segment with a new shape, in this case the two lines with a “v” in the middle. Then you do this recursively to get more and more complicated shapes. Below is the progression from level 0, the base shape to level 1, with the base shape lines replaced by the fractal generator and then so on as the level increases.

This is a fractal because in the limit as the level goes to infinity, the shape has a fractal dimension, in that it is somewhere between 1 dimensional and 2 dimensional in a defined mathematical sense.

Turtle Graphics

To me the easiest way to draw fractals is with a turtle graphics library. This is a simple drawing library where you tell a turtle to either turn or move forwards. As he moves he leaves a trail. Hence the base shape for the Koch snowflake is forward 1, turn 60, forward 1, turn -120, forward 1, turn 60 forward 1. This is then really easy to apply recursively to draw fractals.

Programming the Wio Terminal

Drawing Koch snowflakes on the Wio Terminal turned out to be quite easy. The TFT graphics library Seeed Studio provides is quite good and makes programming easy with routines for lines, colors, text, basic shapes, all the way up to higher level objects like histograms. 320×240 may not seem like much resolution by today’s 4k standards, but remember this is about the same as CGA graphics on the original IBM PCs. Besides initialization, the only routine we used is drawLine. The Wio Terminal came with a USB-C to USB cable to connect the device to a regular computer. You program in the Arduino IDE on your PC and download the result to the WIo Terminal to run.

Below is the complete source code to draw the Koch snowflake.

#include”TFT_eSPI.h”

TFT_eSPI tft;
float turtleX;
float turtleY;
float turtleHeading = 0;

void setup() {
  int level = 3;
  int size = 200;
  tft.begin();
  tft.fillScreen(TFT_WHITE);

  turtleX = 320/10;
  turtleY = 240/2;

  turn( 60 );
  KockSnowflakeSide( level , size);
  turn( -120 );
  KockSnowflakeSide( level, size);
  turn( -120 );
  KockSnowflakeSide( level, size);
  turn( 180 );
}

void KockSnowflakeSide(int level, int size)
{
  if (level == 0)
  {
      forward( size );
  }
  else
  {
      KockSnowflakeSide( level – 1, size / 3 );
      turn( 60 );
      KockSnowflakeSide( level-1, size / 3);
      turn( -120 );
      KockSnowflakeSide( level-1, size / 3);
      turn(60);
      KockSnowflakeSide( level-1, size / 3);
  }
}

void forward(float amount) {
  float newX = turtleX + cos(radians(turtleHeading)) * amount;
  float newY = turtleY + sin(radians(turtleHeading)) * amount;

  tft.drawLine(turtleX, turtleY, newX, newY, TFT_BLACK);
  turtleX = newX;
  turtleY = newY;
}

void turn(float degrees) {
  turtleHeading += degrees;
}

void loop() {
}

I spent most of my professional career as a C programmer, and I really like the Arduino environment. I think learning to program in C is a great skill for any programmer or prospective programmer. It is a great starting point to getting into more technical areas like programming microcontrollers using the GNU GCC tools and all the various low level SDKs you are likely to encounter.

Summary

The Wio Terminal is a great way to get into learning about microcontrollers without needing to know soldering or electronics. The Grove system lets you connect all sorts of sensors to the Wio Terminal using standard cables. The screen is good enough to display things like weather station data and the buttons can be used to build simple UIs.

Programming the Wio using the Arduino IDE works well. The provided board and device support are great, making programming the device easy. C programming has its pitfalls and a novice programmer might want to start with MicroPython first, but learning C is worthwhile. The processor is powerful enough for most applications and having an FPU is a nice bonus.

Overall the Wio Terminal is an interesting entry in the microcontroller world, trying to remove the intimidation and difficulty of learning electronics, but still allowing you to learn programming and construct many of the same DIY projects. Seeed Studio’s website contains many tutorials and suggestions for projects. This would be great in a classroom setting, since you don’t need to police youngsters risking burning themselves with improper care while soldering. The price runs at around $37 which makes it accessible to most people and price competitive against Arduino starter kits.

Written by smist08

August 30, 2021 at 11:43 am