v1.
0
20220301
Embedded Systems and IoT
Ingegneria e Scienze Informatiche - UNIBO
a.a 2022/2023
Docente: Prof. Alessandro Ricci
[modulo-lab-1.1]
MICROCONTROLLERS
PROGRAMMING - ARDUINO/WIRING
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 1
OBJECTIVE
• This lab module provides a practical overview of main
aspects related to microcontroller programming, based
on Arduino and Wiring
• In particular:
– digital I/O
– output PWM
– analog input
– interrupt
– timer
– serial TTL
ESIOT ISI-LT - UNIBO MCU programming 2
ARDUINO - INTRO
• The Arduino project (https://en.wikipedia.org/wiki/Arduino)
– …The Arduino project began in 2005 as a tool for students at the Interaction Design Institute
Ivrea, Italy, aiming to provide a low-cost and easy way for novices and professionals to create
devices that interact with their environment using sensors and actuators...
…The Arduino project was started at the Interaction Design Institute Ivrea (IDII) in Ivrea, Italy.
[2] At that time, the students used a BASIC Stamp microcontroller at a cost of $50. In
2003 Hernando Barragán created the development platform Wiring as a Master's thesis
project at IDII, under the supervision of Massimo Banzi and Casey Reas. Casey Reas is
known for co-creating, with Ben Fry, the Processing development platform. The project goal
was to create simple, low cost tools for creating digital projects by non-engineers. The Wiring
platform consisted of a printed circuit board (PCB) with an ATmega128 microcontroller, an
IDE based on Processing and library functions to easily program the microcontroller.[4] In
2005, Massimo Banzi, with David Mellis, another IDII student, and David Cuartielles,
extended Wiring by adding support for the cheaper ATmega8 microcontroller. The new
project, forked from Wiring, was called Arduino.
– team: Massimo Banzi, David Cuartielles, Tom Igoe, Gianluca
Martino, e David Mellis
• Open-source
• hardware and software
• Makers vision - prototyping, tinkering, inventing
• Web site: http://arduino.cc
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 3
ARDUINO - TEAM (PRE 2015)
ESIOT ISI-LT - UNIBO MCU programming 4
IN LAB: ARDUINO UNO
ESIOT ISI-LT - UNIBO MCU programming 5
ARDUINO UNO
• Main components
– MCU ATMega 328P
• 8 bit, 16 MHz
• Flash memory: 32 KB
• SRAM memory: 2 KB, EEPROM: 1 KB
– 14 digital input/output pins
• 6 can be used as PWM output
– 6 analog input
– USB connector
– power jack Further specs
– ICSP header Operating voltage: 5V
Input voltage (recom.): 7-12 V
– reset button DC current per I/O pin: 40 mA
DC current per 3.3V: 50mA
ESIOT ISI-LT - UNIBO MCU programming 6
ARDUINO UNO
µC to convert serial TTL into USB
PC connection via USB
(power + serial)
Quartz oscillator for the
16 MHz clock
External power/batteries
(6-20 Volt)
Pins that provide the reference voltage for
circuits: GND, 5 V (3.3V also available)
ESIOT ISI-LT - UNIBO MCU programming 7
ARDUINO UNO
Onboard led, connected to pin 13
14 line strip connector => 14 GPIO pins
power on
led
reset
button
Led signalling TX and RX
activities (serial)
ICSP
connector
6 analog input strip connector
ESIOT ISI-LT - UNIBO MCU programming 8
PIN SPECS
• Digital pins 0..13
– nominal voltage: 5V
– can supply or draw current up to 40mA
• Analog input A0…A5
– nominal voltage: 5V
– 10-bit resolution
• 0-5 Volt value => converted by the ADC into a 10-bit
value [0..1023 (210-1) ]
• AREF pin (pin 21) makes it possible to change the
reference value (max value) for the ADC
ESIOT ISI-LT - UNIBO MCU programming 9
ESTERNAL POWER
• Through the PC via USB
• Through batteries or a power supply
– battery capacity depends on desired battery life, the current
drawn
– Esempio:
• estimated power consumption: di 150mA
• desired battery life: 8 hours
=> battery capacity >=150mA*8 = 1200mAh
ESIOT ISI-LT - UNIBO MCU programming 10
PROGRAMMING
• Reference framework used here: Wiring
– open-source framework for microcontrollers
• cross-platform, numerose piattaforme supportate - AVR
Xmega, AVR Tiny, TI MSP430, Microchip PIC24/32...
– based on GNU GCC, with a set of custom libraries
• C/C++ language
– AVR gcc tool chain - avr-gcc compiler
• libc customized to access and interact with the HW
– http://www.nongnu.org/avr-libc/
– large documentation and community
• http://wiring.org.co/learning/tutorials/
– link: http://arduino.cc/en/Reference/HomePage, http://
wiring.org.co/
• Directly supported by Arduino IDE
• Large set of available libraries
– https://www.arduino.cc/reference/en/libraries/
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 11
IDE AND TOOLS
• Every Integrated Development Environment is meant to be installed on some
host PC, connected to Arduino via USB
• Arduino IDE
– very simple and effective for small-size projects
– based on Wiring framework
– implemented in Java
– http://arduino.cc/en/Main/Software
• PlatformIO and Visual Studio Code
– for more complex projects
– PlatformIO - https://platformio.org/
– Visual Studio code: https://code.visualstudio.com/
• Arduino plugin extension to be installed
• PlatformIO extension
• Simulators/Emulators
– An open-source one: Tinkercad - https://www.tinkercad.com/
ESIOT ISI-LT - UNIBO MCU programming 12
ARDUINO IDE
ESIOT ISI-LT - UNIBO MCU programming 13
WIRING PROGRAM STRUCTURE:
• Wiring adopts the superloop as control architecture
• Two main procedures
– setup()
• instructions to be executed at the program boot, to
setup and configure the initial state
• executed once
– loop()
• body of the control loop
• executed repeatedly
ESIOT ISI-LT - UNIBO MCU programming 14
PROGRAM UPLOAD AND
EXECUTION
• Two ways to upload a program on Arduino
– directly by a connected PC, exploiting the bootloader preloaded
on the MCU
• http://arduino.cc/en/Tutorial/Bootloader
– using an external In-System Programmer device, that allows to
program the microcontroller through the ICSP (In-Circuit-Serial-
Programming) interface
• http://arduino.cc/en/Main/ArduinoISP
• We are going to used the first one.
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 15
BOOTING - DETAILS
• Once Arduino is reset (either through the button, or the pin, or
USB), the bootloader program is executed
• If the bootloader receives immediately a proper command by
the IDE (via serial), then it tries to upload the binary sent by
the IDE
– the binary (executable) is downloaded in memory (FLASH)
and then executed
– this occurs each time we select UPLOAD from the IDE => a
reset signal is sent to Arduino, starting then the upload
protocol
• If the bootloader does not receive any command, them the last
executable in memory is executed
ESIOT ISI-LT - UNIBO MCU programming 16
RUNTIME - MEMORY MAP
• Memory map made by the compiler avr-gcc / segments:
– .data (global vars), .bss (constants), heap, stack
• Note
– heap and stack grows in opposite directions
• can collide in the case of memory overflow
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 17
RUNTIME - MEMORY MAP
• Internal registers (including I/O, timer..) are mapped onto 0..0xFF
address space
– so the first useful memory address is 0x100 ($100) i.e. 256 and
the last is 0x8FF ($8FF) i.e. 2303 (256 + 2KiB)
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 18
LABWORK ENVIRONMENT SETUP
• Hardware
– host computer + Arduino UNO + cable
– basic electronic components
• breadboard
• resistors: 220 Ω, 1KΩ, 10 KΩ
• led, tactile button, potentiometer
• Software
– Arduino IDE
• framework Wiring
– to draw circuit parts:
• Tinkercad (open source)
• Eagle, Fritzing
• Shared instruments
– tester (multimeter)
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 19
MATERIAL: THE BREADBOARD
• Useful for creating circuits without soldering
– https://en.wikipedia.org/wiki/Breadboard
• Main points
– terminal strips - the main areas, to hold most of the electronic components.
• In the middle of a terminal strip of a breadboard, one typically finds a notch
running in parallel to the long side. The notch is to mark the centerline of the
terminal strip. The clips on the right and left of the notch are each connected in a
radial way; typically five clips (i.e., beneath five holes) in a row on each side of
the notch are electrically connected.
– Bus strips - To provide power to the electronic components
• connected horizontally
ESIOT ISI-LT - UNIBO MCU programming 20
JUMPERS
(male-male) (male-female)
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 21
WARNING
• Avoid short circuits
– short circuit = connection between 2 points of a circuit with
resistance zero and imposing an electric voltage to the ends > 0
=> ~infinite current (Ohm law)
– can burn components and Arduino as well
• Check the max current that be absorbed by a component
– too much current => damages
• Check the max current to be absorbed by a pin of the MCU
• Check the component polarity
– e.g. leds
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 22
FIRST ACTIVITY IN LAB
• step #0 - Empty
• step #1 - Blinking on-board led
• step #2 - Blinking external led
• step #3 - Fading
• step #4 - Button-Led
• step #5 - Tune
• step #6 - Counting
• step #7 - Even-driven blinking
• step #8 - Serial echo
• step #9 - Deep sleep
• step #10 - Light sleep with timers
ESIOT ISI-LT - UNIBO MCU programming 23
STEP #0 - “EMPTY"
• Description
– how to organise a project in multiple files
• Highlights
– discipline about .c/.cpp and .h content
• header files => only function/procedure signature
declaration and var declarations (not definitions)
• definitions/implementations only in .c/.cpp sources
ESIOT ISI-LT - UNIBO MCU programming 24
STEP #1 - “BLINKING INTERNAL LED”
• Description
– The system must blink the on-board led periodically, with a
1000 ms period
• Highlights
– digital I/O - output
• Wiring API
– pinMode, digitalWrite
– control loop
ESIOT ISI-LT - UNIBO MCU programming 25
STEP #1 - CODE
#define LED_PIN 13
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
delay(1000);
}
ESIOT ISI-LT - UNIBO MCU programming 26
SERIAL OUTPUT
• Exploiting the serial connection with the PC to send messages
that are displayed on PC window
– useful for logging e for debugging
• In Wiring: Serial library
– http://arduino.cc/en/reference/serial
– class Serial
• among the methods (static):
– begin
» to initialize a serial communication session,
specifying the baud rate
– print/println
» to send string messages
– write/read - per send/receive byte blocks
ESIOT ISI-LT - UNIBO MCU programming 27
SERIAL MONITOR
• Feature provided by Arduino IDE to
– visualise messages sent through the serial connection
– send messages as well
• It uses a configurable baud rate
– which must be the same used on the Arduino side
ESIOT ISI-LT - UNIBO MCU programming 28
BLINKING WITH SERIAL LOG
#define LED_PIN 13
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
Serial.println(“ON”);
delay(1000);
digitalWrite(LED_PIN, LOW);
Serial.println(“OFF”);
delay(1000);
}
ESIOT ISI-LT - UNIBO MCU programming 29
STEP #2 - “BLINKING EXT LED”
• Description
– system 1 external led. The system must blink the led
periodically, with a 1000 ms period
• HW
– led, 220 Ohm resistor
• Highlights
– HW
• led - polarità - anodo e catodo
– how to compute the resistance needed
ESIOT ISI-LT - UNIBO MCU programming 30
STEP #2 - BREADBOARD
ESIOT ISI-LT - UNIBO MCU programming 31
LED
• LED (Light Emitting Diode)
– optoelectronic devices — a diode that produces light when a current
passes through
– has a polarity
– https://en.wikipedia.org/wiki/Light-emitting_diode
• It has an operating voltage, that depends on the color
– esempi:
• green: 2.0 V
• red: 1.3 V
• Current consumption: 10..20 mA
ESIOT ISI-LT - UNIBO MCU programming 32
CALCOLO VALORE RESISTENZA
• E’ opportuno inserire una resistenza nel circuito per limitare la corrente che
fluisce nel LED, secondo le sue specifiche
– https://learn.adafruit.com/all-about-leds/the-led-datasheet
• Dal suo datasheet, sappiamo che il LED determina una caduta di potenziale
(chiamata Forward Voltage) di circa 2 Volt (tra 1.8 e 2.5 max)
• Quindi dei 5 Volt dell’alimentazione, rimangono 3 Volt (3 - 2) da far assorbire
alla nostra resistenza
• Sempre dai datasheet del LED, vediamo che il valore di corrente opportuno
per il funzionamento del LED (DC Forward Current) è 20 mA (30 mA max)
– questo valore di corrente è compatibile con la quantità di corrente che
può erogare Arduino da un pin di output (pari a 40 mA)
• Quindi, per la Legge di Ohm, il valore di resistenza da usare deve essere
non inferiore a: R = V / I = 3 / 0.02 = 150 Ohm
– maggiore è il valore, più fioca è la luce (poiché minore è la corrente)
– la resistenza disponibile sul mercato più vicina a 150 Ohm è quella da da
220 Ohm
• Il circuito funziona bene anche con resistenza fino ad 1 KOhm
ESIOT ISI-LT - UNIBO MCU programming 33
220 OHM RESISTOR
• Resistance bands to compute the value of resistance
– e.g. 4-bands resistors
• 220 Ohm => red-red-brown
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 34
STEP #3 - “FADING”
• Description
– system with a pulsing led, fading in and out
• HW
– led, 220 Ω resistor
• Highlights
– analog output and PWM
• pins marked with ~
– 3,5,6,9,10,11
– Wiring API
• analogWrite
ESIOT ISI-LT - UNIBO MCU programming 35
STEP #3 - BREADBOARD
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 36
STEP #3 - CODE
// one supporting PWM
#define LED_PIN 9
int fadeAmount;
int currIntensity;
void setup(){
currIntensity = 0;
fadeAmount = 5;
pinMode(LED_PIN, OUTPUT);
}
void loop(){
analogWrite(LED_PIN, currIntensity);
currIntensity = currIntensity + fadeAmount;
if (currIntensity == 0 || currIntensity == 255) {
fadeAmount = -fadeAmount ;
}
delay(20);
}
ESIOT ISI-LT - UNIBO MCU programming 37
STEP #4 - “BUTTON-LED”
• Description
– system with a tactile button + led. The led must be on
when the button is pressed and off when the button is
released
• HW
– led, 1 resistor 220 Ω, tactile button, 1 resistor 10 KΩ
• Highlights
– digital I/O - input e output
• Wiring API:
– digitalRead
– pull-down resistance
ESIOT ISI-LT - UNIBO MCU programming 38
STEP #4 - BREADBOARD
VCC
J1 S1
A0 D0
P$1 P$3
A1 D1
P$2 P$4
A2 D2
A3 *D3
VCC A4 D4
A5 *D5
*D6
IOREF D7
RESET D8
VIN *D9
5V *D10
3.3V *D11
AREF D12
GND D13
GND SDA
GND SCL
R2
R3
GREEN
VCC
MISO
D1
MOSI
SCK
RESET
GND
GND GND
GND ARDUINO_R3
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 39
PULL-DOWN RESISTOR
• pull-down resistor (10 KΩ) is used to make sure that — when the
button is not pressed — the voltage level on the input pin would be
LOW
– “pull-down” because the signal is forced to LOW (GND)
– “pull-up” instead => forced to HIGH (VCC)
• Big resistance value (es: 10 KΩ)
– to minimise the current that flows in that part of the circuit
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 40
STEP #4 - CODE
#define BUTTON_PIN 2
#define LED_PIN 13
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT);
Serial.begin(9600);
}
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState == HIGH) {
digitalWrite(LED_PIN, HIGH);
Serial.println(“ON”);
} else {
digitalWrite(LED_PIN, LOW);
Serial.println(“OFF”);
}
}
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 41
ABOUT POLLING
• The approach used here to detect the button pressed is
based on polling
– periodical read of the state of the pin
• Problem
– if the button is pressed too fast, it could happen that it
is not detected..
ESIOT ISI-LT - UNIBO MCU programming 42
STEP #5 - “TUNE”
• Description
– system characterised by a potentiometer. It must log in
output the current value of the potenziometer
• HW
– a potentiometer
• Highlights
– analog pin reading
– Wiring API
• analogRead
ESIOT ISI-LT - UNIBO MCU programming 43
STEP #5 - BREADBOARD
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 44
STEP #5 - CODE
#define POT_PIN A0
int current;
void setup() {
Serial.begin(9600);
}
void loop() {
int newValue = analogRead(POT_PIN);
if (newValue != current){
current = newValue;
Serial.println(current);
}
}
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 45
STEP #6 - “COUNTING”
• Description
– system that visualizes a count, which is incremented
each time a button is pressed
• HW
– a tactile button, a 10 KΩ resistor
• Highlights
– interrupt
• Problems
– bouncing problem
– concurrency problems
ESIOT ISI-LT - UNIBO MCU programming 46
STEP #6 - BREADBOARD
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 47
STEP #6 - CODE
#define BUTTON_PIN 2
volatile int count = 0;
int prev = 0;
void setup(){
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), inc, RISING);
}
void loop(){
noInterrupts();
int current = count;
interrupts();
if (current != prev){
Serial.println(current);
prev = current;
}
}
void inc(){
count++;
}
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 48
BOUNCING PROBLEM
• Bouncing - physical phenomenon affecting tactile buttons
• when pressed, there could be multiple internal mechanical
rebounds before stabilising (in some milliseconds)
• These rebounds can generate a sequence of spurious interrupts
• the counter is incremented more than 1 time
• Solutions (at the code level):
• we can solve the problem by ignoring all the impulses that arrive
shortly after the first one (e.g. 20-30 milliseconds)
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 49
ATOMICITY/CRITICAL SECTIONS
• In the control loop, the assignment of the count variable (that could
be concurrently accessed by the interrupt handler too) must be
atomic, i.e. should not be interruptible — to avoid race conditions
– critical section
• To this purpose we can disable (and reenable) interrupts
– noInterrupts()/interrupts()
• When interrupts are disabled, the MCU does is not reactive to
external events (that are lost) => we should minimise the period of
time in which interrupts are disabled
– short-time interrupt handlers
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 50
FURTHER REMARKS
• Not all increments are printed…
• The reason is that logging is done asynchronously with
respect to increment => there could be more than one
increment between two logs
ESIOT ISI-LT - UNIBO MCU programming 51
STEP #7 - EVENT-DRIVEN BLINKING
• Description
– blinking the led by means of timer interrupts
• HW
– led, 220 Ohm resistor
• Highlights
– timer, library Timer1
• https://www.arduino.cc/reference/en/libraries/
timerone/
– how to install a library on the IDE
ESIOT ISI-LT - UNIBO MCU programming 52
STEP #7 - CODE
#include "TimerOne.h"
#define LED_PIN 13
boolean flagState = false;
void blinky(){
if (!flagState){
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
flagState = !flagState;
}
void setup()
{
pinMode(LED_PIN,OUTPUT);
/* set period timer 1000000 usec = 1 sec */
Timer1.initialize(1000000);
Timer1.attachInterrupt(blinky);
}
void loop(){}
ESIOT ISI-LT - UNIBO MCU programming 53
STEP #8 - “SERIAL ECHO”
• Description
– reading messages sent from the serial line and send
them back
• Highlights
– library Serial
ESIOT ISI-LT - UNIBO MCU programming 54
STEP #8 - CODE
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available()){
char data = Serial.read();
Serial.print(data);
}
}
ESIOT ISI-LT - UNIBO MCU programming 55
STEP #9 - DEEP SLEEP
• Description
– testing sleep modes for lowpower consumption
• HW
– tactile button and 10 KΩ resistor
• Highlights
– events that break the sleep and trigger restarting
– time needed to restart
ESIOT ISI-LT - UNIBO MCU programming 56
STEP #9 - SCHEMA
ESIOT ISI-LT - UNIBO Programmazione Base Arduino 57
STEP #9 - CODE
#include <avr/sleep.h>
void wakeUp(){}
void setup(){
Serial.begin(9600);
pinMode(2,INPUT);
attachInterrupt(digitalPinToInterrupt(2), wakeUp, RISING);
}
void loop(){
Serial.println("GOING IN POWER DOWN IN 1s ...");
Serial.flush();
delay(1000);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
/** The program will continue from here. **/
Serial.println("WAKE UP");
/* First thing to do is disable sleep. */
sleep_disable();
}
ESIOT ISI-LT - UNIBO MCU programming 58
STEP #10 - LIGHT SLEEP + TIMER
• Description
– testing light sleep mode in which timers go on working
• Highlights
– disabling selectively the components that are not
needed
– useful approach for implementing schedulers (future
modules)
ESIOT ISI-LT - UNIBO MCU programming 59
STEP #10 - CODE
#include <avr/sleep.h>
#include <avr/power.h>
#include "Timer.h"
Timer* timer;
void setup(){
Serial.begin(9600); void loop(){
timer = new Timer(); /* timer 1 */ Serial.println("GOING IN SLEEP");
timer->setupPeriod(5000); Serial.flush();
} sleep();
Serial.println("WOKE UP");
void sleep(void) }
{
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
power_adc_disable();
power_spi_disable();
power_timer0_disable(); // only timer 1
power_timer2_disable(); // on
power_twi_disable();
sleep_mode();
/* back */
sleep_disable();
power_all_enable();
}
ESIOT ISI-LT - UNIBO MCU programming 60