Generalità Laboratorio Arduino
Accendere un LED LED = Light Emitter Diode Tensione = 1.8 V Corrente = 10 mA Resistenza in serie = (5−1.8)𝑉 15𝑚𝐴 =213 Ω Anodo (+) Catodo (-)
Codice colore delle Resistenze Esempi: Rosso _ Rosso – Nero- Nero + (Marrone) = 220 ohm Marrone – Nero – Nero – Marrone + (Marrone) = 1 Kohm Marrone – Nero- Nero – Rosso + (Marropne) = 10 Kohm Marrone – Nero – Nero – Arancio + (Marrone) = 100 Kohm
Breadboard - Collegamenti
ARDUINO Sistema di controllo basato su Microcontrollore (ATmega328) 14 PIN dedicati a I/O digitale (6 configurabili in PWM) 6 ingressi analogici Alcuni PIN possono essere dedicati a funzioni particolari
Collegamento con Arduino Collegamento diretto: Collegare l’anodo (+) del LED a 5 V Collegare la resistenza a GND
Collegamento con Arduino Collegamento controllato da ARDUINO: Collegare l’anodo (+) del LED a P13 Collegare la resistenza a GND
Come far lampeggiare il LED const int LED = 12; // LED connected to digital pin 12 void setup() { pinMode(LED, OUTPUT); // sets the digital pin as output } void loop() digitalWrite(LED, HIGH); // turns the LED on delay(1000); // waits for a second digitalWrite(LED, LOW); // turns the LED off
Usiamo i pulsanti Connessioni dei pulsanti
Come generare un segnale digitale Come generare un segnale HIGH/LOW tramite un pulsante ? Introduciamo una resistenza (pulldown) Quando il pulsante è premuto la tensione sul PIN sarà 5V Quando il pulsante è rilasciato la tensione sarà 0V (GND)
Esempio di collegamento LED: Pin OUT=P9 BUTTON: Pin IN = P7
Il LED si accende se il pulsante è premuto const int LED = 9; const int BUTTON = 7; int stato; void setup() { pinMode(LED, OUTPUT); pinMode(BUTTON, INPUT); } void loop() { stato=digitalRead(BUTTON); if (stato==1) {digitalWrite(LED, HIGH);} else {digitalWrite(LED, LOW);}
Funzione bistabile Come modificare il codice precedente per far si che Premendo una volta il led si accenda Premendo una seconda il led si spenga …. In pratica si deve riconoscere la transizione dello stato invece che lo stato stesso
Funzione bistabile … int stato_attuale,stato_passato; int luce; void setup() { luce=0; } void loop() { stato_attuale=digitalRead(BUTTON); if ((stato_attuale-stato_passato)==1) {luce=1-luce;} digitalWrite(LED, luce); stato_passato=stato_attuale;
Rimbalzi Può capitare che per “rimbalzi” meccanici il Sistema rilevi più transizioni durante la medesima pressione Come implementare un Sistema “anti-rimbalzo” ? IDEA: ad esempio introducendo un ritardo nel ciclo ! Si fa passare un po’ di tempo tra una rilevazione e la successive! Questo non sia troppo breve (altrimenti non ha effetto) E non sia troppo lungo (altrimenti non rileva pressioni in rapida successione del pulsante Un valore “onesto” può essere 1/10 sec
Macchina a stati finiti (FSM) Nel caso precedente esitevano 2 stati (luce ON e luce OFF) Come modificare il codice per ottenere ad esempio 3 stati ? Premo il pulsante una volta: la luce si accende Premo una seconda volta: la luce lampeggia Premo una terza volta: la luce si spegne
Tre stati (acceso- lampeggio-spento) const int LED = 9; const int BUTTON = 7; int pulsante_attuale,pulsante_passato,stato,luce1,luce2; void setup() { pinMode(LED, OUTPUT); pinMode(BUTTON, INPUT); stato=0; } void loop() { pulsante_attuale=digitalRead(BUTTON); if ((pulsante_attuale-pulsante_passato)==1) stato=stato+1; if (stato==3) stato=0; if (stato==0) {luce1=0;luce2=0;} if (stato==1) {luce1=1;luce2=0;} if (stato==2) {luce1=1;luce2=1;} digitalWrite(LED, luce1); delay(10); digitalWrite(LED, luce2); delay(100); pulsante_passato=pulsante_attuale;
Duty cycle Nel caso precedente modifichiamo i ritardi e riducendoli di un fattore 10: Cosa accade ? In verità il led sta lampeggiando, ma ad una frequenza così elevate che l’occhio non la percepisce Modificando il “duty cycle” ovvero il rapporto tra il tempo di accensione ed il tempo di spegnimento si può modificare la luminosità del led.
Codifica PWM (Pulse Width Modulation) Diverse ampiezze vengono codificate con un duty cycle proporzionale L’ambiente Arduino lo tutto ciò fa automaticamente con la funzione Analogwrite (solo per i pin “~”) Il valore in ingresso va da 0 (spento) a 255 (acceso) Modifichiamo il codice precedente per accendere il LED a diverse intensità sfruttando questa funzione Nota: si possono modificare le proprietà del PWM agendo sui registri interni del Controllore ES: analogWrite(LED, 128)
Tre stati (acceso-debole-spento) const int LED = 9; const int BUTTON = 7; int pulsante_attuale,pulsante_passato,stato,luce; void setup() { pinMode(LED, OUTPUT); pinMode(BUTTON, INPUT); stato=0; } void loop() { pulsante_attuale=digitalRead(BUTTON); if ((pulsante_attuale-pulsante_passato)==1) stato=stato+1; if (stato==3) stato=0; if (stato==0) {luce=0;} if (stato==1) {luce=64;} if (stato==2) {luce=255;} analogWrite(LED,luce); pulsante_passato=pulsante_attuale;
Ingresso analogico Similmente è possibile leggere un ingresso analogico Si devono utilizzare i piedini dedicati (A0-A7) Nota: L’ingresso analogico è un vero segnale a livelli L’uscita anlogica viene “emulata” attraverso la codifica PWM
Uso del “console monitor” E’ possibile per Arduino scrivere stringhe di caratteri Utilizza un particolare protocollo seriale (RS232) che fa riferimento a due segnali TX e RX (collocate sui pin 0 e 1) La scheda è predisposta per collegarsi a tali segnali e portarli attraverso la connessione USB al PC Tali dati possono essere visualizzati attraverso il Monitor (Tool > Serial Monitor) void setup() { Serial.begin(9600); // inizializzazione } void loop() Serial.println(val); // visualizzazione
Lettura della luminosità Lettura di un segnale analogico e visualizzazione dei dati su monitor Si realizzi un partitore resistivo tra la fotoresistenza ed una resistenza fissa da 1Kohm Buio : fotores = 7000 ohm V= 0.87 Vmax Luce intense : fotores = 200 ohm V = 0.17 Vmax int analogPin = 0; int val = 0; void setup() { Serial.begin(9600); } void loop() val = analogRead(analogPin); Serial.println(val);
Processing E’ un ambiente di sviluppo simile ad Arduino Presenta funzioni grafiche evolute e facili da richiamare
Processing (esempio dinamico) Funzioni setup{} e draw {} Funzioni legate allo stato del Mouse Funzione per disegnare (o meno) il background
Facciamo dialogare Arduino e Processing Arduino scrive sulla porta seriale
Processing legge e stampa
Da Processing ad Arduino
… e Arduino legge Controllo se c’e’ un messaggio Decodifico il messaggio Se il messaggio è 1 accendo il LED Se il messaggio è 0 spengo il LED
…ora una sequenza di valori
Che Arduino Interpreta
Usiamo un ingresso analogico
Per muovere un quadrato …
Utilizzo delle librerie Molti dispositivi sono corredati di opportune librerie per un loro impiego più versatile e comodo. Es. “Micro servo SG90” (generare un PWM con le specifiche corrette richiederebbe conoscenze e competenze approfondite) #include <Servo.h> .... Servo myservo; void setup() { myservo.attach(PIN); } void loop() ... New = map(old, low_old, high_old, low_new, high_new); myservo.write(pos);
Sensore di umidità e temperatura E’ un dispositivo complesso Si Interfaccia attraverso opportuni sensori Converte la misura in formato digitale Gestisce le comunicazioni Adotta un protocollo di comunicazione bidirezionale con un solo filo (res. di pull-up) Viene fornita una libreria per Arduino ES: dht11.h #define DHTLIB_OK 0 #define DHTLIB_ERROR_CHECKSUM -1 #define DHTLIB_ERROR_TIMEOUT -2 class dht11 { public: int read(int pin); int humidity; int temperature; };
Misura di temperatura ed umidità include <dht11.h> dht11 DHT; #define DHT11_PIN 9 void setup(){ Serial.begin(9600); Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)"); } void loop(){ int chk; Serial.print("DHT11, \t"); chk = DHT.read(DHT11_PIN); // READ DATA switch (chk){ case DHTLIB_OK: Serial.print("OK,\t"); break; case DHTLIB_ERROR_CHECKSUM: Serial.print("Checksum error,\t"); case DHTLIB_ERROR_TIMEOUT: Serial.print("Time out error,\t"); default: Serial.print("Unknown error,\t"); // DISPLAT DATA Serial.print(DHT.humidity); Serial.print(",\t"); Serial.println(DHT.temperature); delay(1000);
Servo comando controllato dalla luce Si colleghi il sensore di luminosità come prima Si colleghi opportunamente il servo motore #include <Servo.h> int analogPin = 0; int val = 0; Servo myservo; void setup() { myservo.attach(9); } void loop() val = analogRead(analogPin); val = map(val, 200 , 800, 0, 180); myservo.write(val); delay(15);
Sensori evoluti (Giroscopio) Cos’è un giroscopio ? Un dispositivo atto a stabilire l’orientazione nello spazio di un oggetto in movimento Fondamentale per stabilizzare l’assetto di Aerei, Elicotteri, Droni, Sottomarini, Missili, Siluri, … In passato erano meccanici e sfruttavano il principio di “Conservazione del Momento di Quantità di Moto” Ovvero un disco che ruota nello spazio tende a mantenere la stassa orientazione fino a che non intervengano torsioni esterne atte a modificarlo. Se montato su un opportuno supporto si possono eliminare tali torsioni. Se montato su una piattaforma mobile (es.Drone), misurando gli angoli si può risalire all’orienzamento del drone stesso… e quindi agire sui propulsori per stabilizzarlo lungo una orientazione predefinita Ha da sempre affascinato l’uomo per il suo comportamento curioso (dalle “vecchie trottole” ai più moderni “fidget spinner”)
Sensori evoluti (Giroscopio) Il giroscopio sull’ Apollo 13
Un giroscopio Oggi Sfrutta le moderne tecnologie di micro-meccanica e micro-elettronica
MPU6050 3 giroscopi (secondo i 3 assi) 3 accellerometri (secondo i 3 assi) 1 Sensore di Temperatura 1 Processore (MPU – Motion Processing Unit) Fornisce ad esempio gli angoli di Eulero Rollio (Roll) Beccheggio (Pitch) Imbardata (Yaw) Costo 0.92 Euro
MPU6050 Collegamento fisico: SDA : su A4 o su SDA SCL : su A5 o SCL INT: su D2 GND su GND VCC su +5V
MPU6050 Tutti I dati vengono forniti col protocollo I2C Usa i collegamenti SDA e SCL Il Sistema fornisce un Interrupt quando i dati sono disponibili Il codice per Arduino disponibile sul sito Moodle consente, facendo uso di 2 opportune Librerie Di scrivere in chiaro I valori di YRP dierttamente su Console Di comporre I valori come BYTE in un pacchetto da inviare su Seriale (da inviare a Processing) Di comporre I valori dei “quaternioni” in un pacchetto da Inviare a Processing Codice Arduino: I_MPU6050ToProcessing.ino NOTA BENE: Commentare o togliere il commento dalla riga opportuna #define OUTPUT_READABLE_YAWPITCHROLL // #define OUTPUT_TEAPOT // #define OUTPUT_BYTE_YAWPITCHROLL Librerie x Arduino: MPU6050 e I2Cdev
MPU6050 Codice per Processing Visualizzare un quadrato che cambia orientamento e tinta secondo Yaw e Posizione secondo Roll e Pitch: L-quadrato_rotante_mpu6050.pde Visualizzare un CUBO in 3D Orientato con YRP: L-cubo_rotante_mpu6050.pde Orientato con I quaternioni: M-MPU6050_quaternion.pde
Blocco Cardanico (Gimball Lock) Imbardata Beccheggio Rollio Nei giroscopi meccanici bastava misurare I 3 angoli per avere direttamente I valori di rollio, beccheggio ed imbardata
Blocco Cardanico (Gimball Lock) Imbardata Beccheggio Rollio Ma cosa accade se due assi si allineano ?
Blocco Cardanico (Gimball Lock) Ma cosa accade se due assi si allineano ? - si perde un grado di libertà (non si può più distinguere tra rollio e imbardata)
Controllare un motore Noi prenderemo in considerazione due tipi di motori In corrente continua Motori passo-passo (stepper) Entrambi in genere richiedono più corrente di quanta possa essere erogata dalla scheda Arduino, pertanto per pilotarli si utilizzerà un driver.
Motori in Continua (DC) Sono molto semplici Presentano solo due fili A,B A = B = LOW : il motore è fermo A = B = HIGH : Il motore è fermo A = HIGH, B=LOW : il motore gira in un senso A = LOW, B = HIGH: il motore gira in senso inverso LOW in genere è 0V HIGH è la tensione del motore (5V oppure 12V oppure 24V) Per controllare la velocità si può usare il PWM modificando il duty cycle
Driver per motori DC Utilizzo di un ponte ad H La corrente al motore arriva da una Alimentazione opportuna Gli “interruttori” possono essere controllati tramite Arduino
Driver L293 Può pilotare due motori in modo bidirezionale 4 Ingressi (IN1 ... IN4) 2 Ingressi di Enable (utili per controllare la velocità) 4 Uscite (Out1 ...Out4)
Motori Passo-Passo Sono molto precisi (in posizione) ma hanno poca coppia Sono più lenti dei motori DC Possono avere 4,5, 6 o 8 Fili
Funzionamento motori PP Presenta un magnete permanente sul rotore E due avvolgimenti sullo statore In base a come questi sono alimentati si può modificare la posizione del rotore Pilotaggio a 1 fase Pilotaggio a 2 fasi
Funzionamento motori PP Sfruttando entrambe le soluzioni si può eseguire un avanzamento di ½ passo
Accedere agli avvolgimenti In verità gli avvolgimenti sono più di 4 in modo da far compiere al motore passi minori di 90 gradi, ma sempre riuniti tra di loro
Driver per motori PP Si può sempre far uso del circuito L293 per controllare un singolo motore PP nei suoi due avvolgimenti.
Libreria per Arduino “Stepper” La libreria fornita con Arduino è semplice ma limitata Pilota i motori (unipolari e bipolari) a due fasi Comandi: Stepper(steps, pin1, pin2, pin3, pin4) – definisce l’istanza setSpeed(rpms) – configure la velocità step(steps) – definisce il numero di passi Pilota un solo motore alla volta (BLOCKING COMMAND)
Libreria per Arduino “Stepper” Esempio #include <Stepper.h> const int stepsPerRevolution = 2048; Stepper myStepper1(stepsPerRevolution, 8, 10, 9, 11); Stepper myStepper2(stepsPerRevolution, 4, 6, 5, 7); void setup() { myStepper1.setSpeed(10); myStepper2.setSpeed(10); } void loop() { myStepper1.step(stepsPerRevolution); myStepper2.step(-stepsPerRevolution); delay(500); myStepper1.step(-stepsPerRevolution); myStepper2.step(+stepsPerRevolution);
Libreria “AccelStepper” Sviluppata dalla AirSpayce propone molte funzioni in più La gestione dei motori avviene in modo diverso (si propone un target e si fa partire il motore, eventualmente controllandone il processo) – Può muovere più motori contemporaneamente Alcune funzioni: setMaxSpeed (float speed) setAcceleration (float acceleration) setSpeed (float speed) moveTo (long absolute) distanceToGo () currentPosition () stop () run () Ulteriori informazioni: http://www.airspayce.com/mikem/arduino/AccelStepper/index.html
Libreria “AccelStepper” - Esempio #include <AccelStepper.h> #define FULLSTEP 4 #define HALFSTEP 8 AccelStepper stepper1(HALFSTEP, 8, 10, 9, 11); AccelStepper stepper2(HALFSTEP, 4, 6, 5, 7); void setup() /****** SETUP: RUNS ONCE ******/ { stepper1.setMaxSpeed(1000.0); stepper1.setAcceleration(50.0); stepper1.setSpeed(200); stepper1.moveTo(8000); stepper2.setMaxSpeed(1000.0); stepper2.setAcceleration(50.0); stepper2.setSpeed(200); stepper2.moveTo(-8000); }//--(end setup )--- void loop() /****** LOOP: RUNS CONSTANTLY ******/ //Change direction at the limits if (stepper1.distanceToGo() == 0) stepper1.moveTo(-stepper1.currentPosition()); if (stepper2.distanceToGo() == 0) stepper2.moveTo(-stepper2.currentPosition()); stepper1.run(); stepper2.run(); }//--(end main loop )--- Esempio
ESP8266 E’ un moduletto integrato per la connessione WiFi Dialoga con Arduino in Seriale (TX e RX) I comandi seriali servono Per configurarlo (segnali AT) Per gestire le comunicazioni Si può configurare come Station (crea la sua rete WiFi) Come AP (access Point) – per collegarsi a reti WiFi già esistenti (Ad Es per mandare mail) Il suo IP di default è 192.168.4.1 Alimentato a 3.3 V Il Piedino di ch_pd va posto al livello alto
WiFi Connection (ESP8266) Attenzione: Il modulo va alimentato a 3.3 V Il segnale TX di Arduino va abbassato da 5V a 3.3V con un partitore resitivo di 500 ohm e 1 Kohm La gestione del moduletto passa attraverso l’uso di opportune librerie