Skip to content

9. Embedded programing


Week assignment

  1. Compare the performance and development workflows for different microcontroller families (group).
  2. Read the datasheet for the microcontroller I’m programming (individually)
  3. Program the board I have made to do something, with as many different programming languages and programming environments as possible. (individually)

The basics

Syntax

Layout of the words and symbols that are use to create the code. These are the rules that we need to follow in order to make code that will run. Is how we put sense together so that we can comunicate.

Variable

It’s a container that holds a piece of information. There are different types of variables for different types of information and there are general variables that can hold a lot of different things.

int age = 14;

// 
int is the data type
age is the variable 
14 is the value

"int" data type means that the variable can only hold INTegers. 
"double" should be use if we have to store decimals and exponentials
"const" for varialbes that can not be changed
Rules for naming a variable

  • A variable name can only have alphabets, numbers, and the underscore _.
  • A variable name cannot begin with a number.
  • Variable names should not begin with an uppercase character.
  • A variable name cannot be a keyword. For example, int is a keyword that is used to denote integers.
Fundamental Data Types
Data Type Meaning Size (in Bytes) Example
int Integer 2 or 4 int age = 20;
float Floating-point 4 float area = 64.74;
double Double Floating-point 8 double volume = 134.64534;
char Character 1 char test = ‘h’;
wchar_t Wide Character 2 wchar_t test = L’ם’ //storing Hebrew character;
bool Boolean 1 bool cond = false; //has one of two possible values: true or false.
void Empty 0 cannot declare variables. It means “nothing” or “no value”.
Control Stucture

It’s a block that makes decisions based on variables or other conditions. It’s a way for the code to make decisions based on the current situation.

If (this){
do this thing
}
Data Stucture

How we store and organize our data. The most common are lists and arrays.

  • Array: It’s a list with some sort of identifier which lets us get to each item in the list.
    • The array indices start with 0. Meaning x[0] is the first element stored at index 0.
    • If the size of an array is n, the last element is stored at index (n-1).
    • Elements of an array have consecutive addresses.
Compiling

Turn the code into instructions that the computer can execute.

Function

Rehusable block of code that we can call from multimple places within the project. Functions act like a box. So, there’s code that runs inside and can only afects other things in that box unless we tell it otherwise. They can take outside input and return some sort of output. We can include an external file with functions in order to use them across wer project.

Libraries

A collection of many things that can be reuse from project to project.

Init

Setup of necessary elements that need to be in place before any code can run. This is where we need to name data structure or variables so that we can give them values in the code. All the things that the code will need to know should be declare here.

Arduino IDE basic Steps

  1. Download the latest version of Arduino IDE from Arduino website
  2. Go to Tools select the board
  3. Plug the board to the computer and go to Tools and select the port (conecting and dissconecting the board will help to understand which is the correct port)
Sketch

Code that we write to get sent to the board. Every sketch starts with two functions built into it that are empty.

  • Setup: Is run one time and it’s for setting up everything we’ll need in the project. Like, how we are going to use the pins (inputs/outputs).
  • Loop: It’s a loop that runs over and over.

Variables and data structure should be set above these two functions. So that they get defined before the set up is run.

Programming the board with Arduino

For this assignment I’m going to use the board I made on Electronics design week, which has an LED and a button. I’m going to start by turning on the LED when the button is pressed. It’s a basic example that shows an input (pressing the button) and how this will controll an output (LED that will turn on).

So, I started by taking a look at my board and the other ones (UPDI and FTDI) I made at the Electronics Production week. boards

Then, I looked for the datasheet of the microcontroller I used; ATtiny 1614.

What I’ve learned reading the microcontroller datasheet

Basically, I’ve learned that this microcontroller had a very small memory and that I didn’t have a lot of pins but it was going to be enough to try simple stuff.

  • Number of pins: 14
  • Memory: 16 KB
  • Clocks: 16 and 20 MHz.
  • Maximum voltage: 6V;

Another important thing was the position of the microcontroller. I didn’t know which pin was which until I realized that the microcontroller has a circle engraved on one corner. That circle is represented on the datasheet as a black circle.

datasheet

I used the pin map to understand the pin number I was using.

pinmap

schematic

Switch = PA5 = pin 1
LED = PA6 = pin 2

Fortunaltely, both pins are analog/digital. I only needed digital as it will be an on/off signal, so it’s fine.

My UPDI is on pin 11.

The connection of my board was done in this way: TDX = PB3 = Digital pin 4 (Which is RXD on the Attiny 1614) RXD = PB2 = Digital pin 5 (Which is TDX on the Attiny 1614)

RxD means Receive Data. TxD means Transmit Data. So, I mistakenly inverted this. The thing was that I’ve already uploaded a code during the Electronic Design week. So, I decided to try it this way and, in case it didn’t work, I would use an arduino nano insted.

In order to get the Attiny 1614 board in my Arduino IDE I followed this tutorial and installed the MegaTinyCore package.

/* Test 1
turn on a LED when the button is pressed
turn it off when the button is not pressed (or released)
*/
int pinButton = 1; //the pin where connected to the button
int LED = 2; //the pin connected to the LED

void setup() {
   Serial.begin(9600);
  pinMode(pinButton, INPUT); //set the button pin as INPUT
  pinMode(LED, OUTPUT); //set the LED pin as OUTPUT
}

void loop() {
  int stateButton = digitalRead(pinButton); //read the state of the button if it's press or not
  Serial.println(stateButton); // in order to understand which the values of the button 
  if(stateButton == 1) { //if is pressed
     digitalWrite(LED, HIGH); //write 1 or HIGH to led pin
  } else { //if not pressed
     digitalWrite(LED, LOW);  //write 0 or low to led pin
  }
}

With this code the LED is on all the time and it turns off when I press the button. So, I inverted LOW and HIGH.

/* Test 1
turn on a LED when the button is pressed
turn it off when the button is not pressed (or released)
*/
int pinButton = 1; //the pin where connected to the button
int LED = 2; //the pin connected to the LED

void setup() {
  Serial.begin(9600);
  pinMode(pinButton, INPUT); //set the button pin as INPUT
  pinMode(LED, OUTPUT); //set the LED pin as OUTPUT
}

void loop() {
  int stateButton = digitalRead(pinButton); //read the state of the button if it's press or not
  Serial.println(stateButton); // in order to understand which the values of the button 
  if(stateButton == 1) { //if is pressed
     digitalWrite(LED, LOW); //write 1 or HIGH to led pin
  } else { //if not pressed
     digitalWrite(LED, HIGH);  //write 0 or low to led pin
  }
}

I was struggling with Mac and Arduino IDE but after installing MegaTinyCore and rebooting the computer everything worked fine. megaTinyCore

Arduino + PyUPDI

I decided to try programming the board using Python. So, I did the following:

  1. Opened the terminal and write:
     python --version
    
    // and then
    
     pip install https://github.com/mraardvark/pyupdi/archive/master.zip
    
    but I got the following: -bash: pip: command not found

pip is a program that lets you install python packages

so I used this command to install pip

sudo easy_install pip

Then I tryed again with

pip install https://github.com/mraardvark/pyupdi/archive/master.zip
But it didn’t work because it requires Python 3. To instal it I typed:
brew install python

Then I entered

pip3 install https://github.com/mraardvark/pyupdi/archive/master.zip
And I installed the dependencies using
pip3 install intelhex pylint pyserial 
Last but not least I opened the Arduino IDE and clicked on export compile binary. The .hex file was saved in the project folder.

pyupdi lets you interact with the board, so I entered the following line to upload my code to the board.

test1_FL deniserey$ pyupdi -d tiny1614 -b 19200 -f test1_FL.ino.t1614.20c0.u5V.mD0.hex -c /dev/cu.usbserial-D30993IK 

python

I also tried using Microsoft MakeCode but I couldn’t find how to change the board. However, I found it even more intuitive that Sketch. I found really interesting the ‘advance’ option.

Programming my board with plain C

I used this tutorial to understand how to compile and generate the .hex file to upload to the controller.

First, I wrote th following code to blink the led on my board:

#define F_CPU 3333333
#include <avr/io.h>
#include <util/delay.h>

#define LED PIN6_bm // Define LED pin
#define DELAY 500 // Define waiting time

int main(){

    PORTA.DIR |= LED; // Define the led port as output

    while(1){
        PORTA.OUT |= LED; // LED ON
        _delay_ms(DELAY); // Wait half a second

        PORTA.OUT &= ~LED; //LED OFF
        _delay_ms(DELAY); // Wait half a second
    }

    return 0;
}

Then, I used the following line to compile the C code for the Attiny microcontroller:

avr-gcc -Wall -g  -Os -mmcu=attiny1614 -o main.bin main.c

This line generates the .hex file to upload the controller:

avr-objcopy -j .text -j .data -O ihex main.bin main.hex

Last but not least, this line uploads the code to the microcontroller:

python3 -u /megaTinyCore/hardware/megaavr/2.2.9/tools/prog.py -t uart -u /dev/cu.usbserial-A50285BI -d attiny1614 -v --fuses 2:0x02 6:0x04 8:0x00 -f ./main.hex -a write 

I’ve learned that to handle the states of the microcontroller is necessary to understand bitwise operations like PORTA.OUT |= LED; // LED ON I didn’t understand why this works this way and it made me appreciate that Arduino IDE exists.

Basics on how to choose a Microcontroller

  • Bits: The microcontrollers are available in different bit rates like 8-bit, 16-bit and 32-bit rates. The number of bits refers to size of data lines which limit the data. Most Arduino boards consist of an Atmel 8-bit AVR microcontroller. More bits mean better performance but are also more expensive and consume more energy.

  • Frequency: Speed at which the microcontroller will operate Clock-speed: This is something I that I had to configure when using Arduino IDE and basically is the rate at which the development boards process data. For example, Arduino Uno has a clock speed of 16 MHz. If the clock speed is higher that means it will perform better in time-sensitive or data-intensive applications. But, processors with higher clock speeds consume comparatively more power. If running the poject on battery, it’s recommended to aim for microcontrollers that have lower clock speeds.

  • Number of I/O pins : Required ports and pins thay we will use for the project.

  • RAM: All the variables and arrays declared(DATA) in most MCUs

  • Energy consumption and requirements: Working voltage of MCU such as 5V, 3.3V or Low voltage.

  • Memory: there are different types of memories but we use the flash memory when uploading the code to the microcontroller, so it’s basically where the Arduino sketch is stored. The size of the program is displayed after we upload the sketch in the program notification window at the bottom of the IDE. Then we have SRAM (static random access memory) is where the sketch creates and manipulates variables when it runs. This is the one I need to store the graphics. For example, each pixel requires just 3 bytes of SRAM to store the color. An Monochrome OLED Displays only require 1 byte for every 8 pixels, but due to their high resolution, there are still a lot of pixels! The 128x64 version requires 1K of SRAM. And then we have, EEPROM is memory space that programmers can use to store long-term information.

  • Comunication: A USART (Universal Synchronous/Asynchronous Receiver/Transmitter) is a microchip that facilitates communication through a computer’s serial port using the RS-232C protocol (RS-232 protocol is now widely used for connections between data acquisition devices and computer systems). Some attinys don’t have a hardware USART module, so you won’t be able to communicate with them via serial. I found this nice **Attiny_Chart

Compare two microcontroller families

For this part of the assignment, I decided to compare ESP 32 and Attiny1614. ATtiny are a subfamily of 8-bit AVR microcontrollers. The ESP32 is a series of System on Chip (SoC). They contain a Tensilica Xtensa LX6 microprocessor, WiFi, and integrated Bluetooth. It was developed to have low consumption and low cost

Specifications ESP 32 Attiny1614
Type 32 bit 8 bit
Data memory 4Mb 256b
ADC 18 10
GPIO 34 12
Flash Memory 16Mb 16Mb
SRAM 520kb 2 KB
f_CPU (max) 240MHz 20 MHz

Flash programming and debugging protocols:

  • Attiny1614 is programmed through the UPDI protocol, which is a protocol acting as a serial port on a single bi-directional wire. A reserved UPDI pin on the ATtiny will trigger a reset whenever the voltage is set to 0V.

  • There are 2 ways to program a ESP32; By using the serial port 0 or Over the Air (OTA). The OTA service handles the transfer and flashing of the ESP32, which means that the ESP32 will open a web socket when connected to the WiFi.

I followed these steps when programming the Barduino for Mechanical & Machine Design week.

Check Mechanical & Machine Design week for an example on how to program the ESP32.

Check Electronics design or an example on how to program the ATiny1614.

Tip

Throughout the process, one of the most important things I learned is that memory is key if we want to do anything with graphics, since they weigh a lot. But also, there are libraries that are already very heavy. That is why it is essential to prototype using breadboards and to pay attention to the weight of the libraries we use.

Personally, I learned that while the ESP32 is clearly more powerful than the ATtiny1614, the important thing is to understand the needs of the project. Because oversizing implies, for example, higher energy consumption. In other words, we are going to have to use a larger battery when perhaps using a smaller microcontroller we can save space and energy.


Last update: July 8, 2021