L'articolo fa parte delle tre puntate focalizzate sui sistemi embedded, quali Arduino e Raspberry Pi. In questa seconda puntata ci occuperemo della realizzazione di un sistema trasmissione e ricezione di segnali digitali ed analogici utilizzando Arduino, xBee e pochi altri semplici componenti. Aspetti legati alla realizzazione hardware, ovvero il collegamento dei diversi componenti sulla breadboard (il kit base sarà più che sufficiente), ed all'implementazione software, ovvero i due sorgenti che saranno eseguiti sui microcontrollori, saranno ampiamente discussi nel corso dell'articolo. A modi di esempio, l'articolo presenta come accendere, spegnere e regolare la luminosità di alcuni LED. L'esempio mostra come leggere ed inviare segnali analogici e digitali, ed è alla base del controllo di un qualunque sistema robotico. L'articolo termina con i sorgenti utilizzati per l'esempio mostrato.
Introduzione
In questa seconda - per chi si fosse perso la prima, questo è il link - puntata dedicata ai sistemi embedded, Arduino e Raspberry Pi per intenderci, il focus è orientato alla realizzazione di un sistema di ricezione/trasmissione con Arduino (ne serviranno due, un trasmettitore ed un ricevitore) e pochi semplici componenti (dei LED, dei bottoni, ed alcune resistenze). L'applicazione si pone l'intento di dimostrare, attraverso un esempio abbastanza semplice, le potenzialità di questo strumento. In particolare, l'articolo affronta sia gli aspetti hardware (la configurazione dei componenti, le loro connessioni sulla breadboard) che quelli meramente software (il codice che verrà eseguito sulle due Arduino board). Il risultato finale del progetto sarà un sistema Arduino in grado di inviare sia segnali PWM (Pulse Width Modulation) che digitali (ON/OFF) da un Arduino all'altro. L'esempio è alla base di applicazioni più complesse, quali il controllo di un robot. Difatti, collegare un joystick non è poco dissimile dall'esempio trattato. Per completezza, all'interno dell'articolo viene fornito anche il codice per il microcontrollore. Più ampie trattazioni sull'argomento sono disponibili a questi link (link1, link2 e link3).
Hardware
In questa sezione vengono elencate le componenti hardware utilizzate per la realizzazione del progetto. Per completezza, per ognuna di esse viene fornito anche il link ad un e-commerce:
- 2x Arduino Uno
- 2x xBee Radio (per l'esempio è stata utilizzata la serie 1, assicurarsi che la board a disposizione sia dello stesso tipo. Il codice sorgente e la configurazione hardware non sono compatibili con la seconda e terza serie)
- 2x schede breakout xBee
- 1x xBee explorer
- 2x computer (nelle prove utilizzate per la realizzazione di questo articolo, per praticità, sono stati utilizzati due computer, uno per il ricevitore, e l'altro per il trasmettitore. È possibile utilizzare anche un solo dispositivo, avendo però cura di modificare il numero di porta seriale del cavo USB utilizzato per la comunicazione con il microcontrollore)
- 2x potenziometri (quelli del kit base di Arduino vanno più che bene)
- 1x pulsante (vale quanto detto per i potenziometri)
- 3 resistenze da 330 Ohm (in questo articolo sul blog, una guida su come leggere i valori di resistenza usando le bande colorate)
- 1x resistore da 10 kOhm
- 3x LED
- 2x breadboard
- diversi cavi di collegamento
Come anticipato nell'introduzione dell'articolo, per il trasmettitore è stato utilizzato un Arduino con due potenziometri ed un pulsante (vedi Figura 1). Al suo posto, ovviamente, può essere collegato anche un joystick o un qualunque dispositivo di input. Qualunque sia il dispositivo, i valori di resistenza dei segnali di input devono essere sufficientemente grandi (in gergo tecnico, ad alta impedenza) da garantire un perfetto circuito aperto in caso di inutilizzo (segnale digitale basso). Per lo scenario in considerazione 10 kOhm sono più che sufficienti.
Trasmettitore
In Figura 1 è riportato lo schema per il collegamento dei diversi componenti, mentre a fondo articolo si trova il listato del codice utilizzato per il trasmettitore ed il ricevitore. Come si vede dallo schema, i due potenziometri (dispositivi analogici) sono collegati agli ingressi A0 ed A1 del microcontrollore (pin per i segnali analogici), ed all'alimentazione (i pin 5 V e GND); mentre, il bottone (dispositivo digitale) è collegato all'alimentazione (attraverso la breadboard) ed al microcontrollore (pin 13 dedicato ai segnali di input digitali). Arduino riceverà l'alimentazione attraverso la porta seriale del PC, che fungerà anche da scambio dati (visualizzazione dei dati su terminale) e per la programmazione.
Il codice a bordo del microcontrollore legge i valori digitali in ingresso (le pressioni sul bottone) e quelli analogici (le variazioni di resistenza dei due potenziometri) e produce in uscita delle stringhe separate con delle virgole, come riportato nel seguito:
vertOutput,horzOutput,selOutput // veritical ouptut, horizzontal ouptut, selector vertOutput varia da 0 a 1023 horzL'output varia da 0 a 1023 selOutput è 0 (LOW) o 1 (HIGH)
I valori di ingresso possono essere monitorati attraverso il terminale dell'IDE di Arduino (pulsante tipicamente posto in alto a destra, o nel menu a cascata). Molto importante è verificare che ruotando le manopole (i due potenziometri, anche detti trimmer) e pigiando sul pulsante, le stringhe scorrano mostrando valori diversi (0 - 1 per il bottone, tra 0 e 1023 per le due manopole), saranno fondamentali per l'interazione con il ricevitore. Per lo sketch di Arduino (gergo utilizzato per indicare il codice sorgente di Arduino) è stato fissato un bit rate di trasmissione pari a 57600, ma può essere modificato in funzione del numero di interfacce di input collegate al microcontrollore. Ad ogni modo, qualunque sia la velocità scelta, è importante assicurarsi che il modulo radio xBee e le schede Arduino funzionino tutte alla stessa velocità, pena l'impossibilità di stabilire una connessione tra le due.
Per completezza, nel seguito si riporta lo sketch per Arduino che può essere impiegato per leggere gli ingressi forniti da un joystick. Lo scopo è rendere subito pronto il lettore a lavorare con esempi più complessi ed articolati, una volta capite le basi della comunicazione wireless.
/* Programma base del joystick l'output è una stringa contenente tre valori separati da virgole vertOutput,horzOutput,selOutput */ // Imposta i pin per l'input del joystick int selPin = 13; int vertPin = A0; int horzPin = A1; selOutput boolean; int vertOutput; int horzOutput; int ledPin = 13; // Imposta il pin di output per testare il pulsante void setup() { // pin di input per il joystick, pin di output per il pulsante di test pinMode(ledPin, OUTPUT); pinMode(selPin, INPUT); pinMode(vertPin, INPUT); pinMode(OrzPin, INPUT); Serial.begin(19200); } void loop() { vertOutput = analogRead(vertPin); horzOutput = analogRead(horzPin); selOutput = digitalRead(selPin); Serial.print(vertOutput); Serial.print(","); Serial.print(horzOutput); Serial.print(","); Serial.println(selOutput); }
Ricevitore
Il ricevitore Arduino va inteso come un server proxy, che riceve ingressi dal trasmettitore, ed a valle dei quali esegue specifiche azioni (funzioni dell'applicazione di interesse). Il circuito utilizzato per l'esempio (vedi Figura 2) contiene tre LED: due, attenuano o intensificano la propria intensità luminosa a seguito di cambiamenti di resistenza (il potenziometro) operati dal trasmettitore. In altre parole, il LED risulterà spento se l'uscita del potenziometro è pari a 0, ed avrà luminosità massima quando il potenziometro assume valore massimo (1023); il terzo LED, passa da acceso a spento in funzione dello stato del bottone. Quando il bottone è su 0, il LED risulterà spento, e quando il bottone è su 1, il LED risulterà acceso. I resistori per questi LED, necessari per il corretto funzionamento del circuito, hanno un valore di 330 Ohm.
Il codice a fondo articolo consente di comandare il ricevitore instaurando una comunicazione seriale. Come per il trasmettitore, nel seguito è riportata una piccola discussione sul codice così da comprendere al meglio il funzionamento. La prima parte del codice (riportata nel seguito) stabilisce il tipo e le variabili che saranno utilizzate nello sketch di Arduino.
String vertPot; String horzPot; String buttonPot; int vertVal; int horzVal; int buttonVal; int vertPin = 11; int horzPin = 12; int buttonPin = 13; String myString = "255,255,1"; String list[3]; // necessario per la memorizzazione del tockenizer
Qui, invece, la funzione per la configurazione (void setup, in inglese) del dispositivo. La funzione setta i pin di INPUT e di OUTPUT, oltre alla velocità di comunicazione sulla porta seriale. La funzione resta eseguita fin quando la comunicazione seriale è attiva (attraverso il ciclo "while" su "!Serial").
void setup() { pinMode(vertPin, OUTPUT); // imposta i tre pin di uscita pinMode(horzPin, OUTPUT); // pinMode(buttonPin, OUTPUT); // Serial.begin(19200); // Avvia la comunicazione seriale, assicurati di utilizzare una velocità di trasmissione coerente while(!Serial) { ; // attende che la porta seriale si connetta. Necessario per USB nativo } }
Ecco il ciclo principale (il void loop (), eseguito ad ogni ciclo di scansione):
void loop() { if(Seriale.disponibile() > 0) { myString = Serial.readStringUntil('\n'); // Legge la data in entrata in una stringa fino al feed di riga } String horzPot = getValue(myString,',',0); // Memorizza il primo valore della stringa in arrivo String vertPot = getValue(myString,',',1); // Memorizza il secondo valore della stringa in arrivo String buttonPot = getValue(myString,',',2); // Memorizza il terzo valore della stringa in arrivo Serial.print(horzPot); // Serial stampa nuovamente i valori, utile per il debug, ma non necessario. Serial.print(","); Serial.print(vertPot); Serial.print(","); Serial.println(buttonVal); horzVal = map(horzPot.toInt(),0,1023,0,255); // mappa gli ingressi analogici (0-1023) sull'uscita analogica (0-255) vertVal = map(vertPot.toInt(),0,1023,0,255); buttonVal = buttonPot.toInt(); analogWrite(vertPin, horzVal); // usa i valori in entrata per accendere le luci analogWrite(horzPin, vertVal); digitalWrite(buttonPin, buttonVal); }
Questa, invece, è la funzione, getValue, presa in prestito da questo thread su stackoverflow. La funzione aiuta a dividere "myString" (campo in cui viene memorizzato il messaggio ricevuto), che consiste di tre valori separati da virgole, in un array con tre valori distinti:
ATTENZIONE: quello che hai appena letto è solo un estratto, l'Articolo Tecnico completo è composto da ben 2428 parole ed è riservato agli ABBONATI. Con l'Abbonamento avrai anche accesso a tutti gli altri Articoli Tecnici che potrai leggere in formato PDF per un anno. ABBONATI ORA, è semplice e sicuro.