arduino harware regole di programmazione uscite / Ingressi digitali uscite / Ingressi analogici Cicli con array e stringhe for, case, while, do Funzioni operazioni matematiche /trigonometriche /byte applicazioni matematiche Cos'è Arduino Arduino è una piattaforma hardware e software open-source con cui realizzare dispositivi digitali in grado di interagire con il mondo esterno attraverso sensori (ad esempio una fotocellula) e attuatori (ad esempio un motore). L'hardware è basato su un semplice microcontrollore Atmel montato su una scheda con ingressi e uscite sia digitali che analogici a cui collegare sensori e attuatori. La scheda Arduino può essere collegata a un PC tramite la porta USB per trasferire i programmi dal PC o per stabilire una comunicazione seriale. Si consiglia una tensione tra 7 e 12V. Che viene poi ridotta ai 5V e a 3,3 da un regolatore presente sulla scheda Se utilizziamo un alimentatore esterno, sul pin Vin si troverà la tensione di alimentazione vera e propria senza regolazione. Arduino seleziona automaticamente la sorgente di alimentazione. A L I M E N T A Z I O N E ABATTERIA Dimensionamento della batteria Il dimensionamento della batteria è un aspetto fondamentale di un progetto. Arduino One, Mega e 2009, grazie al connettore esterno, permettono di alimentare il sistema per mezzo di batterie… ma quali usare? La batteria da utilizzare dipende da: 1. Tempo d’uso 2. Corrente richiesta dal sistema 3. Tensione richiesta dal sistema 4. Dimensione massima (in cm) della batteria Se per esempio abbiamo un circuito che necessità 3,3V, consuma 150mA e vogliamo che la batteria duri almeno 8 ore, dovremo scegliere un batteria con tensione maggiore di 3,3V (il circuito avrà un regolatore, come Arduino) e una ‘capacità’ di almeno 150mA*8*1,2 = 1440mAh 1,2 è un fattore di correzione per assicurarsi la durata voluta. Comunicazione seriale La maggior parte dei microcontrollori operano in stand-alone, ovvero non necessitano di lavorare connessi ad altri computer. Per caricare il programma nel µC occorre solitamente collegarlo alla porta seriale di un computer. Nelle comunicazioni seriali i dati vengono spediti un bit alla volta. I cavi seriali utilizzati presentano un conduttore di trasmissione (TX) e uno di ricezione (RX). Questo consente di ottenere una comunicazione bidirezionale nella quale i dati vengono inviati e ricevuti contemporaneamente. I pin 0 (RX) e 1 (TX) del connettore DIGITAL della scheda consentono la comunicazione seriale fra il microcontrollore e il PC attraverso il convertitore seriale- USB. Grazie a queste linee il programma scritto sul pc viene inviato al µC e dati dal µC possono essere inviati al pc. Per la comunicazione dal µC PC sono necessarie queste istruzioni: •Serial.begin(speed) ; impostando in speed la velocità di trasmissione (9600bps) •Serial.println(data); per inviare I dati da visualizzare sul monitor nell’apposita finestra Serial Monitor dell’interfaccia grafica. La trasmissione dal PC µC sono gestite dalle istruzioni: Val=Serial.available(); fornisce Il numero di byte presenti nel buffer della porta seriale in attesa di essere letti. Se il buffer è vuoto val=0; Val=Serial.read(); legge il primo byte disponibile nel buffer e lo assegna a val Baud Rate, Velocità di trasmissione tra computer e microcontrollore. Valore tipico 9600 bits/s (baud). Bit di start Serve ad “avvisare” il ricevitore che la trasmissione dei dati sta per iniziare. Data bits Il dato che deve essere inviato. Ad esempio la lettera H in binario è 01001000 (ASCII 72). Bits di stop Servono a indicare al ricevitore che la trasmissione è finita. L’AMBIENTE DI SVILUPPO *IDE* La figura seguente mostra la finestra del programma Arduino: 1. 2. 3. 4. 5. 6. editor di testo area messaggi console di testo barra degli strumenti barra dei menu barra di stato L'editor occupa gran parte della finestra e permette di lavorare con piu file usando DELLE TAB 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 fondamentali, in particolare: ▪ ▪ useremo per poche operazioni 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 è: ▪ ▪ ▪ ▪ ▪ ▪ Verifica: controlla se ci sono errori nel programma Carica: compila il programma - cioè traduce il testo in un file eseguibile - e lo carica sulla scheda Arduino Nuovo: crea un nuovo sketch Apri: mostra un menu con tutti gli sketch (i nostri e quelli di esempio) Salva: salva lo sketch Monitor seriale: apre la finestra del monitor seriale che visualizza i dati inviati dalla scheda Arduino al PC È necessario selezionare la porta seriale e il tipo di scheda utilizzata se la scheda Arduino “non risponde" Qual è la mia porta seriale? Scrivere un programma con l'editor 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 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 NB: il linguaggio è case-sensitive, cioè le lettere maiuscole sono diverse dalle minuscole (ad esempio le variabili led e Led sono diverse e IF non è interpretata come l'istruzione if). Il linguaggio di programmazione Il linguaggio di programmazione usato in Arduino è una versione semplificata del linguaggio C con in più delle funzioni per gestire in maniera semplice le interfacce di input/output della scheda. I programmi vengono scritti al PC utilizzando il software Arduino - un IDE o ambiente di sviluppo integrato - e trasmessi via USB alla scheda Arduino, dove vengono eseguiti. Il codice sorgente di un programma per Arduino si chiama sketch. SOFTWARE - COMUNICARE CON GLI ALTRI Arduino può utilizzare lo stesso cavo USB utilizzato per la programmazione per comunicare con i computer. Serial.begin(); – predispone i parametri della seriale USB (RS232 fittizia) Serial.print(); – per inviare dei dati al computer (USB) Serial.write(); – per inviare dei dati in codice ASCII al computer (USB) Serial.read(); - per leggere i dati inviati dal computer (USB) La funzione “Serial.print();” trasferisce (stampa) i dati sulla porta seriale RS232 virtuale (USB reale). La funzione “Serial.println();”. È simile alla precedente con l’aggiunta di un ritorno automatico a capo e avanzamento di riga. Per configurare la porta seriale RS232 e impostare il baud rate (velocità di trasmissione dei caratteri) si utilizza dentro il setup() la funzione Serial.begin(9600);”. Il valore tipico di trasmissione e ricezione per comunicare con il computer è di 9600 baud con 1-bit di Start, 8-bit di Data 0/1-bit parità e 1-bit di Stop. Velocità maggiori sono supportate 19200, 38400, 115200. int test = 33; // valore numerico coincide con carattere “!” Serial.print(test); // stampa i caratteri ascii “33”. Di default è il valore DECIMALE Serial.write(test); // stampa il carattere ASCII “!”. Serial.print(test, DEC); // stampa i caratteri “33”. Serial.print(test, HEX); // stampa i caratteri “21”. Valore in esadecimale (base 16) Serial.print(test, OCT); // stampa i caratteri “41”. Valore in ottale (base 8); Serial.print(test, BIN); // stampa i caratteri “100001”. Valore in binario (base 2) Stesse modalità con la funzione “Serial.println()” con il cursore che salta su una nuova riga a capo. LE FUNZIONI PIÙUSATE pinMode (3,OUTPUT) ; configura il pin 3come OUTPUT digitalWrite(3,LOW); porta il pin3 al livello LOW (HIGH) Val=digitalRead(3); legge il pin 3 e assegna alla variabile val il valore LOW o HIGH analogWrite( 3,127); genera un’onda quadra con dc del 50 % Val= analogRead(3); legge il valore (0÷1023 ) sul pin 3 (A3)e lo assegna a val Delay(ms); genera un ritardi di ms millisecondi delayMicrosecond(µs); genera un ritardo espresso in µs in microsecondi Val=millis(); pone in val il numero di millisecondi trascorsi dall’inizio dello sketch. Val=pulseIn(3,HIGH); pone nella variabile val la durata in µ della parte alta (HIGH) dell’impulso che si presenta sul pin di ingresso 3 Tone(3,frq,duration); genera sul pin 3 un tono di frequenza in Hz e durata in ms specificate noTone(3); interrompe la generazione del tono sul pin 3 Serial.begin(speed); imposta la velocità di trasmissione della porta seriale Serial.println(data); trasmetti dati tramite laporta seriale Val= Serial.available(); indica il numero di byte in attesa di essere letti nel buffer della porta seriale Val=Serial.read(); legge il primo byte del buffer della porta seriale shiftOut(dataPin,clockPin,bitOrder,value); Viene usata per espandere le uscite della scheda tramite uno shift register SIPO (serial input parallel output) collegato con l’ingresso dati seriale e con il clock a 2 dei pin digitali (dataPin e clockPin). bitOrder (LSBFIRST o MSBFIRST) speciica l’ordine con cui escono i bit e con value il byte da inviareCOSTANTI Oltre alle costanti numeriche const int buttonPin = 2; alle stringhe o caratteri chiusi tra apici , Arduino usa le costanti HIGH/LOW, INPUT/OUTPUT, true/false. Const char x[5]=“Ciao” REGOLE DI PROGRAMMAZIONE UN programma e’ normalmente composto da tre parti /* prima parte, per la dichiarazione delle librerie, delle variabili, delle costanti e per la codifica delle routine e cioe’ parti di codice che vengono eseguite solo quando sono richiamate da una specifica istruzione*/ /* -----( note esplicative sulle finalita’ e sul funzionamento del programma ) -----*/ /*-----( dichiarazione delle eventuali librerie utilizzate dal programma )-----*/ /*--( dichiarazione degli oggetti utilizzati, ad esempio display a cristalli liquidi o servomotori )---*/ /*-----( dichiarazione delle costanti )-----*/ /*-----( dichiarazione delle variabili )-----*/ /*-----( codifica di eventuali routine )-----*/ void setup() /* seconda parte o parte di setup, eseguita solo all’avvio del programma*/ { /* ----( dichiarazione delle porte di input e di output )----*/ /* ----( eventuali istruzioni da eseguire all’avvio del programma )----*/ } void loop() /*terza parte o parte di loop, parte principale del programma, che viene eseguita e ripetuta fino al termine dell’alimentazione o fino alla pressione del pulsante reset*/ { /* ----( istruzioni di programma )-----*/ } Ogni istruzione termina con un “;” Le parentesi tonde e quadre delimitano gli operatori di un’istruzione mentre le parentesi graffe delimitano una serie di istruzioni riferibili ad una condizione, a una routine o a una parte di programma. Se da un’istruzione dipende l’esecuzione di altre istruzioni, le istruzioni “subordinate” sono di norma racchiuse tra parentesi graffe; Ad ogni parentesi aperta deve corrispondere una parentesi chiusa. L’assenza di una parentesi di chiusura o di apertura qualche volta impedisce la compilazione (e quindi l’esecuzione) del programma ed in ogni caso ne rende imprevedibile i funzionamento; La combinazione di caratteri /* indica l’inizio di una zona di note, che puo’ estendersi su piu’ righe e che deve necessariamente essere chiusa dalla combinazione */ La combinazione // indica l’inizio di una zona di note che si protrae fino alla fine della riga; Le indentazioni, non obbligatorie, sono comunque utili per rendere piu’ facilmente comprensibile un programma. Nella sezione “strumenti” dell’IDE esiste la funzione “formattazione automatica”, utile appunto per ottenere l’indentazione automatica del codice; Le variabili e le costanti devono essere dichiarate prima (in termini di posizione fisica nel programma) del loro utilizzo. Per questo motivo e’ buona norma concentrare la loro definizione in testa al programma, prima del setup e delle eventuali routine ricordarsi ▪ ▪ che maiuscole e minuscole non sono uguali la differenza tra =(assegnazione) e == (confronto) “LINGUAGGIO C” PER ARDUINO UNO Il linguaggio è “C standard” (più facile rispetto al C++) possiede moltissime funzioni utili già implementate: pinMode() - impostare un pin come ingresso o uscita digitalWrite() - impostare un pin output digitale a livello alto / basso digitalRead() - leggi lo stato di un pin definito come input digitale analogRead() - legge e converte la tensione di un pin analogico in un valore numerico (10-bit) analogWrite() - scrive un valore "analogico" con PWM (8-bit) delay() - aspetta un periodo di tempo (espresso in millisecondi) millis() – si ottiene il tempo da quando la scheda è stata accesa. E molte altre funzioni, comprese le “librerie” (raccolta di funzioni necessarie per colloquiare con i dispositivi di input / output). Utilizzo della funzione digitalRead() e pinMode() In setup() utilizzare pinMode(numero_pin, INPUT); numero_pin = fornire il numero del pin da utilizzare come input oppure come output es.: pinMode(7, INPUT); // definisci il pin 7 come input pinMode(8, OUTPUT); // definisci il pin 8 come output In loop() utilizzare digitalRead(numero_pin); per ottenere il livello logico acquisito sull’input (pulsante, interruttore, ecc.) se necessario il valore letto può essere memorizzato in una variabile. es.: leggi_pulsante = digitalRead(7); // leggi il valore dall’input collegato al pin7 (i valori sono “0” oppure “1”) e memorizzalo nella variabile denominata «leggi_pulsante» USCITE / INGRESSI DIGITALI USCITE DIGITALI: ACCENSIONE DEI LED CON ARDUINO Ogni pin è in grado di fornire circa 40 mA (15mA Arduino DUE) di corrente, questa corrente è sufficiente per lavorare con un diodo LED (max. 20 mA). Valori assorbiti o erogati che sono superiori ai 40 mA o tensioni superiori a 5V (3,3V Arduino DUE) su qualsiasi pin possono danneggiare il microcontrollore o il dispositivo collegato. /* Accendere 2 LED alternativamente per 250 msec. */ void setup() // funzione di configurazione dei Input/Output { // inizializza il pin 7 e 6 come output, perche' sono collegati ai pinMode(7, OUTPUT); pinMode(6, OUTPUT); } void loop() // p(main) --> ciclo infinito (loop) { digitalWrite(7, HIGH); // accendi il LED1 forzando un livello ALTO digitalWrite(6, LOW); // spegni il LED2 forzando un livello BASSO delay(250); // aspetta 0,25 secondi digitalWrite(7, LOW); // spegni il LED1 forzando un livello BASSO digitalWrite(6, HIGH); // accendi il LED2 forzando un livello ALTO delay(250); // aspetta 0,25 secondi } LED sul pin 7 sul pin 6 sul pin 7 sul pin 6 Uscite digitali: controllo di 2 LED INGRESSI DIGITALI La maggior parte degli ingressi (digital input) che si usano sono interruttori, pulsanti, contatti di fine corsa, ecc. Gli interruttori consentono di interrompere o abilitare il passaggio della corrente Unipolare = un solo cavo viene controllato Doppio polo = due cavi vengono controllati in una sola volta L'interruttore e il pulsante si definiscono chiusi (resistenza tra i suoi due terminali < 1 ohm = cortocircuito), quando consentono il passaggio di corrente, invece se il passaggio è interdetto si definiscono aperti (resistenza > 10 Mohm) L’interruttore, deviatore o il pulsante permettono il passaggio l’interruzione della corrente. Ma Arduino ha bisogno di “leggere” una tensione: 1) Un livello logico 2) Un livello logico COLLEGAMENTO DEI PULSANTI N.A. (normalmente aperti) R1 10K INP Circuito con resistenza di pull-up per collegare un pulsante di tipo N.O. (normaly open) a un pin del microcontrollore. 2 Pulsante premuto livello logico in uscita 0 Pulsante rilasciato livello logico in uscita 1 S1 PULSANTE N.A. 1 PULSANTE N.A. VCC GND PULS. PREMUTO = LOW PULS. NON PREMUTO = HIGH 2 Circuito con resistenza di pull-down per collegare un pulsante di tipo N.O. (normaly open) a un pin del microcontrollore. S2 PULSANTE N.A. 1 PULSANTE N.A. VCC INP R2 470 GND PULS. PREMUTO = HIGH PULS. NON PREMUTO = LOW Pulsante premuto livello logico in uscita 1 Pulsante rilasciato livello logico in uscita 0 COLLEGAMENTO DEI PULSANTI N.C. (normalmente chiusi) • CIRCUITO CON RESISTENZA DI PULL-UP PER COLLEGARE UN PULSANTE DI TIPO N.C. (NORMALY CLOSE) A UN PIN DEL MICROCONTROLLORE. R1 10K INP • PULSANTE PREMUTO LIVELLO LOGICO IN USCITA 1 (APERTO) 2 • PULSANTE RILASCIATO LIVELLO LOGICO IN USCITA 0 (CHIUSO) SW1 PULSANTE N.C. 1 PULSANTE N.C. VCC GND PULS. PREMUTO = HIGH PULS. NON PREMUTO = LOW 2 SW2 PULSANTE N.C. INP 1 PULSANTE N.C. VCC R2 470 GND Circuito con resistenza di pull-down per collegare un pulsante di tipo N.C. (normaly close) a un pin del microcontrollore. Pulsante premuto livello logico in uscita 0 Pulsante rilasciato livello logico in uscita 1 PULS. PREMUTO = LOW PULS. NON PREMUTO = HIGH ARDUINO UNO CON L’INPUT / OUTPUT DIGITALE Come INPUT è possibile collegare e configurare qualsiasi pulsante o interruttore tra i pin 2 e 12 della scheda [sono da escludere i pin 0 (RX), 1 (TX) e 13 (led interno)] Come OUTPUT è possibile collegare e configurare qualsiasi led tra i pin 2 e 13 della scheda [sono da escludere i pin 0 (RX), 1 (TX)] // CONSIDERANO LA RESISTENZA DI PULLUP INTERNA int pulsante = 7; void setup() { pinMode(pulsante , INPUT); // inizializza il pin 13 come INPUT digitalWrite(pulsante, HIGH); //attiva sul pin 7 la resistenza da 10 Kohm di pullup } void loop() { } OPPURE void setup() { pinMode(2, INPUT_PULLUP); pinMode(13, OUTPUT); Serial.begin(9600); R DOWN, R UP: IMPEDISC0NO IL C.C. QUANDO SI PREME IL PULSANTE R- DOWN INTERNA NON PREVISTA A LIVELLO DI ISTRUZIONE if.. else… Permette di prendere delle decisioni. If (..condizione..) { ..codice da eseguire se la condizione e’ vera..; } else { ..codice da eseguire se la condizione e’ falsa..; } …. codice che verra’ eseguito in ogni caso…. E’ possibile usare l’istruzione if anche senza la parola chiave else. In quest’ultimo caso se la condizione e’ vera verranno eseguite le istruzioni racchiuse tra le parentesi graffe che seguono la if, se invece e’ falsa e si passera’ direttamente alle istruzioni successive alla parentesi graffa di chiusura. Struttura: E S E M P I C O N S TRUTTURE DI CONTROLLO: IF……….. ELSE Esempio: if (val==1) // se la variabile “val” contiene il valore “1” { digitalWrite(3, HIGH); // pone in stato “HIGH” (e cioe’ attiva) la componente di OUTPUT che in fase di inizializzazione del programma e’ stata associata alla porta 3 (ad esempio un led) } else { digitalWrite (3, LOW); // se invece “val” contiene un valore diverso da “1” pone in stato di LOW” (disattiva) la componente di OUTPUT associata alla porta 3 } SCRITTURA DI UN DATO DIGITALE IN MODO RIPETITIVO /* lettura di un input digitale con stampa del livello logico sulla porta seriale*/ void setup () // { pinMode(7, INPUT); // inizializza il pin 7 come INPUT (PULSANTE) digitalWrite(7, HIGH); // settaggio per la r interna di pull-up da 10Kohm pinMode(13, OUTPUT); // inizializza il pin 13 come OUTPUT (LED) Serial.begin (9600); } void loop () { int pulsante = digitalRead(7); // acquisisci il valore dell'input pin 7 nella variabile "pulsante" if (pulsante == 0) // verifica se il pulsante è premuto (condizione VERA = pulsante n.a. PREMUTO) { Serial.print("Pulsante PREMUTO collegato al pin 7 --> Livello:"); Serial.println(pulsante, DEC); // stampa sulla seriale il valore dell'input collegato al pulsante (pin 7) digitalWrite(13, HIGH); // accendi il LED forzando un livello ALTO sul pin 13 } else // (condizione FALSA = pulsante n.a. NON PREMUTO) { Serial.print("Pulsante NON PREMUTO collegato al pin 7 --> Livello: "); // stampa sulla seriale Serial.println(pulsante, DEC); // stampa sulla seriale il valore dell'input collegato al pulsante (pin 7) digitalWrite(13, LOW); // spegni il LED forzando un BASSO sul pin 13 } } //PULSANTE PREMUTO 1 NON PREMUTO O #define SI 2 int flag=1; // SI "pulsante" SOLO ISTRUZIONE IF STESSO PROGRAMMA SENZA DEFINE || INDICA OR LOGICO //&& = INDICA AND ! NOT int flag=1; void setup () { Serial.begin (9600); pinMode(SI, INPUT); } void loop () { int var; var=digitalRead(SI); // SCRITTURA VALORE DECIMALE 0 if(!var && flag){ // pulsante non premuto Serial.println(var,DEC); flag=0; } // SCRITTURA VALORE DECIMALE 1 if(var && !flag){ //pulsante premuto Serial.println(var,DEC); flag=1; } delay(10); } void setup () { Serial.begin (9600); pinMode(2, INPUT); } void loop () { int var; var=digitalRead(2); if(not var and flag){ Serial.println(var,DEC); flag=0; } if(var and not flag){ Serial.println(var,DEC); flag=1; } delay(10); } USCITE / INGRESSI ANALOGICI Ingressi Analogici: Arduino ha 6 ingressi analogici (A0…A5) ognuno dei quali ha una risoluzione a 10 bit (cioè è in grado di di riconoscere 2^10 = 1024 intervalli di tensione LETTURA DEGLI INGRESSI «analogRead(3)» permette di acquisire una tensione analogica presente sul PIN A2 compresa tra 0 e 5V In un formato digitale a 10 bit questo comporta che l’intervallo di 5V sarà diviso in 1024 intervalli : 5/1024 = 0,00488 v 0 v = 00000..0; 00048 v = 00..01; 0,0048x2 = 00..010 ecc………0,0048x1022 = 111….1110 0,0048x1024 = 11..11 E presente il PIN AREF, col quale per mezzo di una apposita funzione si può fissare il valore un riferimento minore di 5v (3,3 v) LETTURA DELLE USCITE analogWrite( X,valore) ; uscita dalla scheda Arduino è disponibile solo sui pin digitali: 3, 5, 6, 9, 10 e 11. In uscita il dato viene fornito in forma digitale a 8 bit a cui corrispondono 255 livelli (2^8 = 255) Le seguenti istruzioni analogWrite( 3,127) ; genera sul pin 3 un’onda quadra con D.C. del 50% (2,5, v) analogWrite( 5,63);genera sul pin 5 un’onda quadra con D.C. del 25% (1,25 v) analogWrite( 3,191); genera sul pin 3 un’onda quadra con D.C. del 75% (3, 75 v) const int potenziometro = 0; //imposta l’ingresso A0 del potenziometro const int motore = 9; //imposta il pin che verrà collegato alla base del transistor int velocita; //variabile di supporto per scrivere il valore letto dal potenziometro void setup() { pinMode(motore, OUTPUT); //inizializza il motore come output } void loop() { velocita = map(analogRead(potenziometro),0,1023,0,255); //il motore gira con velocità proporzionale alla rotazione del potenziometro analogWrite(motore, velocita); } #define potenziometro 0 // potenziometro #define motore 9 // motore void setup() { // inizializza il motore come output pinMode(motore, OUTPUT); Serial.begin(9600); } void loop(){ int valore = map(analogRead(potenziometro),0,1023,0,255); // il valore letto in ingresso del potenZiometro a 10 bit viene convertito in un valore a8 bit analogWrite(motore,valore); if(valore >100){ Serial.println("lento"); }else{ Serial.println("veloce"); } } TABELLE DELLE VARIABILI UTILIZZATE CON ARDUINO Una variabile rappresenta un dato che può cambiare il proprio valore durante l’esecuzione del programma.Una costante rappresenta un dato che non può cambiare di valore nel corso dell’esecuzione. La dichiarazione di una costante associa ad un identificatore (nome della costante) un valore (espresso eventualmente mediante altra costante). La dichiarazione di una variabile e di una costante è un passaggio obbligatorio nel linguaggio C e richiede di definire un identificatore (nome della variabile), un tipo (esempio: int, char, etc) e eventualmente le dimensioni (solo per gli "array" e le "stringhe") prima che venga utilizzata nel programma. Una variabile globale è visibile in ogni funzione del programma. Qualsiasi variabile dichiarata fuori da una funzione (per es. setup(), loop(), etc.) è una variabile globale. Le variabili locali sono visibili soltanto all'interno della funzione nella quale esse sono dichiarate. Le variabili locali sono un modo utile per assicurare che soltanto all'interno di quella funzione si ha accesso alle proprie variabili. Questo previene errori di programmazione quando una funzione inavvertitamente modifica variabili usate da un'altra funzione. È anche possibile dichiarare e inizializzare una variabile all'interno di un ciclo. Questo crea una variabile accessibile solo all'interno del ciclo. Esempio: for ( int k=0; k<10; k++) { ..... } La variabile Static viene utilizzata per creare una variabile che è visibile solo da una funzione. la variabile volatile indica al compilatore di caricare la variabile dalla memoria RAM, e non dalla memoria register. int inputVariable = 0; // si dichiara una variabile a cui è assegnato il valore 0 inputVariable = analogRead(2); // imposta la variabile al valore presente sul pin analogico 2 if (inputVariable < 100) // verifica se la variabile è minore di 100 { inputVariable = 100; // se vero viene assegnato 100 } delay(inputVariable); // usa la variabile per impostare il ritardo void setup() { } int valore; //variabile visibile ad ogni funzione void loop( ){ int k=0; for(int i=0; i<100;i++){ //'i' è visibile solamente all'interno del ciclo for «statica» k++; //questa variabile esterna al ciclo for ma visibile solo nel ciclo loop. float f=analogRead(15); // f è una variabile locale che non è¨ disponibile all'esterno del ciclo loop } } CICLI CON ARRAY E STRINGHE FOR, CASE, IF, WHILE, DO ISTRUZIONE for(int x = 0; x < 10; x++) { // blocco di codice da ripetere Serial.print(x, HEX); } È una istruzione di ripetizione particolarmente adatta per realizzare un numero predefinito di cicli tramite un contatore. La prima espressione è di inizializzazione (x=0;) viene eseguita una volta sola, prima di entrare nel ciclo. La seconda espressione (x<10;) rappresenta la condizione di permanenza nel ciclo (viene valutata all'inizio di ogni iterazione). La terza espressione (x++) rappresenta l’incremento o il decremento (x--) unitario per il passaggio al ciclo successivo (valutata alla fine di ogni iterazione). Per forzare l’uscita da un ciclo “for" si utilizza l'istruzione "break“. void setup() { Serial.begin(9600); } int flag=0; void loop() { if(flag==0){ int i,a,j; for (i=1;i<=2;i++) { for (j=1;j<=10;j++) { (a=i*j); Serial.println(a); flag=1; } } } } Lampeggio tre led con ciclo for int timer = 100; // Più alto è il numero, più lenta è la tempistica void setup() {// inizializza ciascun pin come uscita: for (int Pinuno = 2; Pinuno < 5; Pinuno ++) { pinMode(Pinuno , OUTPUT); } } void loop() { for (int Pinuno = 2; Pinuno < 5; Pinuno ++) { // accensione in avanti digitalWrite(Pinuno, HIGH); delay(timer); digitalWrite(Pinuno, LOW); } } Le stringhe Una stringa è una sequenza di caratteri delimitata da virgolette (testo in ASCII) esempio: "ciao!" "Hello" In C le stringhe sono semplici sequenze di caratteri di cui l’ultimo, sempre presente in modo implicito, è «\0» (carattere di fine della stringa) /* Il carattere "\0" e' corrispondente alla fine della stringa*/ char testo1[6] = {'C', 'i', 'a', 'o', '1', '\0'}; // stringa con terminazione char testo2[] = "Ciao2"; // stringa senza terminazione,si puo scrivere piu di 6 ch char testo3[6] = "Ciao3"; // stringa senza terminazione (viene chiusa in automatico dal programma) char testo4[] = {67, 105, 97, 111, 52, 0}; // stringa con terminazione (valori decimali) byte testo5[] = { 'C', 'i', 'a', 'o', '5', '\0'}; // stringa con terminazione void setup() // funzione di configurazione dei Input/Output { Serial.begin(9600); } void loop() // programma principale (main) --> ciclo infinito (loop) { Serial.write(testo1); Serial.println(); Serial.print(testo1); Serial.println(); Serial.write(testo2); Serial.println(); Serial.write(testo3); Serial.println(); Serial.write(testo4); Serial.println(); for(int x=0; x<5; x++) // ciclo con il numero di { Serial.write(testo5[x]); // stampa del } for(int x=0; x<5; x++) // ciclo con il numero di { Serial.print(testo5[x]); // stampa del } while (1);} } caratteri da stampare singolo carattere byte caratteri da stampare singolo carattere ASCII ARRAY Array: ’ un elenco di variabili accessibili tramite un indice. Un array e’ una variabile di tipo int o char seguita da una parentesi quadra aperta, un valore numerico (il numero di elementi) ed una parentesi quadra chiusa. Si utilizza la parola chiave int l’array conterra’ dei numeri interi di valore compreso tra -32768 e 32767 se si utilizza la parola chiave char conterra’ dei caratteri. E possibile definire preventivamente i valori di ogni elemento della tabella, facendo seguire alle parole chiave int o char le parentesi quadre con il numero di elementi, il segno di uguale ed i valori, separati da una virgola e racchiusi tra parentesi graffe. Esempi: char saluto [ ] = "ciao"; // la variabile di tipo string denominata “saluto” contiene la parola “ciao” ed occupa 4 caratteri di testo + il carattere NULL e quindi 5 caratteri int mieiNumeri[6]; // dichiarazione di un array senza inizializzazione int mieiPin[ ]= {2,4,8,3,6}; // dichiarazione di un array senza definirne a dimensione. Il compilatore //conta gli elementi e crea un array avente dimensione adatta. int valoriSensori[6]={2,4,8,3,2,5}; // dichiarazione e inizializzazione di un array char messaggio[5]= “ciao”; // Dichiarazione ed inizializzazione di un array di char. Occorre un //carattere in più per definire il valore che determina la fine dell'array di caratteri. Accesso agli elementi di un array di int Gli indici degli array partono dallo 0, cioè il primo elemento occupa la posizione 0. In un array avente 10 elementi, l'indice 9 rappresenta l'ultimo della lista. Sintassi per leggere un valore in un array tipo var = mioArray[ n] ; var indica la variabile di lettura o di accesso; mioArray[n ] nome dell'array di cui si vuole accedere agli elementi n indica la posizione occupata. esempio int numeri[10]={3,4,6,8,5,12,15,7,9,13}; // definizione e inizializzazione dell'array chiamato numeri [ ] avente 10 elementi int x ; // inizializzazione della variabile x di tipo int x = numeri[0]; // x=3 x = numeri[9]; // x=13 x = numeri[10] ; // richiesta non valida. Contiene un numero casuale (altro indirizzo di memoria) Array di char Un array è un insieme di elementi tutti dello stesso tipo. Nel caso specifico, in un oggetto di tipo String, gli elementi dello stesso tipo sono char. Sintassi per dichiarare stringhe di caratteri char Str1[15]; // definisce un array di char lungo 15 caratter senza nessuna assegnazione char Str2[8]={'a','r','d','u','i','n',o'}; // i caratteri sono 7, la lunghezza dell'array definito è 8, durante la compilazione viene accodato un carattere nullo per arrivare alla lunghezza di 8 char Str3[8]={'a','r','d','u','i','n',o','/0'}; // esplicitamente viene aggiunto il carattere null (/0). char Str4[ ]= “arduino”; // in questo caso la sezione dell' array sarà definita dopo che il compilatore avrà fatto riempito l'array cioè fino al valore null della stringa char Str5[8]= “arduino”; char Str6[15]= “arduino”; stringa di inizializzazione. // inizializza l'array con esplicita sezione estringa costante // inizializza l'array con lunghezza 15 lasciando uno spazio extra dopo la ARRAY int Array[6]={2,4,8,3,2,5}; float ris; void setup() { Serial.begin(9600); } int flag=0; void loop() { if(flag==0){ for(int i=1; i<6; i++){ ris= Array[i-1]*Array[i]; Serial.println(ris); flag=1; } } } char* myStrings[]={"This is string 1", "This is string 2", "This is string 3", "This is string 4", "This is string 5","This is string 6"}; void setup(){ Serial.begin(9600); } void loop(){ for (int i = 0; i < 6; i++){ Serial.println(myStrings[i]); delay(500); } while (1); } // inizializzo le variabili necessarie per la compilazione del programma int value = 5; int tagArray[4]; int totale = 0; int i = 0; int OK = 10; int WARNING = 11; void setup() { pinMode(value,INPUT); //Imposto la variabile come ingresso Serial.begin(9600); } void loop() { Serial.print("Valori tabella: "); //Ogni 10ms memorizza il valore letto in un array (vettore) di numero i for (i=0; i<4; i++) { analogRead(value); tagArray[i]=value; Serial.print(tagArray[i]); Serial.print(" "); totale += tagArray[i]; delay(10); int media = totale/i; //Si esegue la media dei valori Serial.println(""); Serial.println("Media dei valori: "); Serial.print(media); if(media<409) { Serial.println("Tutto OK"); //Se la media ricavata è minore di 2v, non vi è errore OK = HIGH; WARNING = LOW; } else { Serial.println("WARNING!"); //Se la media ricavata è maggiore di 2v, c'è un pericolo WARNING = HIGH; OK = LOW; } delay(10); } } • Istruzione: Switch… case Il controllo switch si comporta come più if in cascata. È utilizzato per quei casi in cui la variabile può assumere più valori che devono essere controllati tutti (es. Che tasto ho premuto?) switch (variabile) { case 1: // istruzioni da eseguire quando la variabile assume valore 1 break; case 2: // istruzioni da eseguire quando la variabile assume valore 2 break; default: // istruzioni da eseguire quando la variabile non assume nessuno dei valori previsti } Consente di selezionare l’esecuzione tra gli N blocchi di istruzioni componenti, in base al valore di una espressione (solo con variabili intere, cioè senza virgola). Per terminare ogni "case" si utilizza l'istruzione "break" (che provoca l'uscita forzata dallo switch). È possibile specificare un’etichetta "default". Essa viene eseguita per qualunque valore diverso dai valori specificati in precedenza nei vari "case". /* Accensione e spegnimento di un led da tastiera del Personal Computer tramite interfaccia seriale Il led collegato con l'Anodo al pin 13 e il catodo a massa viene acceso un numero di volte compreso tra 1 e 4 digitando il corrispondente numero sulla tastiera del PC. P.S. utilizzare il "Serial Monitor" settato a 9600 baud e digitare il carattere seguito da un carattere INVIO oppure effettuando un clic sul pulsante denominato "Send". Si ricorda che il PC invia sulla seriale fittizia solo codici ASCII, quindi il carattere maiuscolo "A" verra' trasmesso sulla seriale viene ricevuto dal codice presente sulla scheda Arduino come un codice 0x41 (valore espresso in esadecimale per il linguaggio C) che corrisponde al valore decimale 65. data: 2 Marzo 2012 da G. Carpignano compilatore: IDE Arduino 0022 */ int led = 13; // il led e' collegato con l'Anodo sul pin 13 e il Catodo a GND. int leggi_byte, num_flash; void setup() { pinMode(led, OUTPUT); // configura il pin 13 come output Serial.begin(9600); // inizializza la seriale a 9600 baud Serial.flush(); // azzera buffer seriale } void loop() { // controlla se e' presente nel buffer della seriale un carattere ASCII while (!Serial.available()); leggi_byte = Serial.read(); // acquisisci il carattere e memorizzalo switch (leggi_byte) // confronta con i possibili valori { case '1': // caso relativo alla ricezione del carattere ASCII 1 num_flash = 1; // numero di volte che deve lampeggiare break; case '2': // caso relativo alla ricezione del carattere ASCII 2 num_flash = 2; // numero di volte che deve lampeggiare break; case '3': // caso relativo alla ricezione del carattere ASCII 3 num_flash = 3; // numero di volte che deve lampeggiare break; case '4': // caso relativo alla ricezione del carattere ASCII 4 num_flash = 4; // numero di volte che deve lampeggiare break; default: // caso relativo alla ricezione diverso da un numero valido num_flash = 0; // numero di volte che deve lampeggiare break; } // fine switch Serial.print(" --> LED ON/OFF per "); Serial.println(num_flash, DEC); // ritrasmetti il numero sulla seriale // ripeti la sequenza di accensione/spegnimento per il numero inserito da tastiera // accensione e spegnimento da tastiera int led1 = 4; int led2 = 7; int led3 = 12; char tastiera=0; void setup() { Serial.begin(9600); pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); } void loop() { tastiera = Serial.read(); switch(tastiera) { case 'a': digitalWrite(led1, 1); break; case 'b': digitalWrite(led1, 0); digitalWrite(led2, 1); digitalWrite(led3, 0); break; case 'c': digitalWrite(led1, 0); digitalWrite(led2, 0); digitalWrite(led3, 1); break; } } CASE void setup() { Serial.begin(9600); } void loop() { // if (Serial.available() > 0) { int dato = Serial.read(); // a seconda del carattere "a =97" 'b' = 98», si da una risposta diversa switch (dato) { case 'a': digitalWrite(2, HIGH); break; case 'b': digitalWrite(3, HIGH); break; case 'c': digitalWrite(4, HIGH); break; case 'd': digitalWrite(5, HIGH); break; case 'e': digitalWrite(6, HIGH); break; } } // } ISTRUZIONE WHILE() while(x < 10) { blocco di codice da ripetere x = x + 1; } L’espressione presente all'interno della parentesi tonda (condizione di ripetizione) viene valutata all’inizio di ogni ciclo. Se la condizione risulta VERA si eseguono tutte le istruzioni presenti tra le parentesi graffe. Se la condizione risulta FALSA (cioè se è uguale a zero) il programma salta all'esecuzione della prima istruzione dopo la parentesi graffa chiusa. Se inizialmente la condizione ha valore zero, il corpo del ciclo non viene mai eseguito. int led = 13; // definizione della variabile "led" utilizzata per scrivere sul pin 13 int pulsante = 7; // definizione della variabile "pulsante" utilizzata per leggere sul pin 7 void setup() // funzione di inizializzazione dei INPUT/OUTPUT { pinMode(led, OUTPUT); // inizializza il pin 13 come OUTPUT collegato al led pinMode(pulsante, INPUT); // inizializza il pin 7 come INPUT collegato al pulsante n.a. digitalWrite(pulsante, HIGH); // utilizza la R=10K di pull-up interna al microcontrollore } void loop() // programma principale (main) --> ciclo infinito (loop) { while(digitalRead(pulsante) == 1) // acquisisci il valore del pulsante pin 7 se il pulsante { // NON E' PREMUTO si avra' un livello ALTO quindi si deve spegnere il led digitalWrite(led, LOW); // spegni il LED collegato al pin 13 della scheda Arduino } digitalWrite(led, HIGH); // accendi il LED collegato al pin 13 della scheda Arduino } WHILE void setup() { Serial.begin(9600); } void loop() { int j = 1 ; while (j<=10) { // inizia il loop Serial.println(j); // scrivi j j=j+1; // incrementa di 1 } // fine del ciclo while(1); } int int int rossoacceso =1000; // tempo di accensione rossospento =500; // tempo di spegnimemnto limite =4; void setup() { Serial.begin(9600); pinMode(2 ,OUTPUT); } void loop() { int j=1; while (j<=limite) { Serial.print(" in fase di lampeggio #: "); Serial.println(j); digitalWrite(2,HIGH); delay(rossoacceso); digitalWrite(2,LOW); delay(rossospento); j=j+1; } } ISTRUZIONE DO … WHILE() Il controllo della condizione di ripetizione viene verificata alla fine di ogni ciclo Le istruzioni presenti tra le parentesi graffe vengono sempre eseguite almeno una volta. È come il ciclo while con la differenza che la condizione è controllata alla fine. do { x = readSensors(); // controlla il sensore } while (x < 100); /* Descrizione: calcola e stampa il fattoriale con l'istruzione do .... while */ void setup() // funzione di inizializzazione della seriale RS232 { Serial.begin(9600); } void loop() // programma principale (main) --> ciclo infinito (loop) { int fattoriale = 1; /* inizializzazione del fattoriale*/ int numero = 4; // valore massimo del fattoriale da calcolare int i=0; /* inizializzazione del contatore*/ do { // calcolo del numero fattoriale (ad esempio per il num. 4 si avra' 1*2*3*4 = 24 fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(numero, DEC); Serial.print(" e' il valore "); Serial.print(fattoriale, DEC); while (1); // blocca il programma (loop infinito) } DO WHILE int valore; void setup() { Serial.begin(9600); } void loop() { int flag=0; if(flag==0){ Serial.println("dammi un numero"); delay(5000); if (Serial.available() > 0) { valore = Serial.parseInt(); Serial.flush(); int fattoriale = 1; int numero = valore ; int i=0; do { fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(valore, DEC); Serial.print(" e' il valore "); Serial.println(fattoriale, DEC); flag = 0; delay(5000); //while (1); } } } Acquisizione numero esterno Per operazioni sui numeri utilizzare if (Serial.available() > 0) { valore = Serial.parseInt(); FUNZIONI Funzioni (parametri di ingresso e parametri di ritorno): Una funzione è un blocco di codice che ha un nome ben definito, quindi è un blocco di istruzioni che vengono eseguiti quando la funzione viene chiamata. Le funzioni sono utilizzate per eseguire operazioni ripetitive in modo da ridurre il codice programma ed evitare quindi confusione nel programma stesso. Le funzioni sono dichiarate all’inizio del programma e specificate dal tipo di funzione. La struttura della funzione è la seguente: Dichiarazione di funzione Sintassi: funzione divisione, somma, ecc… tipo nomeFunzione(parametro1, parametro2, …) oppure nome funzione, (parametro n ) { istruzioni da eseguire; (void) {….. istruzioni della routine ….. ; /* la routine viene eseguita solo nel momento in cui il percorso seguito dal programma incontra l’istruzione di lancio della routine (e cioe’ nome_della_routine (); ). A questo punto il programma esegue le istruzioni della routine e, al termine, ritorna al normale iter eseguendo le istruzioni immediatamente successive all’istruzione di lancio della routine */ 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. Le funzioni sono parti di codice a cui viene associato un nome. Le funzioni hanno principalmente tre funzioni Permettere una maggiore leggibilità del codice,, Evitare di riscrivere lo stesso codice, Possibilità di costruire librerie da poter utilizzare in differenti progetti Una funzione ha solitamente questa struttura: Tipo_dato_uscita NomeFunzione(tipi_ingressi NomeVariabile…) { Corpo della funzione } Arduino permette sia l’utilizzo di funzioni da librerie, sia la creazione di nuove funzioni. 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 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 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 ▪ /* utilizzo di due funzioni che effettuano la divisione e la moltiplicazione di due valori con parametri in ingresso e in uscita*/ void setup() { Serial.begin(9600); } void loop() { float i =3; // prima variabile con virgola float j = 2; //seconda variabile float k; // variabile che contiene il risultato float m; k = divisione(i, j); // la variabile k contiene il risultato m = moltiplicazione(i,j); Serial.println(k); // stampa Serial.println(m); // stampa } /* funzione che effettua la divisione e restituisce il risultato. Il primo parametro viene passato alla funzione con la variabile --> "float x". il secondo parametro viene passato alla funzione con la variabile --> "float y«’ terzo parametro (r1sultato della divis1one) viene restituito dalla funzione tramite la variabile "'risultato"' (anch'essa float divisione (float x, float y) { float risultato; // variabile che contiene il valore calcolato risultato = x / y; // calcolo della divisione e memorizzazione del risultato return risultato; // restituisce risultato } float moltiplicazione (float x, float y) { float risultato1; // variabile che contiene il valore calcolato risultato1 = x *y; // calcolo della divisione e memorizzazione del risultato return risultato1; // restituisce risultato } float) a K */ /* Progetto: variabile_locale_globale Descrizione: utilizzo delle variabili locali e globali con le funzioni */ int x = 3; /*VARIABILE GLOBALE, viene vista e modificata all'interno di qualsiasi funzione presente nel software */ int y = 7; /*VARIABILE GLOBALE, viene vista e modificata all'interno di qualsiasi funzione presente nel software*/ void setup() // funzione di inizializzazione della seriale RS232 { Serial.begin(9600); } /* funzione che permette lo scambio dei dati tra due variabili void scambio_valore() { utilizzando il valore */ int temp; // VARIABILE LOCALE, viene vista e considerata solo all'interno della funzione denominata scambio_valore(); temp = x; // poni il primo valore nella memoria di una terza variabile locale x = y; // memorizza il secondo valore nella prima variabile y = temp; // memorizza la variabile temporanea nel secondo valor } /* La funzione scambia i due valori utilizzando i puntatori (riferimento alla locazione di memoria delle variabili) deve essere utilizza nel seguente modo: scambio_puntatore(x,y); */ void scambio_puntatore(int &valore1, int &valore2) { int temp; // VARIABILE LOCALE, viene vista e considerata solo all'interno della funzione denominata scambio_valore(); temp = valore1; // poni il primo valore nella memoria di una terza variabile locale valore1 = valore2; // memorizza il secondo valore nella prima variabile valore2 = temp; // memorizza la variabile temporanea nel secondo valore } int sensore_T=A0; //inizializzo il sens di temperatura int sensore_livello=6; //inizializzo il sens dig di livello int m1=7; //inizializzo i motori int m2=8; int m3=9; int m4=10; int m_LM293=11; //inizializzo la pompa dell'acqua int m_LM293_2=12; int i; int somma=0; int media; int Tm=50; //imposto i limiti di temperatura int TM=63; int TM2=55; void setup() { Serial.begin(9600); //comunincazione seriale pinMode(sensore_livello, INPUT); pinMode(m1, OUTPUT); pinMode(m2, OUTPUT); pinMode(m3, OUTPUT); pinMode(m4, OUTPUT); pinMode(m_LM293, OUTPUT); pinMode(m_LM293_2, OUTPUT); } void loop() { sensore_digitale(); //funzione che permette di cambiare verso di spinta della pompa in base al sensore di livello for(i=0; i<=12; i++) { int sensore=analogRead(sensore_T); //funzione che permette di fare la media delay(2000); somma=somma+sensore; Serial.println("Sensore "); Serial.println(sensore); if(i==12) { media=somma/i; i=0; somma=0; Serial.println("media "); Serial.println(media); } } if(media<=Tm) //se media è minore di Tm tutte le valvole sono chiuse { digitalWrite(m1, LOW); digitalWrite(m2, LOW); digitalWrite(m3, LOW); digitalWrite(m4, LOW); digitalWrite(m_LM293, LOW); } if(Tm<media<=TM2) caso1(); if(TM2<media<=TM)//se è verificata tale condizione le valvole si attivano per i tempi aumentati del 30% caso2(); if(media>TM) //se è verificata tale condizione le valvole si attivano per i tempi aumentati del 50% caso3(); } void caso1() { digitalWrite(m_LM293, HIGH); digitalWrite(m1, HIGH); delay(2000); digitalWrite(m1, LOW); digitalWrite(m2, HIGH); delay(3000); digitalWrite(m2, LOW); digitalWrite(m3, HIGH); delay(3000); digitalWrite(m3, LOW); digitalWrite(m4, HIGH); delay(4000); digitalWrite(m4, LOW); } void caso2() { digitalWrite(m_LM293, HIGH); digitalWrite(m1, HIGH); delay(2600); digitalWrite(m1, LOW); digitalWrite(m2, HIGH); delay(3900); digitalWrite(m2, LOW); digitalWrite(m3, HIGH); delay(3900); digitalWrite(m3, LOW); digitalWrite(m4, HIGH); delay(5200); digitalWrite(m4, LOW); } void caso3() { digitalWrite(m_LM293, HIGH); digitalWrite(m1, HIGH); delay(3000); digitalWrite(m1, LOW); digitalWrite(m2, HIGH); delay(4500); digitalWrite(m2, LOW); digitalWrite(m3, HIGH); delay(4500); digitalWrite(m3, LOW); digitalWrite(m4, HIGH); delay(6000); digitalWrite(m4, LOW); } void sensore_digitale() { if(sensore_livello==HIGH) { digitalWrite(m_LM293, HIGH); digitalWrite(m_LM293, LOW); } else { digitalWrite(m_LM293, LOW); digitalWrite(m_LM293_2, HIGH); } } OPERAZIONI MATEMATICHE OPERATORI DI ASSEGNAZIONE x++; // è uguale a x = x + 1, incrementa la variabile x di +1 x--; // è uguale a x = x - 1, decrementa x di -1 x += y; // è uguale a x = x + y, incrementa x di + y x -= y; // è uguale a x = x - y, decrementa x di y x *= y; // è uguale a x = x * y, moltiplica x per y x /= y; // è uguale a x = x / y, divide x per y Se scrivo: value++, prima valuta la variabile value e poi la incrementa di 1. Se invece scrivo: ++value, prima incrementa di 1 e poi valuta. Operatori di confronto x == y // x è uguale a y x != y // x è diverso da y x<y // x è minore di y x > y // x è maggiore di y x <= y // x è minore o uguale a y x >= y // x è maggiore o uguale a y a = a + 1 si può scrivere a++ a = a + 2 si può scrivere a += 2 Lo stesso vale per – (meno meno). x = 2; x += 4; // x ora contiene 6 x - = 3; // x ora contiene 3 x *= 10; // ora contiene 30 x /= 2; // x ora contiene 15 Operatori d matematici + per le addizioni - per le sottrazioni / per le divisioni * per le moltiplicazioni = per l’assegnazione del risultato “%“ anziche’ calcolare una percentuale, restituisce il resto di una divisione. Sintassi result = valore1+valore2; result = valore1-valore2; result = valore1*valore2; result = valore1/valore2; FUNZIONI MATEMATICHE il linguaggio include funzioni matematiche alcune delle quali sono qui’ rappresentate. L’elenco completo delle istruzioni e delle funzioni e’ reperibile nella sezione “aiuto” dell’ambiente di sviluppo. gamma = min (alfa,beta); inserisce in gamma il valore minore tra i due valori contenuti nelle variabili alfa e beta val=min(50,30); // in val sara’ presente il valore 30 val = max(x,y); // inserisce in val il valore maggiore tra i valori contenuti in x e y val = abs(x); // inserisce in val il valore assoluto di x (toglie il segno a x) val = constrain(x,a,b); // x e’ un valore variabile; a e’ il minimo valore accettabile e b e’ il massimo valore accettabile. nserisce in val il valore x se x e’ compreso tra a e b; inserisce in val il valore a se x è minore di a; inserisce in val il valore b se x è maggiore di b. val = pow(base,esponente); // calcola una potenza e cioe’ inserisce in val la base elevata all’esponente. Attenzione: val deve essere una variabile di tipo double val = sqrt(x); // calcola la radice quadrata di x. Attenzione, val deve essere una variabile di tipo double. val = random (max) // inserisce in val un numero a caso compreso tra 0 ed il valore contenuto in max Poiche’ i numeri generati sono in realta’ pseudo casuali (fanno cioe’ parte di una enorme sequenza predefinita), per evitare di ripetere la medesima sequenza di numeri ad ogni avvio del programma e’ opportuno inizializzare il generatore di numeri a caso utilizzando l’istruzione: randomSeed(seme); // inizializza il generatore di numeri a caso Inserendo in seme un numero sempre diverso e quindi derivato, ad esempio, da una funzione di tempo applicata ad un’azione umana (come il tempo intercorso tra l’avvio del programma e la pressione di un pulsante) oppure il valore fornito da una porta analogica non utilizzata. In questo modo ad ogni avvio del sistema l’istruzione random () restituira’ numeri a caso in sequenze sempre diverse. TRIGONOMETRIA Calcola il seno di un angolo espresso in radianti. Il risultato sarà compreso tra -1 e 1. Sintassi double valore=sin(rad); valore è il risultato della funzione sin; rad rappresenta l'angolo in radianti di tipo float; La funzione restituisce il seno dell'angolo in formato double. Calcola il coseno di un angolo espresso in radianti. Il risultato sarà compreso tra -1 e 1. Sintassi double valore=cos(rad); valore è il risultato della funzione cos; rad: angolo in radianti di tipo float La funzione restituisce il coseno dell'angolo in formato double. Calcola la tangente di un angolo espresso n radianti. Il risultato sarà compreso tra meno infinito e più infinito. Sintassi double valore=tan(rad); valore è il risultato della funzione tan; rad è l'angolo espresso in radianti di tipo float La funzione restituisce la tangente dell'angolo espresso in double. OPERATORI TRA: BITS AND BYTES OR composto ( |= ) L'operatore composto di OR tra bit (|=) è spesso usato particolari bit in una variabile. x |= y ; // equivalente a x = x | y; Il parametro x è una variabile di tipo char, int long y invece una costante di tipo integer o char, int, o long tra una variabile e una costante che setta (mette a 1) Operatore logico Operatore tra bit && indica AND logico & indica AND tra bit || indica OR logico | ! indica il NOR logico ~ ! int a = 92; int b = 101; int c = a & b; Int c = a | b int z = a ^ b X o r int b = ~a; not indica OR tra bit indica il NOR tra bit operatore and e or tra bt // in binario : 0000000001011100 // in binario : 0000000001100101 // : 0000000001000100, o 68 in decimale APPLICAZIONI MATEMATICHE / BYTE Modulo %: sintassi result=dividendo%divisore: restituisce il resto della divisione x=7%5; // x contiene 2 x=9%4; // x contiene 1 in quanto 9/4=2 con resto 1 . l'operatore % non lavora su tipi float. Esempio /*aggiorna un valore in un array ogni volta che attraversa un ciclo */ int valori[10]; int i = 0; int pot=0; void setup( ) { } void loop( ) { valori[i] = analogRead(0); i = (i + 1) % 10; // operatore modulo ogni 10 volte aggiorna il valore di valori Serial.print(pot); } OPERATORI int Var = 10; int Result = 0; void setup() { Serial.begin(9600); } void loop() { //il valore Result sarà uguale a 50 Var = 50; Result = constrain(Var, 10, 100); // Restituisce x : se x è // compreso tra a e b // a se x è minore di a // b se x è maggiore di b Serial.println(Result); //il valore Result uguale a 10 Var = 5; Result = constrain(Var, 10, 100); Serial.println(Result); //il valore Result uguale a 100 Var = 500; Result = constrain(Var, 10, 100); Serial.println(Result); } int Var1 = 10; int Var2 = 50; int Result = 0; void setup() { Serial.begin(9600); } void loop() { //il valore Result sarà uguale a 10 Result = min(Var1, Var2); Serial.print(Result); //non fa nulla while(true); } int Var1 = 10; int Var2 = 50; int Result = 0; void setup() { Serial.begin(9600); } void loop() { //il valore Result sarà uguale a 10 Result = min(Var1, Var2); Serial.print(Result); //non fa nulla while(true); } float num1 , num2, ris; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); ris =sqrt(num1); Serial.println("il risuiltato e: Serial.println(ris); while(true); } "); float num1, num2, ris, ris1 int scelta=0; ; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt();//riceve in input un numero intero(da tastiera) Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt();//riceve in input un numero intero(da tastiera) Serial.flush(); if(num1>=num2) Serial.println("Numero 1 è maggiore di numero 2"); else Serial.println("Numero 1 minore di numero 2"); ris=(num1+num2); ris1=(num1*num2); Serial.print("IL RISULTATO E: "); // stampa Serial.println(ris); // stampa il risultato Serial.print("IL RISULTATO E: "); // stampa Serial.println(ris1); // stampa il risultato delay(5000); // tempo di ritardo 5000 msec. = 5 sec. } float num1, num2, num3, Array[5], ris; int scelta=0; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) Array[0] =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[1] =Serial.parseInt();//riceve in input un numero da tastiera Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[2] =Serial.parseInt();//riceve in input un numero da tastiera Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[3] =Serial.parseInt();//riceve in input un numero da tastiera) Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[4] =Serial.parseInt(); //riceve in input un numero da tastiera) Serial.flush(); ris= Array[0]; for(int i=1; i<5; i++){ if(Array[i]<ris) ris= Array[i]; } Serial.print("IL MINIMO E: "); Serial.println(ris); } float num1, num2, num3, Array[5], ris; int scelta=0; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci la base: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci l'esponente: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); ris = 1; for(int i=0; i<num2; i++){ ris = ris * num1; } Serial.print("IL RISULTATO E: "); Serial.println(ris); } void setup() { Serial.begin(9600); } void loop() { int flag=0; if(flag==0){ Serial.println("dammi un numero"); delay(5000); if (Serial.available() > 0) { int valore = Serial.parseInt(); Serial.flush(); int fattoriale = 1; int numero = valore ; int i=0; do { fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(valore, DEC); Serial.print(" e' il valore "); Serial.println(fattoriale, DEC); flag = 0; while (1); } } } float num1, num2, num3, Array[5], ris; int scelta=0; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci la base: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci l'esponente: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); ris = 1; for(int i=0; i<num2; i++){ ris = ris * num1; } Serial.print("IL RISULTATO E: Serial.println(ris); } "); // stampa float num1, num2, ris ; int scelta=0; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt();//riceve in input un numero da tastiera Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt();//riceve in input un numero da tastiera Serial.flush(); if(num1==num2) Serial.println("NUM1 E NUM2 sono uguali "); else Serial.print("NUM1 E NUM2 sono diversi "); } float num1, num2, num3, Array[5], ris; int scelta=0; void setup() { Serial.begin(9600); } void loop() { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) Array[0] =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[1] =Serial.parseInt(); //riceve in input un numero da tastiera Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[2] =Serial.parseInt(); //riceve in input un numeroda tastiera Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[3] =Serial.parseInt(); //riceve in input un numeroda tastiera) Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) Array[4] =Serial.parseInt(); //riceve in input un numero da tastiera) Serial.flush(); ris= Array[0]; for(int i=1; i<5; i++){ if(Array[i]<ris) ris= Array[i]; } Serial.print("IL MINIMO E: "); Serial.println(ris); } void setup() { Serial.begin(9600); } void loop() { int flag=0; if(flag==0){ Serial.println("dammi un numero"); delay(5000); if (Serial.available() > 0) { int valore = Serial.parseInt(); Serial.flush(); int fattoriale = 1; int numero = valore ; int i=0; do { fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(valore, DEC); Serial.print(" e' il valore "); Serial.println(fattoriale, DEC); flag = 0; while (1); } } void setup() { Serial.begin(9600); } void loop() { int fattoriale = 1; /* inizializzazione del fattoriale*/ int numero = 4; // valore massimo del fattoriale da calcolare int i=0; /* inizializzazione del contatore*/ do { // calcolo del numero fattoriale (per 4 si avra' 1*2*3*4 = 24) fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(numero, DEC); Serial.print(" e' il valore "); Serial.print(fattoriale, DEC); while (1); } float num1,num2, num3, ris, ris1; int scelta=0; long randNumber; int val = 60; float Var = 10.6598; byte valore = 10; // variabile a 8 bit con il numero da controllare se pari o dispari byte valore1; void setup() { Serial.begin(9600); } void loop() { Serial.println("Scegliere l'operazione da svolgere premendo:"); Serial.println("[1] per la and"); Serial.println("[2] per la or"); Serial.println("[3] per la not"); Serial.println("[4] constrain"); Serial.println("[5] casuale"); Serial.println("[6] minmax"); Serial.println("[7] mappatura"); Serial.println("[8] eliminazione"); Serial.println("[9] paridispari"); Serial.println("[10] pardispar"); input(); operazioni(); } void input(){ while(scelta<=0 || scelta>=10){ if(Serial.available()>0){ scelta=Serial.parseInt();//riceveun numero intero(da tast) } } } void operazioni(){ switch(scelta){ case 1: faiand(); break; case 2: faior(); break; case 3: fainot(); break; case 4: constrain_(); break; case 5: casuale(); break; case 6: minmax (); break; case 7: mappatura (); break; case 8: eliminazione (); break; case 9: // paridispari(); break; case 10: // pardispar(); break; } scelta=0; } void faiand (){ Serial.println("Inserisci primo bit: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt();//rende l'input un intero Serial.flush(); Serial.println("Inserisci secondo bit: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush();/non dare errori di lettura dal bufffer if(num1==1 && num2==1) Serial.println("1"); else Serial.println("0"); } void faior (){ Serial.println("Inserisci primo bit: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt();//rende l'input un intero Serial.flush(); Serial.println("Inserisci secondo bit: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); if(num1==0 && num2==0) Serial.println("1"); else Serial.println("0"); } void fainot (){ Serial.println("Inserisci primo bit: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt();//rende l'input un intero Serial.flush(); if(num1==0) Serial.println("1"); else Serial.println("0"); } void constrain_(){ Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num3 =Serial.parseInt(); Serial.flush(); ris=constrain(num1,num2,num3); Serial.println(ris); // stampa il risultato delay(1000); } void casuale( ) { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); randNumber = random(num1, num2);// stampa un numero random da 10 a 19 Serial.println(randNumber); delay(50); } void minmax ( ) { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); ris = min(num1 , num2); ris1 = max(num1 , num2); Serial.print(" Il minimo e: "); Serial.println(ris); Serial.print(" Il massimo e: "); Serial.println(ris1); } void mappatura ( ) { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) num1 =Serial.parseInt(); Serial.flush(); Serial.println("Inserisci un altro numero: "); delay(5000); if(Serial.available()>0) num2 =Serial.parseInt(); Serial.flush(); ris = map(val, num1, num2, 0, 255); Serial.print(" Il valore mappato e: "); Serial.println(ris1); } void eliminazione () { // arrotonda per difetto ris = floor(Var); Serial.println(ris); // arrotonda per accesso ris1 = ceil(Var); Serial.println(ris1); } void paridispari( ) /*la condizione viene verificata se e' uguale a 0, ma prima viene effettuata l'AND (&) con la variabile "valore", cioe' si avra' 10 & 1 che vale in binario "00001010" & "00000001" diventa, effettuando la logica AND su ogni singolo bit "00000000" che corrisponde a 0.*/ if ((valore & 1) == 0) // se il confronto vale 0 { // si e' in presenza di un numero PARI Serial.print("Il numero "); Serial.print(valore, DEC); Serial.print(" e' PARI."); } else { // altrimenti il numero e' DISPARI Serial.print("Il numero "); Serial.print(valore, DEC); Serial.print(" e' DISPARI."); } } void pardispar( ) { { Serial.println("Inserisci un numero: "); delay(5000); if(Serial.available()>0) valore1 = Serial.read(); Serial.flush(); if ((valore1 & 1) == 0) // se il confronto vale 0 { // si e' in presenza di un numero PARI Serial.print("Il numero "); Serial.print(valore1, DEC); Serial.print(" e' PARI."); } else { // altrimenti il numero e' DISPARI Serial.print("Il numero "); Serial.print(valore1, DEC); Serial.print(" e' DISPARI."); } } } void setup() { Serial.begin(9600); } void loop() { int flag=0; if(flag==0){ Serial.println("dammi un numero"); delay(5000); if (Serial.available() > 0) { int valore = Serial.parseInt(); Serial.flush(); int fattoriale = 1; int numero = valore ; int i=0; do { fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(valore, DEC); Serial.print(" e' il valore "); Serial.println(fattoriale, DEC); flag = 0; while (1); } } void setup() { Serial.begin(9600); } void loop() { int fattoriale = 1; /* inizializzazione del fattoriale*/ int numero = 4; // valore massimo del fattoriale da calcolare int i=0; /* inizializzazione del contatore*/ do { // calcolo del numero fattoriale (per 4 si avra' 1*2*3*4 = 24) fattoriale = (i + 1) * fattoriale; i = i + 1; } while (i < numero); Serial.print("Il fattoriale del numero "); Serial.print(numero, DEC); Serial.print(" e' il valore "); Serial.print(fattoriale, DEC); while (1); } BIT E BYTE void setup() { Serial. begin (9600 ); } void loop() { Serial.print( "Logica AND --> 3 && l uguale " ); // bitwise della logica AND tra il valore 3 e 1 Serial.print(3 & 1) ; // stampa Del risultato l in decimale Serial.print(" decimale, oppure in binario: " ) ; Serial.println(3 & 1 , BIN) ; // stampa in binario 00000011 & 00000001 --> 00000001 Serial.print("Logica OR --> 5 || 3 uguale " ); // bitwise della logica OR tra il valore 5 e 3 Serial.print(5 || 3 ) ; // stampa del risultato in decimale Serial.print(" decimale , oppure in binario: " ); Serial.println(5 || 3 , BIN) ;// Il stampa in binario 00000101 || 00000011 --> 00000111 Serial.print("Logica EX- OR --> 5 ^ 3 uguale " ); // bitwise della logica EX-OR tra il valoire 5 e 3 Serial.print(5^ 3) ; // stampa del risultato in decimale Serial.print(" decimale, oppure in binairio: " ); Serial.println(5 ^ 3, BIN) ; //stampa in binario 00000101 " 00000011 --> 00000110 byte byteValore = 1; unsigned int intValore = 1 ; unsigned long longValore = 1; byteValore = -byteValore; // bitwise della logica NOT su una variabile a 8 bit intValore = -intValore; // bitwise della logica NOT su una variabile a 16 bit longValore = -longValore; // bitwise della logica NOT su UNa variabile a 32 bit Serial.print("Logica NOT con variabile tipo 'BYTE = l' --> -byteValore (8 bit) uguale " ) ; Serial.println (byteValore, BIN); //stampa il risultato in binario Serial.print("Logica NOT con variabile tipo INT = l ' --> -intValore (16 bit) uguale " ) ; Serial.println(intValore, BIN) ; //stampa il risultato in binario Serial.print("Logica NOT con variabile tipo 'LONG = l' --> - intValore (32 bit) uguale " ) ; Serial. println (longValore, BIN); //stampa il risultato in binario while (1); }