Dispensa Arduino
Dispensa Arduino
Dispensa Arduino
Introduzione ad Arduino
In questa sezione presentiamo la piattaforma hardware e software Arduino. Esamineremo:
le caratteristiche tecniche della scheda Arduino Uno;
l'ambiente di sviluppo su PC;
il linguaggio di programmazione C;
1
2
Arduino Uno è una scheda di sperimentazione e prototipazione basata sul microcontrollore
ATmega328 prodotto da Atmel e presenta queste caratteristiche:
comunicazione: Arduino UNO prevede diversi protocolli di comunicazioni per poter comunicare
con dispositivi diversi; i pin 0/1 chiamati anche RX/TX ricevono e trasmettono i dati seriali
provenienti dall'integrato 16U2 che si occupa della conversione dei dati provenienti dall'USB in dati
seriali (e viceversa) adatti per il microcontrollore; i pin 10/11/12/13 supportano la comunicazione
SPI, una sorta di bus sincrono per la comunicazione tra microcontrollori; i pin A4/A5 implementano
i protocolli I2C o TWI.
1.3 La memoria
L'ATmega328 ha a disposizione 32 KB di memoria che includono però anche il bootloader (0,5
KB), cioè il programma che permette l'avvio del kernel del microcontrollore; dispone anche di 2
KB di SRAM (usate per le variabili e le costanti del software) e 1 KB di memoria EEPROM
(accessibile via software grazie alle relative librerie).
La memoria SRAM non è molto grande e va usata con attenzione (basti considerare che ogni
carattere di testo occupa un byte e tutta la memoria SRAM disponibile è di solo 2048 byte).
1.4 Input/output
I 14 pin digitali possono essere programmati a scelta sia come ingressi che come uscite e
supportano al massimo 40 mA; alcuni di essi pero hanno anche funzioni specializzate; in particolare
i pin 2 e 3 gestiscono l’interrupt, i pin 3,5,6,9,10,11 permettono una modulazione a larghezza di
impuso PWM, il pin 13 e collegato ad un led.
Gli ingressi analogici accettano segnali in tensione compresi tra 0 e 5 Volt che vengono convertiti in
digitale da un ADC a 10 bit (1024 possibili valori da 0 a 1023).
NB: la corrente massima erogabile da ogni pin è 40mA. Se si cerca di erogare più corrente o si
cortocircuita per errore un pin (sia a massa che a 5 Volt) c'è il rischio di danneggiare
irreversibilmente il pin o l'intera scheda. Fare attenzione!
3
1.6 Alimentazione
La scheda può essere alimentata direttamente dal PC tramite pa porta USB (5 V) o tramite il jack di
alimentazione purche la tensione sia tra i 7 e i 12 V (la scheda sopporta in realta l'intervallo 6-20 V,
ma fuori dal range 7-12 possono esserci problemi di stabilita nei 5 V o il danneggiamento della
scheda a causa del surricaldamento dei regolatori). In alternativa l'alimentazione può arrivare da una
sorgente esterna collegata al pin VIN.
Nella scheda e possibile prelevare alimentazioni per dispositivi esterni dai due regolatori che
forniscono 3.3 V e 5 V, dal pin VIN o dai pin GND per avere la massa di riferimento della scheda.
pin descrizione
Vin tensione dell'alimentazione esterna
5V tensione dal regolatore della scheda
3,3V tensione dal regolatore della scheda
GND massa (0 Volt)
IOREF riferimento di tensione
0e1 usati anche per la comunicazione seriale
2e3 usati anche come interrupt
3, 5, 6, 9, 10, 11 usati anche come uscite analogiche PWM
13 usata anche per il LED montato sulla scheda
da A0 a A5 ingressi analogici a 10bit (range 0-5 Volt → da 0 a 1023)
AREF riferimento per gli ingressi analogici
reset per fare un reset della scheda
4
Starting clockwise from the top center:
Analog Reference pin (orange)
Digital Ground (light green)
Digital Pins 2-13 (green)
Digital Pins 0-1/Serial In/Out - TX/RX (dark green) - These pins cannot be used for digital i/o
(digitalRead anddigitalWrite) if you are also using serial communication
(e.g. Serial.begin).
Reset Button - S1 (dark blue)
In-circuit Serial Programmer (blue-green)
Analog In Pins 0-5 (light blue)
Power and Ground Pins (power: orange, grounds: light orange)
External Power Supply In (9-12VDC) - X1 (pink)
Toggles External Power and USB Power (place jumper on two pins closest to desired supply) -
SV1 (purple)
USB (used for uploading sketches to the board and for serial communication between the board
and the computer; can be used to power the board) (yellow)
Microcontrollers
ATmega328 (used on most recent boards) ATmega168 (used on most Arduino Diecimila ATmega8 (used on
14 (of which 6 provide and early Duemilanove) some older board)
Digital I/O Pins 14 (of which 6 provide 14 (of
PWM output) Digital I/O Pins
PWM output) which
Analog Input Pins 6 (DIP) or 8 (SMD) Digital 3
Analog Input Pins 6 (DIP) or 8 (SMD) I/O Pins provide
DC Current per PWM
40 mA DC Current per
I/O Pin output)
40 mA
I/O Pin
Flash Memory 32 KB Analog
Flash Memory 16 KB Input 6
SRAM 2 KB Pins
SRAM 1 KB
EEPROM 1KB DC
EEPROM 512 bytes Current
40 mA
(datasheet) per I/O
(datasheet) Pin
Flash
8 KB
Memory
SRAM 1 KB
512
EEPROM
bytes
(datasheet)
D i gi t a l P i n s
In addition to the specific functions listed below, the digital pins on an Arduino board can be used for
general purpose input and output via the pinMode(), digitalRead(), and digitalWrite() commands. Each
pin has an internal pull-up resistor which can be turned on and off using digitalWrite() (w/ a value of
HIGH or LOW, respectively) when the pin is configured as an input. The maximum current per pin is
40 mA.
Serial: 0 (RX) and 1 (TX). Used to receive (RX) and transmit (TX) TTL serial data. On the
Arduino Diecimila, these pins are connected to the corresponding pins of the FTDI USB-to-TTL
5
Serial chip. On the Arduino BT, they are connected to the corresponding pins of
the WT11 Bluetooth module. On the Arduino Mini and LilyPad Arduino, they are intended for
use with an external TTL serial module (e.g. the Mini-USB Adapter).
External Interrupts: 2 and 3. These pins can be configured to trigger an interrupt on a low
value, a rising or falling edge, or a change in value. See the attachInterrupt() function for details.
PWM: 3, 5, 6, 9, 10, and 11. Provide 8-bit PWM output with the analogWrite() function. On
boards with anATmega8, PWM output is available only on pins 9, 10, and 11.
BT Reset: 7. (Arduino BT-only) Connected to the reset line of the bluetooth module.
SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). These pins support SPI communication,
which, although provided by the underlying hardware, is not currently included in the Arduino
language.
LED: 13. On the Diecimila and LilyPad, there is a built-in LED connected to digital pin 13.
When the pin is HIGH value, the LED is on, when the pin is LOW, it's off.
Analog Pins
In addition to the specific functions listed below, the analog input pins support 10-bit analog-to-digital
conversion (ADC) using the analogRead() function. Most of the analog inputs can also be used as digital
pins: analog input 0 as digital pin 14 through analog input 5 as digital pin 19. Analog inputs 6 and 7
(present on the Mini and BT) cannot be used as digital pins.
I2C: 4 (SDA) and 5 (SCL). Support I2C (TWI) communication using the Wire
library (documentation on the Wiring website).
Power Pins
VIN (sometimes labelled "9V"). The input voltage to the Arduino board when it's using an
external power source (as opposed to 5 volts from the USB connection or other regulated power
source). You can supply voltage through this pin, or, if supplying voltage via the power jack,
access it through this pin. Note that different boards accept different input voltages ranges,
please see the documentation for your board. Also note that the LilyPad has no VIN pin and
accepts only a regulated input.
5V. The regulated power supply used to power the microcontroller and other components on
the board. This can come either from VIN via an on-board regulator, or be supplied by USB or
another regulated 5V supply.
3V3. (Diecimila-only) A 3.3 volt supply generated by the on-board FTDI chip.
Other Pins
AREF. Reference voltage for the analog inputs. Used with analogReference().
Reset. (Diecimila-only) Bring this line LOW to reset the microcontroller. Typically used to add
a reset button to shields which block the one on the board.
Reference Home
Corrections, suggestions, and new documentation should be posted to the Forum.
The text of the Arduino reference is licensed under a Creative Commons Attribution-ShareAlike 3.0
License. Code samples in the reference are released into the public domain.
6
7
Denominazione Numerazione dei pin sulla scheda Corrispondenza
Denominazione
corrispondenza Arduino UNO rev3 numerazione pin
pin della scheda
pin sul sul
Arduino UNO
microcontrollore Connettori SX Connettori DX microcontrollore
rev3
ATmega 328P (lato sinistro) (lato destro) ATmega 328P
D5 (PWM) PD5 5 11
D6 PWM) PD6 6 12
Digital Input/Output
D7 PD7 7 13
D8 PB0 8 14
D9 (PWM) PB1 9 15
D10 (PWM) PB2 10 16
D11 PWM) PB3 11 17
D12 PB4 12 18
D13 PB5 13 19
GND 14 22
AREF 15 21
NC 16
NC 17
Ao (ADC0) PC0 1 23
A1 (ADC1) PC1 2 24
Analog Input
A2 (ADC2) PC2 3 25
A3 (ADC3) PC3 4 26
A4 (ADC4) PC5 5 27
A5 (ADC5) PC5 6 28
Vin 8
GND 7
GND 6
+5V (*) 5
Power
+3.3V 4
RESET RST 3 1
IOREF (*) (+5V) 2
NC 1
(*) Collegati
insieme.
8
Schema piedinatura della scheda Arduino UNO rev.3
USB
J
A
C
K
NC 17
NC 16
PIEDINATURA SCHEDA
AREF 15
ARDUINO UNO rev.3 GND 14
1 NC D13 13
D
2 IOREF(*) P D12 12
i
3 RESET g PWM D11 11
o
i
4 +3.3V t PWM D10 10
w
a
5 +5V(*) l PWM D9 9
e
6 GND D8 8
I
r
7 GND n
D7 7
p
8 Vin (*) Pin collegati insieme u PWM D6 6
t
1 A0 A / PWM D5 5
n O
2 A1 u D4 4
a
3 A2 l t PWM D3 3
o p
4 A3 g u D2 2
t
5 A4 TX D1 1
I
6 A5 n RX D0 0
9
Piedinatura delle MCU xx8 e descrizione dei segnali principali.
Chiudiamo questo capitolo con la descrizione della piedinatura del microcontrollore ATmega 328P-
PU che è da considerarsi identica per tutti i modelli della famiglia xx8 (ATmega8 e ATmega88-
168-328 P e noP).
• SCK – Serial Clock, segnale della programmazione ISP, è un collegamento diretto tra micro
programmatore e micro target.
• SS – Slave Select, segnale della programmazione ISP, esce dal micro programmatore e si
collega al pin RST del micro target.
10
• RST – Reset, di norma è fissato su livello logico H mediante una resistenza di pull-up, quando
viene portato a livello logico L resetta il micro; nella programmazione ISP, il pin RST del
micro programmatore resta libero, mentre quello del micro target si collega al pin SS del
micro programmatore; nei casi di collegamento diretto micro-micro, come quello appena
descritto, i livelli logici sono garantiti dal segnale SS, quindi si può fare a meno della
resistenza di pull-up.
• SDA – Linea Serial Bus Data Input, segnale del bus I2C; viene utilizzato per il collegamento
di più periferiche su questo unico BUS.
• SCL – Linea Serial Bus Clock Line segnale del bus I2C; fornisce il clock alle periferiche
collegate a questo unico BUS.
• TXD – Pin di trasmissione della porta seriale; il collegamento seriale prevede che questo pin
si colleghi, in modo incrociato, alla porta RX di un altro dispositivo.
• RXD – Pin di ricezione della porta seriale; il collegamento seriale prevede che questo pin si
colleghi, in modo incrociato, alla porta TX di un altro dispositivo.
• PWM – Pulse Width Modulation, è un segnale ad onda quadra avente frequenza dipendente
dal clock e dal prescaler interno al micro, e duty cycle impostabile via software mediante il
comando analogWrite(pin, value) con “pin” che è uno dei pin preposti del micro e “value”
che va da 0 a 255; con value=127 si ha una perfetta onda quadra (duty cycle 50%) con valori
inferiori la componente LOW dura di più della componente HIGH (duty cycle <50%) con
valori superiori la componente HIGH dura di più della componente LOW (duty cycle >50%).
• Dxx – Sono i pin di I/O digitali del micro, utilizzabili nella forma più semplice, mediante i
comandi: 1) pinMode(pin, INPUT) come ingressi; in tal caso il comando digitalRead(pin)
legge lo stato logico del pin; la variante pinMode(pin, INPUT_PULLUP) oltre ad impostare
il pin come ingresso, attiva una resistenza interna di pull-up. 2) pinMode(pin, OUTPUT)
come uscite; in tal caso il comando digitalWrite(pin, HIGH/LOW) imposta lo stato logico
del pin.
• X1 – Ingresso XTAL1 a cui è possibile collegare: 1) Uno dei due pin di un quarzo esterno,
tra XTAL1 e GND va collegato un condensatore ceramico di opportuna capacità; al posto del
condensatore si può usare un condensatore a capacità variabile, per ottenere la massima
precisione di oscillazione del quarzo. 2) L’uscita di un oscillatore esterno (clock a livelli
logici TTL generato da un circuito integrato quarzato) anche in questo caso tra XTAL1 e
GND va collegato un condensatore ceramico di opportuna capacità. 3) Uno dei due pin di un
risuonatore ceramico, questo componente ha già il condensatore integrato al proprio interno.
• X2 – Ingresso XTAL2 che in base alle tre situazioni precedenti si usa così: 1) Secondo pin del
quarzo esterno, tra XTAL2 e GND va collegato un condensatore ceramico di opportuna
capacità, identico a quello previsto su XTAL1, ma sempre a valore fisso. 2) Con la tipologia
ad oscillatore esterno questo pin resta libero. 3) Terzo pin del risuonatore ceramico, anche qui
non serve il condensatore; è importante però collegare il secondo pin (centrale) del
risuonatore ceramico a GND.
11
• AVCC – Alimentazione separata positiva per il circuito di conversione analogico-digitale
(ADC).
• Ayy – Sono i pin degli ingressi analogici del micro, collegati all’ADC, possono ricevere
tensioni variabili tra 0 e VCC, trasformandoli in una scala numerica compresa tra 0 e 1023, si
usano mediante il comando analogRead(pin); i pin analogici sono sempre utilizzabili anche
come I/O digitali, mediante gli specifici comandi visti in precedenza.
• ARef - A questo pin è possibile applicare una tensione di riferimento esterna di precisione
analogReference(EXTERNAL) per il comparatore dell’ADC, che si sostituisce alla standard
VCC analogReference(DEFAULT), ma che non può comunque essere maggiore di VCC; è
anche possibile usare un valore di precisione interno al micro
analogReference(INTERNAL) di 1,1 Volt; nei modelli di micro di questa famiglia, sul pin
ARef (nei casi DEFAULT e INTERNAL) viene riportata la tensione di riferimento del
comparatore, e vi si applica un condensatore ceramico o in poliestere da 0,1 F verso GND,
per bloccare eventuali disturbi.
N.B.: Dal data sheet ufficiale della ATMEL è possibile verificare che alcuni pin hanno anche altre
funzioni, non riportate qui per semplicità
12
2. Il software di Arduino
Dal sito di Arduino è possibile scaricare gratuitamente il software Arduino, in particolare l'ambiente
di sviluppo e i driver necessari per comunicare con la scheda. Il software è disponibile per
Windows, Mac e Linux.
2.1 Installazione del software in Windows
Il procedimento per l'installazione è descritto dettagliatamente - in inglese - nella sezione Getting
Started|Windows del sito di Arduino. In sintesi occorre:
scaricare il file .zip ed estrarlo nella posizione in cui si vuole installare il software
collegare la scheda col cavo USB (il LED power si accende)
installare il driver Arduino UNO.inf contenuto nella cartella drivers selezionando il driver
quando viene rilevata la scheda o usandoGestione dispositivi dal pannello di controllo
avviare il software Arduino e selezionare il tipo di scheda (Arduino Uno) e la porta seriale (ad
es. COM3)
13
Arduino:
Gli elementi principali del programma sono:
1. editor di testo
2. area messaggi
3. console di testo
4. barra degli strumenti
5. barra dei menu
6. barra di stato
L'editor occupa gran parte della finestra e permette di lavorare con più file contemporaneamente
usando delle tab (un po' come i browser ).
L'area messaggi mostra quale operazione sta eseguendo l'IDE mentre la console di testo visualizza
in maniera più dettagliata il risultato di queste operazioni, evidenziando errori o altre informazioni.
La barra di stato mostra il nome della scheda Arduino e della porta seriale utilizzata.
Dalla barra dei menu mostra è possibile accedere a tutte le funzionalità dell'IDE; la useremo per
poche operazioni fondamentali, in particolare:
impostare il tipo di scheda e la porta seriale utilizzate (menu Strumenti); nel nostro caso
sceglieremo “Arduino Uno” e una delle porte COM
impostare la posizione della cartella degli sketch che conterrà tutti i nostri programmi
(File|Preferenze); nel nostro caso una cartella nell'unità di rete Z:
La barra degli strumenti contiene sei icone che corrispondono ai comandi più utilizzati. La funzione
svolta da ognuno di loro è:
Il codice sorgente dei programmi - che in Arduino sono chiamati sketch - è un semplice file di testo
con estensione .ino. L'editor dell'ambiente di sviluppo, oltre alle solite funzioni presenti in tutti
editor, ha delle caratteristiche particolari che facilitano la scrittura dei programmi, in particolare:
il syntax highlighting, cioè la capacità di evidenziare il testo con colori diversi in base alle
regole del linguaggio di programmazione utilizzato (ad esempio i commenti sono in grigio, le
parole chiave in arancione, costanti in azzurro, ecc.)
l'auto-indentazione (l'indentazione consiste nell'aumentare il rientro del testo per dare
struttura al codice; non è necessaria - viene ignorata in fase di compilazione - ma aumenta
notevolmente la leggibilità del codice e ne facilita la comprensione); l'editor provvede ad
14
indentare correttamente il codice mentre lo si digita (ad esempio aumentando di due spazi il
rientro del blocco di codice di una funzione)
la guida di riferimento (Reference) del linguaggio di programmazione che può essere
consultata dal menu Aiuto o richiamando una voce in particolare selezionando una parola
chiave nel testo e utilizzando il menu contestuale
Risorse
Tutte le pagine sono in inglese.
il sito ufficiale
la scheda Arduino Uno
pagina di download del software
descrizione dettagliata della procedura di installazione in Windows
la guida di riferimento del linguaggio di programmazione
il forum in italiano
la guida ARDX di Oomlout
la guida SIK di SparkFun
il fumetto su Arduino
Il linguaggio di programmazione usato in Arduino è una versione semplificata del linguaggio C con
l‘aggiunta delle funzioni per gestire in maniera semplice le interfacce di input/output della scheda. I
programmi sono scritti al PC utilizzando il software Arduino - un IDE o ambiente di sviluppo
integrato -, trasmessi mediante la porta seriale USB al microcontrollore ATmega 328P e
memorizzati nella memoria EEPROM del microcontrollore ATmega 328P. Il programma viene
eseguito successivamente in modo ciclico.
Il codice sorgente di un programma per Arduino si chiama sketch.
La struttura di base di un programma (sketch) scritto per la scheda Arduino è molto semplice e può
essere suddiviso in tre parti:
1) Prima parte, posta generalmente all’inizio dello sketch per una migliore leggibilità, contiene
l’inserimento degli eventuali file di libreria e la dichiarazione di tutte le variabili che
verranno utilizzate.
2) Seconda parte, costituita dalla funzione setup() utilizzata per configurare la scheda, per
esempio per programmare i pin digitali in ingresso o uscita ecc..
Sintassi della funzione setup():
void setup()
{
Istruzioni di configurazione della scheda che devono essere eseguite una sola volta
all’inizio dell’esecuzione del programma;
}
3) Terza parte, costituita dalla funzione loop() che contiene il programma da eseguire
ciclicamente.
Sintassi della funzione loop():
void loop()
{
Istruzioni del programma che devono essere eseguite ciclicamente fino a quando il
microcontrollore è alimentato;
}
15
Entrambe le funzioni sono necessarie per l’esecuzione del programma. Il contenuto scritto dentro le
parentesi graffe della funzione setup, contiene la dichiarazione delle variabili, viene eseguita una
sola volta e serve per programmare i pin del Microcontrollore ATmega 328P utilizzando la funzione
pinMode, o per inizializzare la comunicazione seriale.
La funzione loop include il codice da eseguire in modo continuo: lettura ingressi, attivazione uscite,
ecc..
Esempi:
void setup()
{
pinMode (pin,OUTPUT); // Imposta la variabile pin come uscita
}
void loop()
{
digitalWrite (pin;HIGH); // scrive un livello logico 1 (+5 Volt) su pin
delay (1000); // inserisce un ritardo di 1 secondo (1000 millisecondi)
digitalWrite (pin,LOW); // scrive un livello logico 0 (0 Volt) su pin
delay (1000); // inserisce un ritardo di 1 secondo (1000 millisecondi)
}
il simbolo // permette di aggiungere un commento in una riga del codice; quello che scriviamo
dopo questo simbolo viene ignorato dal programma compilatore ma può essere utile per
spiegarne il funzionamento
allo stesso modo il testo compreso tra i simboli /* e */ viene ignorato dal programma
compilatore; in questo modo possiamo scrivere commenti che si estendono su più righe
le parentesi graffe aperta { e chiusa } delimitano l'inizio e la fine di un blocco di
codice (inserite da tastiera con la combinazione di tasti Maiuscolo+AltGr+[ e
Maiuscolo+AltGr+]);
al termine di ogni istruzione va inserito un punto e virgola ;
le variabili, per memorizzare valori che possono cambiare durante l'esecuzione del
programma
le costanti, per memorizzare valori che non cambiano durante l'esecuzione del programma
16
Le variabili hanno un nome, un tipo e un valore e devono essere dichiarate, cioè elencate, prima di
poter essere utilizzate. Una dichiarazione come questa:
int valoreSensore = 0;
dice che useremo una variabile chiamata valoreSensore per memorizzare numeri interi a che il suo
valore iniziale è 0 (il valore inziale è opzionale).
Nel corso del programma possiamo assegnare un nuovo valore alle variabili con l'operatore di
assegnazione (simbolo =):
valoreSensore = 100;
Ogni volta che compare il nome della variabile, verrà utilizzato il valore precedentemente
assegnato.
Possiamo scegliere un nome a piacere per le variabili ma non può essere uguale a una delle parole
chiave del linguaggio Arduino (quelle elencate nella pagina della guida di riferimento). Inoltre è
bene:
Per scegliere il tipo di dati per una variabile è bene tenere conto che:
i numeri interi sono a 16 bit e vanno da -32768 a 32767; per valori più piccoli o più grandi ci
sono altri tipi di dati;
i numeri con la virgola sono a 32 bit, hanno un numero di cifre fisse mentre la virgola è
“mobile” (NB il simbolo del separatore di decimale è il punto!); vanno usati solo se
necessario perché occupano più memoria, possono dare risultati “strani” a causa delle
approssimazioni e sono più lenti da elaborare;
17
i caratteri usano il codice ASCII (256 simboli) e vanno racchiusi tra apici singoli (ad
esempio 'A').
i valori logici:
false, cioè falso che corrisponde a zero
true, cioè vero che corrisponde a 1 (e più in generale a qualunque numero diverso da zero)
i valori che possono assumere i pin digitali:
HIGH, cioè il valore alto di tensione che vale 5 Volt se il pin è usato come output e
corrisponde a un valore maggiore di 3 Volt se è usato come input
LOW cioè il valore basso di tensione che vale 0 Volt se il pin è usato come output e
corrisponde a un valore minore di 2 Volt se è usato come input
i valori INPUT e OUTPUT usati per impostare i pin
Queste costanti sono evidenziate col colore blu nell'editor.
3.6 Le espressioni
Le istruzioni di un programma possono contenere delle espressioni composte da variabili, costanti
ed operatori.
Gli operatori matematici sono:
=, per assegnare un valore
+, -, * e /, per somma, sottrazione, prodotto e divisione
%, per il modulo, cioè il resto di una divisione (ad es. 7 % 5 vale 2)
Gli operatori logici si usano con operandi logici, danno come risultato vero o falso e sono:
&& è l'operatore “and” e dà come risultato vero se entrambi gli operandi valgono vero
|| è l'operatore “or” e dà come risultato vero se almeno un operando è vero
! è l'operatore “not” e scambia vero e falso
Come in matematica possiamo usare le parentesi per indicare l'ordine delle operazioni. Per chiarire
facciamo qualche esempio:
l'espressione (3 > 2) && (5 < 2) vale falso perché il secondo operando è falso
l'espressione (3 > 2) || (5 < 2) vale vero perché il primo operando è vero
l'espressione !((3 + 2) == 5) vale falso
NB: fare attenzione a non confondere l'assegnazione (=) con l'uguaglianza (==)!
18
la selezione o struttura condizionale, che permette di eseguire istruzioni diverse in base al
verificarsi o meno di una condizione.
il ciclo o struttura iterativa, che permette di ripetere più volte un gruppo di istruzioni.
Nel linguaggio Arduino ci sono delle parole riservate per la gestione delle strutture di controllo e
pertanto non possono essere utilizzate come nomi di variabile o nomi di etichette. Ci sono due modi
per realizzare una struttura condizionale:
con le istruzioni if e if…..else;
con l'istruzione switch;
Flow-Chart START
Test NO
SI
ESEGUI LE ISTRUZIONI
DA 1 a n
END
19
2) Nel secondo caso la sintassi è la seguente:
Flow-Chart
END
END 20
La condizione che compare tra parentesi è un'espressione che ha come risultato vero o falso (ad
esempio punteggio > 5); se la condizione è vera viene eseguito il blocco di codice delimitato dalle
parentesi graffe altrimenti si passa all'istruzione successiva. Il blocco con else if è opzionale e
permette di verificare una seconda condizione alternativa alla prima. Il blocco else è anch'esso
opzionale e contiene le istruzioni da eseguire nel caso in cui tutte le condizioni precedenti siano
risultate false. Molto spesso nella selezione compaiono solo il primo e l'ultimo blocco.
L'istruzione switch funziona in maniera leggermente diversa dalle istruzioni if e if…..else. Essa usa
la sintassi seguente:
switch (variabile)
{
case valore1:
blocco di istruzioni da eseguire se variabile è uguale a valore1
break;
case valore2:
blocco di istruzioni da eseguire se variabile è uguale a valore2
break;
………….
case default:
blocco di istruzioni da eseguire se variabile non corrisponde a nessuno dei
valori elencati
}
In questo caso viene eseguito un determinato blocco di istruzioni o codice se il valore della variabile
indicata nell’l'istruzione switch è uguale al valore indicato nell’l'istruzione case. L'ultimo caso
(default) è opzionale. È bene notare che i blocchi di istruzioni non sono delimitati da parentesi
graffe ma cominciano dopo il simbolo : e terminano con l'istruzione break; (tale istruzione va
omessa nel case default). Questo tipo di struttura permette di esprimere in maniera semplice una
selezione con molte opzioni possibili.
Nel linguaggio Arduino ci sono due modi per realizzare una struttura iterativa:
Ciclo iterativo for, per ripetere un gruppo di istruzioni un certo numero di volte;
Iclo iterativo while, per ripetere un gruppo di istruzioni finché una condizione è vera.
Ciclo for
Il ciclo for viene utilizzato per ripetere un blocco di istruzioni da 1 a N, racchiuso tra le parentesi
graffe, un determinato numero di volte. A tal fine il ciclo for necessita di una variabile
contatore che cambia valore ogni volta che viene ripetuto il gruppo di istruzioni e viene usata per
stabilire se continuare il ciclo o meno.
Nel ciclo iterativo for troviamo tre elementi separati da un punto e virgola (;):
Inizializzazione del contatore al valore iniziale;
La condizione che deve essere vera per continuare il ciclo;
Incremento della variabile contatore.
La sintassi è la seguente:
21
for(variabile contatore=valore iniziale; test o condizione sulla variabile contatore; incremento della
variabile contatore) /* Le istruzioni da 1 a n vengono eseguite fino a quando la risposta al test sulla
variabile contatore è SI (vera). In questo caso le istruzioni potrebbero non
essere mai eseguite */
{
Istruzione 1; Flow-Chart
Istruzione 2; START
…………...;
Istruzione n;
} VARIABILE
CONTATORE=VALORE
INIZIALE
Test sulla NO
variabile END
contatore ?
SI
ESEGUI LE ISTRUZIONI
DA 1 a n
INCREMENTA LA
VARIABILE CONTATORE
Il contatore viene usato solo all'interno del ciclo for e di solito ha un nome molto semplice (ad
esempio “X” o “I”). L'esempio seguente esegue un gruppo di istruzioni 20 volte:
for(int I=0;I<20;I++)
{
Istruzione 1;
Istruzione 2;
…………...;
Istruzione n;
}
In questo caso il blocco di istruzioni viene ripetuto fino a quando la variabile contatore I è minore di
20 - cioè 20 volte - e la variabile I viene incrementata usando l'operatore ++che corrisponde
all'espressione:
I = I+1;
cioè assegna ad I il suo valore aumentato di uno.
Al comando for segue una parentesi tonda. Il contenuto all’interno della parentesi definisce quante
volte deve essere ripetuto il blocco di istruzioni contenute entro le parentesi graffe.
22
int I=0; dichiara la variabile contatore di tipo intero, impostata al valore iniziale uguale a zero.
I<20; specifica che fino a quando la variabile contatore è minore di 20 vengono ripetute le istruzioni
da 1 a n, perché la risposta al test è vera.
I++; ad ogni ciclo iterativo la variabile contatore I viene incrementata di uno, cioè I=I+1.
Esempio:
The for statement is used to repeat a block of statements enclosed in curly braces. An increment
counter is usually used to increment and terminate the loop. The for statement is useful for any
repetitive operation, and is often used in combination with arrays to operate on collections of
data/pins.
//statement(s);
The initialization happens first and exactly once. Each time through the loop, the condition is
tested; if it's true, the statement block, and the increment is executed, then the condition is tested
again. When the condition becomes false, the loop ends.
Example
// Dim an LED using a PWM pin
int PWMpin = 10; // LED in series with 470 ohm resistor on pin 10
void setup()
{
// no setup needed
}
void loop()
{
for (int i=0; i <= 255; i++){
analogWrite(PWMpin, i);
delay(10);
}
}
23
Coding Tips
The C for loop is much more flexible than for loops found in some other computer languages,
including BASIC. Any or all of the three header elements may be omitted, although the semicolons
are required. Also the statements for initialization, condition, and increment can be any valid C
statements with unrelated variables, and use any C datatypes including floats. These types of
unusual for statements may provide solutions to some rare programming problems.
For example, using a multiplication in the increment line will generate a logarithmic progression:
Generates: 2,3,4,6,9,13,19,28,42,63,94
Another example, fade an LED up and down with one for loop:
void loop()
{
int x = 1;
for (int i = 0; i > -1; i = i + x){
analogWrite(PWMpin, i);
if (i == 255) x = -1; // switch direction at peak
delay(10);
}
}
24
Ciclo while (Il funzionamento è lo stesso del ciclo for. La sintassi è leggermente diversa)
ciclo while esegue all’infinito le istruzioni racchiuse tra le parentesi graffe fino a quando la
condizione racchiusa dentro le parentesi tonde diventa falsa.
All’interno delle istruzioni bisogna inserire la variazione delle variabili che modificano la
condizione, altrimenti si rischia di non uscire più dal ciclo iterativo. Tale variazione potrebbe anche
provenire dall’esterno, per esempio da un sensore. START
Sintassi: Flow-Chart
VARIABILE
Variabile contatore=valore iniziale;
CONTATORE=VALORE
while(test o condizione sulla variabile contatore) INIZIALE
{
Istruzione 1;
Istruzione 2;
…………………………..;
Istruzione n;
Incremento della variabile contatore;
} Test sulla NO
variabile END
contatore ?
SI
ESEGUI LE ISTRUZIONI
DA 1 a n
INCREMENTA LA
VARIABILE CONTATORE
NB Per non ripetere il ciclo all'infinito è necessario che nel blocco di codice venga modificato
qualcosa che possa rendere falso il test. L'esempio seguente è equivalente al ciclo for visto sopra:
Esempio:
I=1;
while(I<20)
{
Istruzione 1;
Istruzione 2;
…………………………..;
Istruzione n;
I = I+1;
}
Il blocco di struzioni viene ripetuto fino a quando I<20; ogni volta la variabile I aumenta di uno fino
a rendere falsa la condizione indicata tra parentesi.
25
while loops (dalla guida in linea di Arduino IDE)
Description
while loops will loop continuously, and infinitely, until the expression inside the parenthesis, ()
becomes false. Something must change the tested variable, or the while loop will never exit. This
could be in your code, such as an incremented variable, or an external condition, such as testing a
sensor.
Syntax
while(expression)
{
// statement(s)
}
Parameters
Example
var = 0;
while(var < 200){
// do something repetitive 200 times
var++;
}
Il ciclo do … while si comporta come l’istruzione while ma con una importante differenza: esegue
almeno una volta le istruzioni contenute all’interno del ciclo do … while. Quindi viene usato
quando si vuole che il codice dentro la parentesi graffe venga eseguito almeno una volta prima di
verificare la condizione.
Sintassi: START
SI Test sulla NO
variabile END
contatore ?
26
Esempio:
L’esempio seguente assegna il valore letto dal sensore analogico alla variabile VAR, si ferma per 50
millisecondi, poi inizia il ciclo iterativo fino a quando VAR<100.
do
{
VAR=readSensors(); /* assegna il valore di readSensors() alla variabile VAR */
delay(50); /* ciclo di ritardo di 50 millisecondi */
}
while(VAR<100); /* inizio del ciclo iterativo finchè VAR<100 */
do
{
// statement block
} while (test condition);
Example
do
{
delay(50); // wait for sensors to stabilize
x = readSensors(); // check the sensors
3.10 Le funzioni
Una funzione è un blocco di codice a cui abbiamo dato un nome che può essere utilizzato in varie
parti del programma. Una volta definita una funzione possiamo utilizzarla semplicemente
indicandone il nome, cioè chiamando la funzione.L'ambiente di programmazione Arduino
comprende una serie di funzioni utili già definite e pronte da utilizzare; l'elenco completo si trova
nella pagina guida di riferimento del sito di Arduino. Possiamo aggiungere altre funzioni
definendole nel nostro programma; per farlo dobbiamo assegnare un nome e un tipo alla funzione e
scrivere il blocco di codice da eseguire quando la funzione viene chiamata.
Alcune funzioni quando vengono eseguite restituiscono un risultato (ad esempio la
funzione sqrt() che calcola la radice quadrata di un numero), altre invece non restituiscono alcun
risultato (ad esempio le funzioni setup() e loop()). Il tipo di una funzione è il tipo di dati del valore
che viene restituito e può essere:
uno dei tipi usati anche per le variabili
il tipo void per le funzioni che non restituiscono risultato
Quando una funzione viene chiamata potrebbe essere necessario passare dei parametri alla
funzione. I parametri servono a fornire i dati necessari all'esecuzione della funzione; ad esempio per
27
calcolare la radice quadrata del numero 4 è necessario passare il parametro “4” alla funzione in
questo modo: sqrt(4). I parametri possono essere valori o variabili e vanno indicati tra le parentesi
(NB le parentesi vanno sempre indicate, anche quando non ci sono parametri da passare).
Esempi:
1. Nel listato seguente viene utilizzata una funzione utente chiamata lampeggio() , che non
restituisce alcun valore al programma chiamante principale (funzione di tipo void e non
necessita da questa di alcun parametro). Il programma principale void loop() a un certo punto,
dopo un primo blocco di istruzioni, chiama la funzione utente void lampeggio() , il cui
compito è accendere e spegnere un diodo LED per la durata di 1 secondo. Al termine
dell’esecuzione della funzione utente, il controllo ritorna al programma principale e
l’esecuzione riprende dall’istruzione immediatamente successiva alla chiamata della funzione
utente.
/* Esempio di listato contenete la funzione utente lampeggio() di tipo void */
void setup()
{
pinMode(led,OUTPUT);
}
void loop()
{
/*
blocco di istruzioni che contiene la chiamata
alla funzione utente lampeggio()
*/
}
void lampeggio()
{
digitalWrite(led,HIGH); /* Il diodo LAD si accende */
delay(1000); /* Ciclo di ritardo di 1 sec. */
digitalWrite(led,LOW); /* Il diodo LED si spegne */
delay(1000); /* Ciclo di ritardo di 1 sec. */
}
2. Un caso di funzione che restituisce un valore è illustrato nel listato seguente. In questo caso il
programma principale void loop() chiama la funzione Lett_sensore(), che gli restituisce nella
variabile intera val_sens il risultato di val di una serie di elaborazioni. Queste consistono nella
lettura tramite analogRead(1) di 5 valori forniti da un sensore connesso al pin analogico 1,
nell’esecuzione della loro media aritmetica e nella riduzione della scala del risultato nel
campo da 0 a 255.
/* Esempio di listato contenete la funzione utente Lett_sensore() che restituisce il valore val */
void loop()
{
/*
blocco di istruzioni che contiente la chiamata
alla funzione utente Lett_sensore()
*/
28
int val_sens = Lett_sensore();
/*
blocco di istruzioni
*/
}
int Lett_sensore()
{
int i;
int val;
for(i=o;i<5;i++)
{
val=val+analogRead(1);
}
val=val/5; /* calcola la media aritmetica */
val=val/4; /* scala da 0 a 255 */
return val;
}
3. Nell’esempio seguente che mostra una funzione utente prodotto() , dopo la chiamata da parte
del programma principale, gli restituisce nella variabile k un valore intero (risultato). Questo
consiste nel prodotto fra i due valori delle variabili i e j passati a loro volta dal programma
principale alla funzione utente.
void loop()
{
int i=2;
int j=3;
int k;
/*
blocco di istruzioni che contiente la chiamata alla funzione utente prodotto()
*/
k=prodotto(i,j);
/*
blocco di istruzioni
*/
}
int prodotto(int x,int y)
{
int risultato;
risultato=x*y;
return risultato;
}
In questa sezione descriviamo rapidamente la sintassi di alcune funzioni del linguaggio Arduino.
Una panoramica più completa di tutte le funzioni e della loro sintassi è disponibile - sempre in
inglese - nella guida di riferimento.
29
Input/output
una serie di funzioni matematiche e trigonometriche;
la funzione random(minimo, massimo) per generare numeri casuali compresi in un
intervallo;
le funzioni della classe Serial, per stabilire una comunicazione seriale con un PC
attraverso la porta USB.
Alcune raccomandazioni
Ricordare:
Questi ultimi suggerimenti riguardano lo stile usato per scrivere il programma e, pur non essendo
indispensabili, rendono più leggibile e quindi più comprensibile il programma. Per lo stesso motivo
non è una buona idea scrivere uno sketch come questo:
Il programma - senza commenti, senza spazi e senza “a capo” - è corretto e viene compilato senza
errori ma è difficile da leggere e da capire.
30
Lo stesso sketch va scritto correttamente come segue:
int led=13;
void setup()
{
pinMode(led,OUTPUT);
}
void loop()
{
digitalWrite(led,HIGH);
delay(1000);
digitalWrite(led,LOW);
delay(1000);
}
31
Strutture Variabili Funzioni
setup() Costanti Digital I/O
loop() HIGH | LOW pinMode()
Strutture di controllo INPUT | OUTPUT digitalWrite()
if true | false digitalRead()
if..else integer constants Analog I/O
for floating point constants analogReference()
switch case Tipi di dati analogRead()
while void analogWrite() – PWM
do…while boolean Advanced I/O
break char tone()
continue unsigned char noTone
return byte shiftOut()
goto int insigne int shifttln()
Elementi sintattici word pulseln()
; (punto e virgola) long Tempo
{ } (parentesi graffe) unsigned long millis()
// (commento su una riga) float micros()
/*… */ commento su più righe) double delay()
#define string – char array delayMicroseconds()
#include string – object Matematica
Operatori aritmetici array min()
(=) assegnazione Conversioni max()
(+) somma char() abs()
(-) sottrazione byte() constrai()
(*) moltiplicazione int() map()
(/) divisione word() pow()
(%) modulo long() sqrt()
Operatori di comparazione float() Trigonometria
(= =) uguale a Variabile Scope & Qualificatori sin()
( !=) diverso da variable scope cos()
(<) minore di static tan()
(>) maggiore di volatile Numeri casuali
(<=) minore o uguale a const randomSeed()
(>=) maggiore o uguale a Utilities random()
Operatori Booleani sizeof() Bit e Byte
(&&) and lowByte()
(||) or highByte()
Operatori per i puntatori bitRead()
(*) operatore per deferenziare bitWrite()
(&) operatore per referenzialre bitSet()
Operatori Bitwise (sui singoli bit) bitClear()
(&) bitwise and bit()
(|) bitwise or Interrupt esterni
( ) bitwise not attachInteterrupt()
(<<) shift binario a sinistra detachInterrupt()
(>>) shift binario a destra Interrupt
Operatori compositi interrupts()
(++) incrementa noInterrupts()
(--) decrementa Comunicazioni
(+=) somma composita Serial
(-=) sottrazione composita
(*=) moltiplicazione composita
(/=) divisione composita
(&=) compound bitwise and
(|=) compound bitwise or
32
In Arduino abbiamo a disposizione una serie di librerie standard, da includere o meno nel
programma a seconda delle nostre esigenze di progetto e già presenti nell’IDE standard:
EEPROM – per leggere e scrivere su memorie EEPROM, che conservano i dati anche senza
essere alimentate.
Ethernet – per collegare ad Internet e a una rete Ethernet attraverso Arduino Ethernet
Shield.
Firmata – per comunicare con il computer collegato al Arduino secondo il protocollo
standard.
LiquidCristal – per gestire i display a cristalli liquidi basati su controller HD44780 o
compatibile (LCD).
SD – per leggere e scrivere le schede di memoria SD.
Servo – per controllare i servomotori.
SPI – per dialogare con dispositivi che utilizzano l’interfaccia e il protocollo Serial
Peripheral Interface (SPI).
SoftwareSerial – per creare una porta seriale su qualsiasi pin digitale.
Stepper – per gestire i motori passo-passo (stepper).
Wire – per gestire la comunicazione con uno o più dispositivi che impiegano la modalità di
comunicazione a due fili Two Wire Interface (TWI/I2C).
Sul sito ufficiale di Arduino (arduino.cc/en/Reference/Libraries) sono disponibili i collegamenti alle
“Contributed Libraries” con le descrizioni e le istruzioni per includere nel proprio sketch.
33
3.12 Le resistenze di PULL-UP interne e/o esterne al microcontrollore e di PULL-DOWN
esterne.
INTODUZIONE:
I pin di ingresso dei circuiti digitali e i pin di ingresso digitali dei microcontrollori presentano
solitamente una resistenza di ingresso molto alta con possibilità di accettare in ingresso segnali di
frequenza molto alta (segnali di disturbo).
Questo significa che se sono lasciati flottanti (cioè senza applicare nessun segnale) possono captare
segnali di disturbo elettromagnetici o elettrostatici che possono far commutare le uscite del circuito
in modo del tutto casuale.
Si definisce floating (flottante) quel pin di ingresso a cui non è applicato nessun segnale
digitale.
Quindi per un corretto funzionamento del circuito digitale è necessario collegare a questi pin di
ingresso un adeguato e noto livello di tensione (alto=+5V; basso=0V).
Nella logica TTL si possono rispettare le seguenti bande di livello dei segnali digitali:
Dove:
Vihmin = +2V è il minimo livello di tensione
interpretato dal circuito digitale come livello
logico alto (1 logico).
Consideriamo uno switch collegato all’ingresso digitale di un microcontrollore come riportato nello
schema di figura seguente:
Per eliminare questo problema ci sono due tecniche (utilizzando delle resistenze esterne):
1. Inserire una resistenza di PULL-UP R1 collegata tra l’ingresso digitale e +V come nello
schema seguente:
Aperto Alto
Chiuso Basso
2. Inserire una resistenza di PULL-DOWN R1 collegata tra l’ingresso digitale e GND (massa)
come nello schema seguente:
Aperto Basso
Chiuso Alto
35
Come si determinano i valori delle resistenze di PULL-UP e/o di PULL-DOWN esterne ?
In modo molto sintetico possiamo dire che il valore della resistenza di PULL-UP esterna R1
deve essere in grado di portare a livello logico alto la tensione sul pin digitale di ingresso al
microcontrollore quando lo switch è aperto. Il valore di tensione all'ingresso del pin dipende
dalla corrente assorbita e dalla famiglia logica a cui appartiene il dispositivo: da famiglia a famiglia
i livelli accettati come alto e basso variano.
Il circuito equivalente visto dall'ingresso del pin digitale può essere sintetizzato come una
resistenza di ingresso Rinput .
Quando lo switch è chiuso, il pin è collegato direttamente a massa attraverso la bassa resistenza
del contatto stesso e del suo cablaggio, per cui il livello di tensione è sicuramente basso.
Quando lo switch è aperto, il livello di tensione al pin è quello stabilito dal partitore composto
da R1 e dalla resistenza di ingresso Rinput .
In altre parole, la caduta di tensione sulla resistenza R1 determinata dalla corrente che affluisce al
pin dalla Vcc (attraverso R1 ) deve essere tale da non far scendere la tensione all'ingresso del pin al
di sotto della Vihmin per quel dato dispositivo digitale.
Quando il contato è chiuso, attraverso R1 passa una corrente data da Vcc / R1 . Se il valore
di R1 è troppo basso, la corrente sarà elevata e questo non è di alcuna utilità al circuito, anzi,
è condizione che si cerca di evitare nelle realizzazioni che richiedono un basso consumo.
Quando l' interruttore è aperto, il valore di R1 e della corrente assorbita dal pin di ingresso
Iin determina la tensione al pin stesso data da Rinput * Iin . Se R1 ha un valore troppo alto, la
tensione al pin non arriverà al livello alto necessario per garantire il livello logico alto.
Quindi, la prima condizione tende a cercare valori di R1 il più alto possibile, mentre la seconda
tende ad abbassarne tale valore.
La resistenza del PULL-UP può essere valutata approssimativamente con la seguente formula:
36
R1 < [Vccmin - Vihmin ] / Iin
dove Iin è la corrente di ingresso che il pin assorbe a livello alto cioè con lo switch aperto. I vari
parametri si rilevano dal foglio dati dei componenti digitali. Per la resistenza di PULL-DOWN il
calcolo sarà relativo alla tensione Vilmax.
Dal punto di vista pratico, possiamo evitare ogni considerazione troppo complessa (e che non è
necessariamente funzionale) e possiamo dire che R1 dovrà avere un valore il più elevato
possibile, ma senza eccedere.
In pratica si può considerare la regola empirica, ma corretta, di utilizzare una resistenza di PULL-
UP pari a 1/10 della resistenza di ingresso vista dal pin Rinput .
In queste condizioni siamo sicuri che la tensione formata dal partitore R1 -Rinput sarà sicuramente
superiore a quella di livello alto (Vihmin ) per qualsiasi famiglia logica.
Per gate CMOS la resistenza di ingresso è dell' ordine di molte decine di megaohm, per cui
la R1 potrà variare tra 100 kohm e 1 Mohm.
Va considerato che, anche se la resistenza del gate è di decine o centinaia di megaohm, ci
possono essere percorsi di corrente non intenzionali, ad alta resistenza, tra i pin dell'
integrato, ad esempio a causa di sporco, residui dei flussanti di saldatura, umidità e anche
vie parassitarie all'interno l'IC stesso. In generale questi percorsi sono dell'ordine di 10-100
mega ohm o più, per cui, se si mantiene la resistenza di PULL-UP sotto il valore di 1
Mohm, la scelta è adeguata.
Ovviamente valori molto minori, come il classico 10K andranno comunque bene, anche se
tenderanno ad avere un maggior consumo di corrente non giustificato.
Per gli ingressi dei microcontrollori, solitamente TTL compatibili, ma realizzati con
CMOS, la resistenza di ingresso sarà dell' ordine del megaohm o più e quindi R1 potrà
variare tra 10 kohm e 100 kohm.
Per ingressi TTL la resistenza di ingresso è minore e anche R1 dovrà essere attorno a 5
kohm o meno.
Dato che 10 kohm è un valore comune, si può utilizzare questa resistenza per un PULL-UP di uso
"universale", anche se vanno fatte altre considerazioni.
per contro, nel PULL-UP, tanto maggiore sarà la resistenza R1 , tanto più il livello di
tensione applicato al pin di ingresso si avvicinerà al limite di theshold, dato che maggiore
sarà la caduta di tensione.
Questo vuol dire che una tensione indotta dall' esterno non dovrà avere un valore
37
eccezionale per portare il pin nell' area di indeterminatezza.
Per contro, un basso valore della resistenza di PULL-UP porterà la tensione al pin di
ingresso più vicino alla Vdd e quindi aumenterà la reiezione ai disturbi.
Un'altra considerazione da fare è che maggiore è la resistenza di pull-up, più lenta sarà
una variazione di livello applicata al pin.
Questo è perché il circuito interno al pin, e sopratutto quello esterno, hanno una capacità
parassita che può anche essere significativa rispetto alla frequenza dei segnali applicati
quando è accoppiata con la resistenza di pull-up.
Infatti si forma un filtro RC e questo necessita di tempo per cambiare di stato. Se è richiesta
una rapida variazione del segnale, un pull-up di valore elevato, accoppiato con la capacità
del pin e del circuito esterno collegato, può limitare la velocità alla quale la logica cambia
stato in modo affidabile o, per lo meno, ridurre la velocità di commutazione e deformare i
fronti di salita e discesa del segnale.
Se si conosce il valore del carico capacitivo, è possibile calcolare la resistenza massima ammissibile
di pull-up con alcune equazioni, ma va poi verificato se il componente che pilota il pull-up può
erogare la corrente necessaria per portare il livello a "0"; se non è possibile, occorre utilizzare un
valore più elevato di pull-up e ritrovarsi con un tempo di salita maggiore sull'output oppure
introdurre un buffer.
Se quanto detto a riguardo dei pull-up è estendibile anche ai pin inutilizzati, va notato che, in alcuni
casi, i costruttori raccomandano proprio di lasciare alcuni pin non collegati (nc - no connection). Le
possibilità sono due:
il pin non corrisponde ad alcuna connessione del silicio, quindi non ha nessuna
importanza il livello di tensione
il pin ha funzioni riservate dal costruttore, ad esempio di test, e in tal caso non va
collegato ad alcun segnale esterno.
In ogni caso, dove il costruttore indica un nc è opportuno astenersi dal collegare quel pin a qualsiasi
cosa.
Ma esiste anche la possibilità che il costruttore abbia implementato pull-up o, più facilmente,
pull-down all' interno del chip per assicurare una corretta polarizzazione a uno o più pin.
38
Ne è un esempio lo
schema dell'RTC
DS1302 di Maxim.
Possiamo osservare
che il costruttore ha
integrato resistenze
di pull-down sui pin
di accesso seriale al
chip, del valore di
circa 40 kohm.
Questo serve a
garantire un sicuro
livello basso (i pin
sono attivi a livello
alto) nel caso di
mancanza di
connessione o di
connessione con bus
ad alta impedenza.
Pertanto, prima di prevedere sul circuito resistori di pull-up o pull-down è esenziale consultare i
fogli dati dei componenti, onde verificare la struttura e le reali esigenza dei componenti.
Up e non solo
Quindi, se possiamo dire che resistori di pull-up sono utilizzati in circuiti elettronici per garantire
che gli ingressi ai sistemi di logica dei livelli definiti e certi, anche se i dispositivi esterni di
ingresso sono disconnessi o ad alta impedenza, dobbiamo anche ricordare che resistori di pull-up
sono utilizzati anche in altre situazioni.
Un pull-up può essere utilizzato all'interfaccia tra due diversi tipi di dispositivi logici che operano a
tensioni Vcc diverse.
39
Ad esempio, nell' interfacciare l' uscita di
una logica TTL con l' ingresso di un
CMOS, alimentati alla stessa tensione, un
pull-up, tipicamente tra 1 e 4.7 kohm dovrà
essere inserito per assicurare il giusto
livello di tensione.
In questo senso un pull-up costituisce anche il carico di un bus open collector, ad esempio I2C o il
PS/2 della tastiera/mouse del PC.
Resistori pull-up possono essere utilizzati su uscite logiche dove è necessario ottenere tempi di
commutazione spinti, iniettando più corrente nei condensatori parassitari e riducendo il tempo dato
dall' RC; in queste condizioni spesso si preferisce a semplici pull-up dei terminatori pull-up/pull-
down, tipico il 220/330 ohm dei bus TTL, oppure terminatori attivi (ad esempio nei bus SCSI).
40
Resistenza di PULL-UP interna ai microcontrollori
Alcuni port di I/O dei microcontroller dispongono di resistenze di PULL-UP integrate, la cui
inclusione è solitamente programmabile mediante la scrittura di un livello logico alto sul pin.
Queste "resistenze" integrate hanno lo scopo principale è di fornire un percorso corrente per
supportare contatti verso la massa, come interruttori, tastiere, ecc. Nel caso di interfaccia con
componenti attivi vanno verificate le condizioni di lavoro e se necessario vanno utilizzate resistenze
di pull-up esterne.
41
Scusami se rispondo solo adesso.
Lo schema elettrico del circuito è il seguente:
La resistenza che vedi nel circuito è detta di pull down, questa resistenza consente di far si che nel
momento in cui premo il pulsante (per rilevare lo stato HIGH) non si crei un cortocircuito tra Vcc e
GND, cioè la resistenza limita la corrente che vi circola, inserendo una resistenza da 10KOhm avrai
una corrente pari a: I = V/R = 5 V/10000 Ohm = 0,5mA.
42
Puoi usare valori di resistenza anche superiori, in genere valori da 10K a 47K vanno bene.
Infatti è quasi sempre inutile usare le pull up esterne, per attivare quelle interne, in wiring, basta
usare la digitalWrite (n,HIGH) dove n è il pin input, precedentemente definito come tale, su cui
desideriamo attiva la pull up.
In pratica scrivi lo stato HIGH su un pin dichiarato come input digitale e con questa operazione
viene attivata la pullup interna relativa a quel pin.
I pin digitali di Arduino possono essere configurati per essere usati sia come ingressi che come
uscite. Anche i pin analogici posso essere configurati ed usati per svolgere funzioni digitali.
pinMode(pin, mode)
dove pin è un valore di tipo int che indica quale pin stiamo configurando, e mode può assumere due
valori INPUT ed OUTPUT.
INPUT
Quando configuriamo un pin come INPUT lo settiamo in condizione di alta impedenza, in pratica è
come se in serie al pin ci fosse una resistenza di circa 100MOhm. Questa resistenza serve a non
“caricare” il circuito da cui andiamo a leggere il dato limitando l’assorbimento di corrente.
Se da un lato questa resistenza ci fa comodo perchè ci dà una alta sensibilità, dall’altro può crearci
problemi proprio per lo stesso motivo: se lasciamo il pin scollegato, o magari collegato ad un filo
che non giunge da nessuna parte, rischiamo di subire l’influenza di un qualche accoppiamento
capacitivo (o qualche altro genere di distrurbo) che ci fa leggere un valore inesatto. Un esempio può
essere l’uso di un encoder dove i contatti sono liberi finchè non ruotiamo l’encoder, e poi tornano
scollegati.
Per ovviare a questo problema possiamo usare una resistenza di pull-up “nativa” dell’arduino. Essa
si attiva usando il comando digitalWrite(pin, HIGH) su un pin precedentemente configurato come
input. In questo modo si attiva una resistenza da 20 KOhm interna all’Arduino tra l’alimentazione
ed il pin.
Nota: Questa resistenza genera una piccola corrente che potrebbe far accendere lievemente un LED
collegato a quel pin.
Nota2: Sulla maggior parte delle board al pin 13 è collegato anche un led con una resistenza, questa
potrebbe far variare la lettura quando si attiva la resistenza di pull-up su questo pin.
Per capire bene la funzione della resistenza di pull-up interna vediamo queste due configurazioni
praticamente equivalenti.
43
Con Pull-Up esterna:
Nel primo abbiamo usato la classica configurazione con la resistenza di pull-up esterna; come uscita
usiamo il pin 13, così da fruttare il led integrato in Arduino; per la misura dell’ingresso digitale
abbiamo usato un pin analogico: per attivarli come ingressi/uscite digitali si usa la normale sintassi
pinMode() ricordandosi che essi sono numerati da 14 a 19 (A0 diventa 14, A1 diventa 15 ecc…).
Nel secondo abbiamo attivato la resistenza di pull-up interna ed abbiamo tolto quella esterna, il
risultato è uguale!!!
OUTPUT
La configurazione da pin di OUTPUT è l’esatto contrario dell’INPUT: il pin viene posto in bassa
impedenza, ed è in grado di generare (o assorbire) fino a 40 mA di corrente. Dobbiamo stare attenti
a non superare questo limiti, perchè ciò comporterebbe la bruciatura del transistor d’uscita rendendo
il pin (e a volte anche l’ATMega) inutilizzabile.
44