L'intervento di Paolo Paolucci durante l'Arduino Day, che si è tenuto il 29 marzo 2014 presso il FabLab Sardegna Ricerche, nella sede di Pula del Parco scientifico e tecnologico della Sardegna.
“Cogenerazione ad alto rendimento: opportunità per le PMI e la PA, aggiorname...
Il cuore di Arduino: Un sistema di sviluppo basato su microcontrollore Atmel AVR - Paolo Paolucci
1. Un sistema di sviluppo basato su
microcontrollore Atmel AVR
PaoloP
http://forum.arduino.cc/index.php?action=profile;u=58300
2. Argomenti
Architettura generale dei microcontrollori
Ambiente di sviluppo integrato
Caratteristiche e elementi di Arduino UNO
Principali caratteristiche del ATmega328P
Concetti di porte e pin del microcontrollore
Istruzioni per comandare i pin del microcontrollore
7. Cos’è Arduino?
Piattaforma di sviluppo open source
Open Source Hardware
Open Source Software
Economica e facilmente reperibile
Espandibile tramite «shield»
12. Prima di Arduino…
Computer
• Software
• Eclipse
• AVR Studio 4
•Porte
• Serial
• Parallel
• USB
Programmatore
• Interfaccia
• JTAG/ICE
• ISP
•Programmatore
• Bit-Bang
• ICSP
• AVRISP Mk II
Microcontrollore
• Versione
•DIP
•SOIC
•QFN
•Funzioni
•ADC/DAC
•PWM
•USB
13. Arduino Uno R3
LED
Connettore
USB
Jack Alimentazione
Connettori Pin DigitaliPulsante di Riavvio
Microcontrollore
AVR
ATmega328P
Connettori Pin Analogici
Connettori alimentazione
Convertitore
USB-Seriale
14. Arduino IDE (integrated development environment)
L'ambiente di sviluppo integrato
Arduino rende semplice la scrittura
di codice e caricarlo sulla scheda.
Funziona su Windows, Mac OS X e
Linux.
L'ambiente è scritto in Java e basato
su Processing, avr-gcc e altri software
open source.
15. Il linguaggio di Arduino
Linguaggio C/C++
Sintassi semplificata da funzioni di supporto alla programmazione
Astrazione dei nomi dei pin, passaggio ai numeri
Facile da imparare e potente
Facilità di riutilizzo del codice C per altri progetti
Librerie scritte in C/C++
Moltissimo codice di esempio (Tutorial – Playground)
Moltissime librerie già pronte (GitHub – GoogleCode)
16. Parole chiave del C
auto double int struct
break else long switch
case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while
17. Le funzioni di Arduino
Digital I/O
pinMode()
digitalWrite()
digitalRead()
Analog I/O
analogReference()
analogRead()
analogWrite() - PWM
Due only
analogReadResolution()
analogWriteResolution()
Advanced I/O
tone()
noTone()
shiftOut()
shiftIn()
pulseIn()
Time
millis()
micros()
delay()
delayMicroseconds()
Math
min()
max()
abs()
constrain()
map()
pow()
sqrt()
Trigonometry
sin()
cos()
tan()
Random Numbers
randomSeed()
random()
Bits and Bytes
lowByte()
highByte()
bitRead()
bitWrite()
bitSet()
bitClear()
bit()
External Interrupts
attachInterrupt()
detachInterrupt()
Interrupts
interrupts()
noInterrupts()
Communication
Serial
Stream
USB (Leonardo and Due only)
Keyboard
Mouse
18. http://it.wikipedia.org/wiki/Microcontrollore
Microcontrollore
In elettronica digitale il microcontrollore o microcontroller o MCU (MicroController
Unit) è un dispositivo elettronico integrato su singolo chip, nato come evoluzione
alternativa al Microprocessore ed utilizzato generalmente in sistemi embedded ovvero
per applicazioni specifiche di controllo digitale.
ANALOG
INPUTS
19. AVR
Sviluppati da Atmel nel 1996
Famiglia di Microcontrollori RISC
(reduced instruction set computer)
Istruzioni a lunghezza fissa, accesso alla memoria di tipo load-store con
32 registri general-purpose
Pipeline a due stadi per velocizzare l’esecuzione
Esecuzione della maggior parte delle istruzioni in un solo ciclo di clock
Fino a 12 volte più veloce di una architettura standard CISC
Architettura Harvard
22. AVR
Memoria Flash programmabile, RAM, EEPROM interne
Sistema di programmazione interno (ISP)
Varietà di periferiche: I/O digitali, ADC, Timer, UART, RTC timer, pulse width
modulator (PWM)…
Funzionamento fino a 20MHz
Ampia gamma di tensioni di funzionamento: da 1.8 V a 6.0 V.
Package variabile da 8 pin fino a 64 pin
Famiglie
ATtiny25-45-85, ATtiny24-44-84, ATtiny2313-4313 ...
ATmega88, ATmega168, ATmega328P ...
26. Tensione di lavoro dei pin
I Microcontrollori sono fondamentalmente dei dispositivi digitali dove
l’informazione è ‘codificata’ in due stati discreti:
HIGH or LOW (stato logici: 1 oppure 0)
Tensioni
5 V (per HIGH)
0 V (per LOW)
3.3 V (per HIGH)
0 V (per LOW)
28. Porte e Pin del Microcontrollore
Costituiscono il canale di
comunicazione del flusso di
informazioni da e per il
microcontrollore
Es. PORTB
• Pins PB0 – PB7
• Possono non essere contigui
• Spesso sono bidirezionali
34. Direzione dei dati nelle Porte e Pin
Input
Quando si prendono le informazioni dal mondo esterno (sensori)
verso la MCU
Output
Quando si invia un segnale per cambiare lo stato di un qualcosa di
esterno alla MCU (accendere o spegnere un led, un motore, etc.)
all’accensione o al Reset i pin sono impostati di default come input
da programma è possibile cambiare la direzione e lo stato dei pin in
qualsiasi momento
ogni porta I/O ha associati dei registri di memoria
35. Registri di memoria I/O
SREG: Status Register
SP: Stack Pointer Register
GIMSK: General Interrupt Mask Register
GIFR: General Interrupt Flag Register
MCUCR: MCU General Control Register
MCUSR: MCU Status Register
TCNTO: Timer/Counter 0 Register
TCCR0A: Timer/Counter 0 Control Register A
TCCR0B: Timer/Counter 0 Control Register B
OCR0A: Timer/Counter 0 Output Compare
Register A
OCR0B: Timer/Counter 0 Output Compare
Register B
TIMSK0: Timer/Counter 0 Interrupt Mask
Register
TIFR0: Timer/Counter 0 Interrupt Flag Register
EEAR: EEPROM Address Register
• EEDR: EEPROM Data Register
• EECR: EEPROM Control Register
• PORTB: PortB Data Register
• DDRB: PortB Data Direction Register
• PINB: Input Pins on PortB
• PORTD: PortD Data Register
• DDRD: PortD Data Direction Register
• PIND: Input Pins on PortD
• SPI I/O Data Register
• SPI Status Register
• SPI Control Register
• UART I/O Data Register
• UART Status Register
• UART Control Register
• UART Baud Rate Register
• ACSR: Analog Comparator Control and Status
Register
Nell'architettura dei calcolatori un registro è una piccola parte di memoria utilizzata per velocizzare l'esecuzione dei programmi fornendo un accesso
rapido ai valori usati più frequentemente, tipicamente, i valori correntemente in uso in una determinata parte di un calcolo. La maggior parte delle
moderne architetture dei computer (RISC, o più genericamente "architetture load-store") è basata su un'architettura a pipeline che trae beneficio dal
limitare l'accesso in memoria alle sole istruzioni load e store, utilizzando soltanto registri e costanti per l'esecuzione di tutte le altre istruzioni.
36. Registri della Porta B
PORTB: PortB Data Register
DDRB: PortB Data Direction Register
PINB: Pins Input on PortB
Bit 7 6 5 4 3 2 1 0
Bit 7 6 5 4 3 2 1 0
Bit 7 6 5 4 3 2 1 0
37. Registri di una Porta
Ciascuna Porta I/O ha associati 3 registri:
1. DDRx (dove “x” è A, B, C…)
Data Direction Register Port x
Determina quali pin della porta sono input (0) e quali sono output (1)
DDRB = 0x02; /* imposta il secondo pin della porta B come output” */
2. PORTx
Port Driver Register
PORTB = 0x02; /* imposta il secondo pin della porta a livello alto e azzera gli altri */
3. PINx
Port Pins Registers
Legge contemporaneamente lo stato di tutti e 8 i pin della porta
unsigned short int x;
x = PINB; /* Scrive lo stato della porta B nella variabile x */
39. Struttura di UNO sketch
Un programma su Arduino == ‘sketch’
Deve obbligatoriamente avere:
setup()
loop()
setup()
Configura il modo dei pin
loop()
Corpo principale del programma
impostato come ciclo infinito
Come un while(1) {…}
Dov’è la funzione main() ?
/* Blink
Turns on an LED on for one second, then off for one
second, repeatedly.
This example code is in the public domain.
*/
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is
the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by
making the voltage LOW
delay(1000); // wait for a second
}
40. MAIN.cpp
#include <Arduino.h>
int main(void) {
init();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun)
serialEventRun();
}
return 0;
}
Semplificazioni dell’IDE
nasconde:
Main.cpp
Prototipi delle funzioni
Gestione degli #include
41. Impostare la direzione di un pin
Con Arduino IDE
pinMode(pin_no., dir)
Es. impostare il pin 3 di Arduino (PD3) come uscita
pinMode(3, OUTPUT);
Nota: un pin alla volta
Supponiamo di voler impostare i pin 3, 5 e 7 (PD3, PD5 e PD7) come
uscite.
Come possiamo fare?
42. Esempio 1
Arduino IDE Registri
Impostare i pin 3, 5 e 7 (PD3, PD5 e PD7) come uscite
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(7, OUTPUT);
DDRD = 0b10101000;
or
DDRD = 0xA8;
or
DDRD | = 1<<PD7 | 1<<PD5 | 1<<PD3;
43. PINMODE()
void pinMode (uint8_t pin, uint8_t mode) {
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
out = portOutputRegister(port);
if (mode == INPUT) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out &= ~bit;
SREG = oldSREG;
} else if (mode == INPUT_PULLUP) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
SREG = oldSREG;
}
}
44. Uso di un pin per accendere un LED
Accendiamo un LED connesso al pin 7 di
Arduino (PD7) (occhio alla resistenza!)
Come si deve impostare la direzione del pin
7 (PD7)?
pinMode(__, ______);
Accendiamo il LED
digitalWrite(7, HIGH);
Spegniamo il LED
digitalWrite(7, LOW);
ATmega328
Arduino
pin 7
(PD7)
45. Esempio 2
Arduino Registri
Impostare i pin 0 e 1 (PD0 e PD1) come uscite con un livello del segnale
ALTO
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
digitalWrite(0, HIGH);
digitalWrite(1, HIGH);
DDRD = b00000011;
PORTD = b00000011;
o
DDRD = 0x03;
PORTD = 0x03;
oppure
DDRD | = 1<<PD1 | 1<<PD0;
PORTD | = 1<<PD1 | 1<<PD0;
46. Digitalwrite()
void digitalWrite (uint8_t pin, uint8_t val) {
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
47. PIN, sensori e resistenze di pull-up - 1
Usiamo un pulsante come sensore
Vogliamo leggere lo stato del pulsante
Qual è la direzione da attribuire al pin 3
di Arduino (PD3)?
pinMode(__, ______);
Qual è la tensione sul pin PD3 quanto il
contatto è chiuso?
Qual è la tensione sul pin PD3 quanto il
contatto è aperto?
Indeterminata!
ATmega328
Arduino
pin 3
(PD3)
48. PIN, sensori e resistenze di pull-up - 2
Forniamo una tensione sul pin PD3 per
determinare lo stato attivando la resistenza di
pull-up
Impostiamo PD3 come input-pullup:
pinMode(3, INPUT);
digitalWrite(3 ,HIGH);
oppure
pinMode(3, INPUT_PULLUP);
Che tensione leggero sul pin PD3
quanto il pulsante è aperto?
VTG
Che tensione leggero sul pin PD3
quanto il pulsante è chiuso?
GND
ATmega328
PD3
VTG= +5V
0
1
49. PIN, sensori e resistenze di pull-up - 3
Spegniamo la resistenza di pull-up
Dopo aver impostato PD3 come input:
pinMode(3, INPUT);
…….
digitalWrite(3, LOW);
ATmega328
PD3
VTG= +5V
0
1
50. PIN, sensori e resistenze di pull-up - 4
‘Weak Drive’
Settando il pin come input e attivando la
resistenza di pull-up interna la corrente in
uscita dal pin è debole.
Il valore tipico delle resistenze di pull-up per
l’ATmega328 è tra i 20 e 50 kΩ
ATmega328
PD3
VTG= +5V
0
1
iweak
51. Esempio 3
Arduino Registri
Impostare i pin 0 e 1 (PD0 e PD1) come ingresso attivando la resistenza
di pull-up
pinMode(0, INPUT);
pinMode(1, INPUT);
digitalWrite(0, HIGH);
digitalWrite(1, HIGH);
DDRD = 0; // all PORTD pins inputs
PORTD = b00000011;
o
PORTD = 0x03;
oppure
DDRD & = ~(1<<PD1 | 1<<PD0);
PORTD | = (1<<PD1 | 1<<PD0);
oppure
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);