Week 4 Embedded Programming
This page documents the group assignment for week 04 of Högni, Jóhannes and Ólöf.
- Demonstrate and compare the toolchains and development workflows for available embedded architectures
- Document your work to the group work page and reflect on your individual page what you learned
Glossary
This week's projects include words/concepts that are new to us and we decided to explain a few of them for better understanding.
Architecture of an embedded system
-
Means the abstract structure of interacting elements of an embedded system (both hardware and software).
Embedded Systems Architecture; Noergaard, Tammy 2005 Architecture of microprocessors
-
Microcontrollers use either HARVARD or VON-NEUMANN architecture, which describes how the processor exchanges data with the memory. Harvard architecture (RISC) is what is used in modern microcontrollers. It allows a higher speed compared to the VON-NEUMANN architecture (CISC).
Philadelphia University Bootloader
-
A small programm on a separate storage area of a microcontroller, that enables the microcontroller to receive a new program.
Proteus Core
-
Enables the compatibility of a type of microcontroller with the IDE.
Arduino Documentation Embedded System
-
An applied computer system with limited hardware and/or software functionality and designed for a specific function and high reliability.
Embedded Systems Architecture; Noergaard, Tammy 2005 IDE
-
An integrated development environment (IDE) is a software application that provides comprehensive facilities for software development.
Wikipedia Library
-
Package containing code / functions that are ready-to-use for a certain purpose.
Digikey Package
- Defines the size and mounting type of an electronical component.
Wikipedia Processor
-
An electrical components that performs an operation on an external data source.
Wikipedia Toolchains
-
All the tools that are used together, and form a chain or sequence, to transform a code into an operating firmware.
Machines that Make Word size
-
The number of bits a processor can process in a single cycle. (usually 8, 16, 32 or 64 bits).
Ktpql
ATtiny412
The ATtiny412 microcontroller with an 8-bit AVR processor that can run up to 20MHz and has a 256B memory. Information on ATtiny on DigiKey.
Datasheet and pinout
Datasheet and pinout
Datasheet and pinout for ATtiny412 here. The image below is a screenshot from the datasheet.
More abot the pins on ATtiny412
This screenshot below is taken from Spence Konde and it shows well the function of each pin.
To understand the pins better I looked at how Adrián Torres explained the pins according to these screeshots above. Adrián Torres lists the pins this way:
VDD: Supply voltage
GND: Ground
Digital pins: PA0, PA1, PA2, PA3, PA4, PA5, PA6 = 7 pins.
Analog pins: PA1, PA2, PA3, PA4, PA5, PA6 = 6 pins.
UPDI Programming pins: PA0 (Physical pin nr. 6).
External Clock Pin: PA3
Adrián Torres also mentiones that all I/O pins can be configured with internal pullup resistance. He also defines which pins can use USART/SPI/TWI communications, but since they have pins in common, they cannot use different communications at the same time:
USART - Universal Synchronous and Asynchronous Receiver and Transmitter: RX(PA1) and TX(PA2).
SPI - Serial Peripheral Interface: MOSI(PA1), MISO(PA2) and SCK(PA3).
TWI - Two Wire Interface (12C): SDA(PA1) and SCL(PA2).
Programming the ATtiny
Ólöf programmed the ATtiny in Pre-Fab. You can read more about it here and here below is how it went:
Andri Sæmundsson made a series of videos for Fab Lab Reykjavík, where he explaines all the steps in producing a circuit board with ATtiny412. I followed his directions and here I describe how I programmed the ATtiny412.
Programming the ATtiny412 - video
Here Andri Sæmundsson explaines how to program ATtiny 412 - video.
In the Arduino IDE app I clicked on Tools, Board and then Board manager. Then I wrote megatinycore in the upper left window and chose Install. Then I clicked on Tools, Board and then megaTinyCore and then ATtiny412. After that I clicked on Tools, Programmer and then SerialUPDI SLOW: 57600 baud.
I used C++ in the Arduino IDE app. I created a new sketch. According to the pinout datasheet for ATtiny412 and the PCB board design the LED is on pin 4 and the button is on pin 0. Therefore I began by defining that the LED was on pin 4 and the button on pin 0 in Arduino by writing #define LED 4 and in the next line below #define BUTTON 0. When // is added in front of text, the computer ignores it. That way you can use text to explain what is going to happen in each step.
Here you can see how I followed the instructions from Andri (added some explanations myself) and wrote this code:
//Defining which pin to use for LED and button
#define LED 4
#define BUTTON 0
//Variable to keep track of how many button presses
uint8_t buttonPresses = 0;
//Defining what is input and what is output or input and pullup
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
}
//Creating a loop that follows a pattern and then repeats itself
void loop() {
//Defining what happens if button is pressed
if (digitalRead(BUTTON) == HIGH) {
//Increment buttonPresses
buttonPresses++;
//If buttonPresses is greater than 4, reset it to 0
if (buttonPresses > 4) {
buttonPresses = 0;
}
// Blink LED based on buttonPresses count
for (uint8_t i = 0; 1 <buttonPresses; i++) {
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
delay(200);
}
// Wait for button to be released
while (digitalRead(BUTTON) == HIGH) {
}
}
}
Arduino IDE interface
Here you can see what the Arduino IDE interface looks like. When you've written the code, you click on the checkmark on the left to compile the code. You have to make sure that you choose the right port. Then you click on the arrow to upload the code.
To connect the board to a computer I needed a serial UPDi-3 pin, and Svavar Konráðsson told us that it was designed by prof. Neil Gershenfeld. I also needed a FTDI cord (USB to TTL Serial Cable) to make a connection from the pins on the board to USB on the computer.
By clicking on Tools and Port I could see a list of ports. Then I connected the cord to the computer and checked out which port had beed added to this list. That was the port that I wanted to use, so I clicked on it.
I clicked on Sketch and Upload using programmer. Everything worked except that the LED blinked constantly, as can be seen in the video below. The code was obviously not correct.
Video of ATtiny - mistake in code
Constant blinking - ATtiny412
Þórarinn Bjartur Breiðfjörð advised me to change the time of the delay from 200 to 2000. That way it was easier to see how the LED was behaving. Then I took a better look at the code and saw that in one place I had written the number 1 instead of the letter i. I fixed that and then everything worked as it should.
This is the new code that I fixed:
//Defining which pin to use for LED and button
#define LED 4
#define BUTTON 0
//Variable to keep track of how many button presses
uint8_t buttonPresses = 0;
//Defining what is input and what is output or input and pullup
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
}
//Creating a loop that follows a pattern and then repeats itself
void loop() {
//Defining what happens if button is pressed
if (digitalRead(BUTTON) == HIGH) {
// Increment buttonPresses
buttonPresses++;
//If buttonPresses is greater than 4, reset it to 0
if (buttonPresses > 4) {
buttonPresses = 0;
}
// Blink LED based on buttonPresses count
for (uint8_t i = 0; i < buttonPresses; i++) {
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
delay(200);
}
// Wait for button to be released
while (digitalRead(BUTTON) == HIGH) {
}
}
}
Video of ATtiny blinking a LED
ATtiny412
ESP32-S3
The ESP32-S3 is a modern microcontroller by Espressif with a dual-core 32 bit processor running at 240 MHz. It includes connectivity via Wifi and Bluetooth (including BLE) and has 512 kB SRAM memory. There are 45 GPIO pins on the chip and many different peripherals are supported including UART, SPI, PWM, ADC, PulseCounter, Touch Sensor and LCD/Camera Interface.
The supply voltage used by the chip is 3,3 V and it supports four different power modes for energy-saving applications.
It has two ULP coprocessors (RISC-V and FSM) and one of them can be active during sleep mode at a time.
The current draw in deep-sleep can be as low as 7 µA.
The programming can be done via the USB-Port, so there is no other hardware required.
Datasheet and Pinout
Here is a link to the ESP32-S3 Datasheet and below is a diagram showing the pinout of the chip.
Programming
For testing programming the ESP32-S3 we got a development board from Waveshare. It connects via USB-C to the computer.
We demonstrate two ways of programming the ESP32-S3. One is using the C++ and VSCode and the other is using Micropython and Thonny.
Below is a simple visualization of two possible toolchains (but there are of course many more).
C++ / VSCode
For VSCode (and also Arduino IDE) there is a good tutorial on the Waveshare website.
In VSCode you need to install the ESD-IDF extension. Then you can create a new project and choose an example program or template if you like.
It didn't work in the first place, because we added the example project into the GIT repository of this site. That seemed to create some conflicts, so when trying again in another location of the c-drive it worked without any issues.
We selected the hello-world example, but before being able to compile the program and send it to the microcontroller some configurations needed to be made.
Note
Select UART as Flash Method, the appropriate COM-Port (COM11 in our case) and the right chip type, before clicking on Build, Flash and Monitor.
The example is written in C++ and is located in the main folder of the project named hello_world_main.c.
As you can see in the terminal the microcontroller sends a "Hello world!" and identifies itself, before counting to 10 s and restarting the program.
The example code looks like this:
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
void app_main(void)
{
printf("Hello world!\n");
/* Print chip information */
esp_chip_info_t chip_info;
uint32_t flash_size;
esp_chip_info(&chip_info);
printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
CONFIG_IDF_TARGET,
chip_info.cores,
(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
(chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");
unsigned major_rev = chip_info.revision / 100;
unsigned minor_rev = chip_info.revision % 100;
printf("silicon revision v%d.%d, ", major_rev, minor_rev);
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
printf("Get flash size failed");
return;
}
printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
for (int i = 10; i >= 0; i--) {
printf("Restarting in %d seconds...\n", i);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
printf("Restarting now.\n");
fflush(stdout);
esp_restart();
}
Micropython / Thonny
For using Micropython, the Thonny application was recommended.
We found a good tutorial on how to programm the ESP32 with Thonny.
First you install Thonny.
Then you need to install the correct firmware on the ESP32-S3 to enable it to understand Micropython, which can be downloaded here as a *.bin file.
Select and install the firmware using Options - Interpreter in Thonny.
This takes some minutes to finish, but once done, you should be able to talk to the ESP32-S3 with Micropython.
Let's try sending help()
in the Shell. It works!
Now let's make the onboard LED blink. But how to address the RGB LED? It's not just a simple Pin.OUT
.
We found this site explaining the NeoPixel module in Micropython and adapted the code to make a loop and have the LED blink.
Also we know, that the RGB LED is connected to GPIO 38. To make a loop with a 0,5 s delay, we then also need to import the time library.
from machine import Pin
import time
from neopixel import NeoPixel
pin = Pin(38, Pin.OUT) # set GPIO38 to output to drive NeoPixels
np = NeoPixel(pin, 1) # create NeoPixel driver on GPIO38 for 1 LED/pixel
for i in range(60):
np[0] = (255, 255, 255) # set the LED to white
np.write() # write data to LED
time.sleep(0.5)
np[0] = (0, 0, 0) # set the LED to off
np.write() # write data to LED
time.sleep(0.5)
That works as well!
Raspberry Pi Pico
Information and pinout datasheet for Raspberry Pi Pico here.
Datasheet for Raspberry Pi Pico here.
Datasheet for RP2040 here.
One of the tasks was to get a program physically into the microcontroller and I was able to do that using the Raspberry Pi Pico. I connected it to my computer using a USB A port connected to USB C on the Raspberry Pi Pico.
was able to turn on the built in LED by using the following program that I found here
from machine import Pin import time
ATmega328P
The Arduino Uno board is no longer in Fab Lab Inventory, but this board can be helpful when trying things out. That is why we added ATmega328P and the Arduino Uno board to this comparison. Here are some basic information on the Arduino Uno board. The Arduino Uno board is based on the ATmega328P microcontroller with 6 analog inputs and 14 digital input/output pins. Amongst those pins are 6 pins that can be used as PWM outputs. It can be connected to a computer through a USB A/B cable.
Datasheet and pinout for ATmega328P
Datasheet and pinout for ATmega328P here. The screenshot below is from the datasheet.
Datasheet and pinout for Arduino Uno
Information and pinout datasheet for Arduino Uno here. The screenshot below is from the datasheet.
Programming the Arduino Uno board
Switching between boards
Here The Arduino IDE was used to program the Arduino Uno board the same way that the ATtiny412 was programmed. When switching between microcontrollers you have to change the settings in Arduino IDE by choosing Tools, Board and then click on the Arduino Uno.
The same code was used as was used to program the ATtiny412:
//Defining which pin to use for LED and button
#define LED 4
#define BUTTON 0
//Variable to keep track of how many button presses
uint8_t buttonPresses = 0;
//Defining what is input and what is output or input and pullup
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
}
//Creating a loop that follows a pattern and then repeats itself
void loop() {
//Defining what happens if button is pressed
if (digitalRead(BUTTON) == HIGH) {
// Increment buttonPresses
buttonPresses++;
//If buttonPresses is greater than 4, reset it to 0
if (buttonPresses > 4) {
buttonPresses = 0;
}
// Blink LED based on buttonPresses count
for (uint8_t i = 0; i < buttonPresses; i++) {
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
delay(200);
}
// Wait for button to be released
while (digitalRead(BUTTON) == HIGH) {
}
}
}
Arduino Uno/Arduino IDE - video
ATmega328P-Arduino Uno with Arduino IDE
Arduino Uno/VSCode/PlatformIO
We wanted to try more toolchains. Jeffery Naranjo used the PlatformIO extension in Visual Studio Code to program an Arduino Uno. This tutorial on the Digikey site explains the first steps in using the PlatformIO. This site is also a good guide. To be quite sure how everything worked, this video was also used as a step by step guidance. In the video all steps are explained, from installing Visual Studio Code, installing Python and installing the PlatformIO extension. Since both VS Code and Python were installed, I jumped over these steps.
Under extensions in Visual Studio Code the PlatformIO extension was chosen and installed. This took a few minutes.
Note
When you click on the device button you can see the devices and the port they are connected to.
Note
When you create a new project or update an older project, you give it a name and choose the right board.
Note
When you begin working on a sketch you click on Libraries, src (source directory) and then click on the file main.cpp. This is the file you edit to create a sketch. The PlatformIO uses the .cpp ending and it stands for C++.
VSCode/PlatformIO - video
ATmega328P-Arduino Uno with Platformio in Visual Studio Code
Two toolchains for Arduino Uno
After using two different platforms to program the Arduino Uno it was possible to compare these two. I (Ólöf) found it difficult to understand exactly what to define as a part of a toolchain. Þórarinn Bjartur Breiðfjörð pointed out this video that expains Toolchains in Arduino. It helped me to understand and I decided to make this flowchart with explanations, based on this video.
Finding the toolchain in PlatformIO
It was not easy to find information about the toolchain in PlatformIO. I googled "how can you see which compiler is used in platformio" and found this answer. As you can see, the information should be defined like this:
Note
I began searching by clicking every file that I could see, but did not find what I was looking for. It was frustrating so I took a break. Then I searched again and I noticed how the window did not always show the whole text. I used the bar under the window in a json file to scroll to the right and found it!
Note
You can see that it uses the AVR-GCC compiler, just as the Arduino IDE does. After GCC in the line you can see AVR, so it uses the AVR Downloader/Uploader. Then it uses the bootloader that is already pre-installed as a program in the Arduino Uno. To my surprise, the toolchains were the same, except for the platform where you create your code. I used this this video that expains Toolchains in Arduino as a guidance when I created this flowchart. The flowchart was made in Canva.
Comparison of the microcontrollers used
We saw the group project site at FabLab Reykjavík here and got inspired to make a comparison table for the different microcontrollers.
ATtiny412 | RP 2040 | ATmega328P | ESP32-S3 | |
---|---|---|---|---|
Price | $ 0,58 | $ 14 | $ 2,89 | $ 1,85 |
Architecture/Family | Harvard, AVR® RISC | Harvard ARM | Harvard, AVR® RISC | Harvard, ULP-RISC-V, ULP-FSM |
Physical Size | 5 mm x 6 mm | 21 mm x 51 mm x 3,9 mm | 7 mm x 7 mm | 7 mm x 7 mm |
Operating Voltage | 1,8 V ~ 5,5 V | 1,8 V - 5,5 V | 2,7 V ~ 5,5 V | 3,3 V |
Word size | 8 bit | 32 bit | 8 bit | 32 bit |
Clock speed | 16 and 20 MHz | 133 MHz | 16 MHz | 240 MHz |
Number of Processor cores | 1 | 2 | 1 | 2 |
Flash memory | 4 kB | 2 MB | 32 kB | external |
RAM | 256 B | 264 kB | 2048 B | 512 kB |
No of digital Pins | 7 | 40 | 20 | 45 physical, uses multiplexer |
No of analog Pins | 6 | 3 | 6 | 20 ADC channels |
Peripherals | Brown-out Detect/Reset, POR, WDT | USB, UART, I2C, SPI,PWM,Timer, Watchdog,RTC, ADMa and Temp Sensor, SSI | Brown-out Detect/Reset, POR, PWM, WDT | ADC, RTC, GPT, I2C, I2S, LCD, LEDC, MCPWM, PCNT, RMT, SD, SPI, Temp Sensor, Touch Sensor, TWAI, UART, USB |
Connectivity | I2C, IrDA, LINbus, SPI, UART/USART | Wifi, Bluetooth, BLE, UART, USB | ||
Programming languages | C,C++, Assembly | C/C++/Micropython, Assembly, Rust | C,C++, Assembly | C/C++, Micropython, Lua, ... |