Come gestire e controllare i nostri dispositivi senza usare cavi – Parte 2 – Controllo via radio rele´ e temperatura con XBee e PIC16F88
Nella prima parte di questo articolo abbiamo potuto vedere come è semplice utilizzare un modulo Xbee, interfacciarlo ad un computer e comunicare senza fili tra due pc. In quest’altra parte realizzeremo una comunicazione wireless tra un computer e un dispositivo a microcontrollore facendo uso sempre di due moduli XBee Pro (ricordo: i più potenti).
Il picmicro che ho scelto per questa applicazione è il PIC16F88: nello spazio occupato da un comune integrato DIL a 18 pin abbiamo a disposizione le stesse periferiche che abbiamo imparato ad utilizzare con il 16F877A, ed in particolare per questa applicazione sfrutteremo il convertitore A/D e ovviamente, dovendo comunicare con l’XBee, l’ USART.
E’ pertanto assolutamente necessario avere letto a fondo i due articoli del corso di programmazione che parlano di queste due periferiche altrimenti non sarete in grado di capire cosa accade:
- L’USART e la comunicazione seriale con il protocollo RS232
- Il convertitore Analogico/Digitale: principi di funzionamento
- Il convertitore Analogico/Digitale: utilizzo della sonda LM35 per realizzare un termostato
Faremo un utilizzo “massiccio” degli interrupt: sfrutteremo insieme l’interrupt sull’overflow del timer0, quello sulla fine della conversione A/D e quello sulla ricezione di un byte sull’USART; in questo modo il nostro programmino, seppure molto semplice, getta le basi per poter realizzare in maniera molto efficiente qualsiasi cosa ci passi per la testa con il minimo sforzo. Essendo tutto gestito dagli interrupt, aggiungere codice è molto più semplice e permette inoltre di adattare semplicemente il programma anche ad altri picmicro.
Con l’applicazione presentata in questo articolo saremo in grado, dal nostro pc, di comandare via radio due relè, conoscerne lo stato e sapere la temperatura del luogo in cui abbiamo posto la nostra scheda. Sfrutteremo quindi i moduli XBee in maniera bidirezionale: il modulino radio posto sulla nostra scheda remota riceverà dei comandi dal pc e restituirà delle risposte, vedremo quindi anche come inviare una lettura analogica.
Indice dei contenuti
Materiale utilizzato
Per questa prova ho usato parte del materiale già visto nella prima parte dell’articolo, acquistabile su Robot-Italy, più pochi altri componenti:
- 2 Moduli XBee PRO con antenna integrata
- Una XBee USB Board – che mi permetterà di collegare un Modulo XBee sulla porta USB del computer
- Una 1000Pads Mini XB Board – che è una millefori “evoluta” avente a bordo già tutto l’occorrente per il collegamento con un modulo XBee, tra cui -cosa importantissima- il regolatore di tensione a 3,3V
- Una 1000Pads Mini 2 Relays Board – una scheda, appartenente al sistema 1000 Pads Mini con su montati due relè miniaturizzati a 5 volt già “pronti”: sono inclusi condensatori, transistor (mosfet) per il pilotaggio e diodo di ricircolo: dovremo soltanto far arrivare un segnale a 0V sugli ingressi denominati “in” per attivare il relè corrispondente.
Ci saranno quindi un PIC16F88 con zoccolo, un regolatore di tensione 7805, qualche condensatore per stabilizzare le alimentazioni, una clip per pila a 9V, una sonda di temperatura LM35 , due strip di contatti a 10 pin (uno maschio e uno femmina – utilizzati per connettere tra loro due schede) e dei distanziali da 12mm con relative viti per mantenere le schede e rendere il tutto più robusto.
Come dicevo nella prima parte, ho utilizzato delle schede appartenenti al sistema 1000Pads Mini: sono molto piccole, costano poco e hanno a bordo già l’occorrente per svolgere il loro compito, semplificando di molto la realizzazione di prototipi, in questa foto a sinistra c’è la 1000Pads Mini XB Board, al centro la 2 Relay Boards e a destra una basic board (che è una scheda generica dai 1000 usi):
Come vedete sono molto compatte e hanno tutte la stessa dimensione e posizione dei fori di fissaggio: questo permette di impilarle una sull’altra facendo uso di distanziali (io consiglio i distanziali da 12mm):
Il collegamento elettrico tra una scheda e l’altra può avvenire in vari modi, io utilizzerò degli strip saldati sulla contattiera presente sul lato minore, come vedremo tra poco.
Schema elettrico e costruzione
Lo schema realizzato è davvero molto semplice dal momento che gran parte della circuiteria è già presente sulle schede utilizzate. Il circuito l’ho distribuito su due schede montate una sull’altra: sulla mini XB board, posizionata al piano superiore, ho montato (a parte ovviamente l’XBee) il ramo di alimentazione, il partitore per inviare il segnale di trasmissione all’XBee e la sonda di temperatura LM35 secondo il seguente schema:
Voglio farvi alcune raccomandazioni: prima di collegare l’XBee e la seconda scheda con il pic (lo ripeto in altre parole: non collegate ancora l’XBee – non collegate ancora il pic), è bene fare alcuni semplici test per verificare che il montaggio sia corretto e per evitare possibili guai successivamente. Colleghiamo la batteria e controlliamo che sia presente la tensione di 5Volts all’uscita del regolatore (il led comunque deve accendersi). Inoltre, cosa più importante: verifichiamo di aver montato correttamente il partitore inviando 5volt al punto contrassegnato come “TX PIC”: nel punto “RX XBEE” dobbiamo leggere circa 3,2Volts. Già che ci siamo, controlliamoci anche i 3,3Volts sui pad collegati all’uscita del regolatore (che vi illustrerò tra poco).
Nel punto contrassegnato come “VIN” (che arriva in ingresso al regolatore di tensione da 3,3V integrato sulla scheda) invieremo direttamente la tensione della batteria a 9volt piuttosto che quella in uscita al regolatore di tensione 7805: in questo modo i due rami di alimentazione saranno abbastanza disaccoppiati evitando possibili interferenze. Vi illustro qui i punti in cui dare tensione e da cui prelevare i segnali (che comunque sono anche serigrafati sulla scheda):
Come vedete i piani di massa sono già presenti e le due file di contatti che ho contrassegnato con GND, così come i punti indicati con GND sulla serigrafia, sono già tutti collegati tra loro. Le file di contatti che ho colorato in rosso si trovano a +3.3V e sono in pratica connesse all’uscita del regolatore di tensione integrato sulla scheda per cui per la nostra prova non andranno utilizzate, quindi: lasciate liberi quei contatti e non saldateci nulla sopra!
Dal momento che queste non sono semplici millefori, alcuni pad sono collegati tra loro (vi dicevo difatti che è una via di mezzo tra una breadboard e una millefori) per cui fate riferimento alla documentazione ufficiale di tali schede oppure usate un tester per capire i collegamenti. Non è comunque difficile capire il modo in cui sono collegati i pad dal momento che le linee serigrafate sulla basetta raggruppano i pad collegati insieme in riquadri.
I punti di: GND, +5V, AN6 PIC, TX e RX PIC li ho quindi collegati a 5 pin dello strip maschio rivolto verso il basso e ho ripreso i collegamenti sulla scheda inferiore da uno strip femmina.
Sulla 2 Relay Board, che andrà posizionata sotto, ci sarà unicamente il PIC16F88 con la sua poca circuiteria necessaria per poter funzionare e con due pin collegati ai terminali di attivazione dei relè:
Sulla scheda non ho previsto il connettore ICSP, se volete potete metterlo voi, io ho preferito montare solo lo stretto necessario e programmare il pic su una scheda a parte.
I terminali di attivazione dei relè, sulla relay board, sono contrassegnati con la serigrafia “IN”. Inviando 0V a tali pin, il relè corrispondente si eccita e si illumina il relativo led rosso, collegheremo quindi RA1 e RA2 in questi punti:
Capirete ovviamente il motivo per il quale ho scelto RA2 e RA1 per pilotare i relè… Montando il pic con il pin1 rivolto verso i relè, tali pin si trovano in posizione comoda!
I contatti chiusi dal relè possono essere ripresi nei punti indicati come COM (comune), NO e NC (normalmente aperto e normalmente chiuso).
Le file di contatti laterali, contrassegnate con + e – andranno ovviamente collegate rispettivamente a +5V e a massa (e quindi anche ai pin 14 e 5 dello zoccolo destinato ad accogliere il pic).
Prima di montare il pic è meglio fare una prova fornendo alimentazione alla scheda e portando la massa sullo zoccolo del pic sui pin 1 e 18: i relativi relè si dovranno eccitare. Dovranno inoltre essere presenti i 5Volt sul pin 14.
Altra importante raccomandazione: fate attenzione a ciò che collegate ai due relè ! Anche se i relè di tale scheda sono a doppio scambio, i contatti dei due scambi sono collegati tra loro per cui è come se avessimo, per ogni relè, un singolo scambio ma capace di sopportare il doppio della corrente. A tali contatti può essere applicata una tensione massima di 30V e possono sopportare una corrente massima di 1A (vi ricordo che si tratta in ogni caso di relè miniaturizzati) per cui possono andare bene per comandare piccole ventole o motori a 12V che non assorbano più di 1A oppure ancora possono essere usati per pilotare relè più grandi o relè allo stato solido nel caso in cui vogliate pilotarci carichi a 220V come lampadine o altro.
Alimentando il tutto con una batteria a 9Volt (che dati gli esigui consumi dei componenti attivi, ha una prospettiva di vita abbastanza lunga) potete davvero toccare con mano come può essere semplice realizzare un’automatismo del genere in così poco spazio:
Ahimé! Ammetto che quel quarzo coricato non si addice assolutamente al mio stile. La scheda coi relè va difatti montata sotto e l’altezza dei quarzi standard (cioè quelli in formato HC49U) non lo permette per cui sono stato costretto a piegarlo. Ovviamente utilizzando un quarzo a profilo basso (cioè in formato HC49S che ha un’altezza inferiore a 4mm) il problema “estetico ” non sussiste.
Qui potete vedere in dettaglio come ho realizzato il collegamento elettrico tra le due schede utilizzando due strip da 10 pin: quello maschio montato sulla scheda superiore e diretto verso il basso, e quello femmina sulla scheda inferiore e diretto verso l’alto:
Se esistessero dei distanziatori da 1,1mm scomparirebbe anche quello spazietto tra i due strip (notate i contatti dorati visibili?) in quanto i comuni strip, montati l’uno nell’altro, hanno un’altezza totale proprio da 1,1mm, per cui i distanziali da 1,2mm non permettono loro di entrare completamente anche se il contatto comunque c’è e non si hanno problemi.
Ho da aggiungere un’ultima cosa: le basette appartenenti al sistema 1000pads mini sono a doppia faccia con fori metallizzati, per cui quando andrete a saldarvi sopra i componenti, non è necessario saldarli da entrambi i lati. Nel caso dovreste rimuovere i componenti, piuttosto che una pompetta aspirastagno consiglio una trecciola di rame dissaldante: oltre ad assorbire lo stagno in maniera molto più pulita, assorbe anche parte del calore evitando così di rovinare la scheda.
Il codice
Tenendo conto che con l’XBee altro non realizziamo che una semplice comunicazione seriale asincrona e avendo già letto alcuni articoli precedenti, menzionati più in alto, non andremo a fare nulla di complicato.
Dal momento che, rispetto ad altri pic, il 16F88 potrebbe risultare po’ “particolare” (nel senso che è molto versatile e ha quindi alcuni registri in più) incontreremo dei settaggi “strani” per quanto riguarda la word di configurazione e per la funzione analogica.
In particolare sul 16F88 abbiamo 2 word di configurazione: basterà semplicemente utilizzare due volte di seguito la macro __CONFIG: il compilatore capirà da sé che la prima volta che la richiamiamo andremo ad impostare la prima word e quindi la seconda chiamata sarà per la seconda word:
__CONFIG(UNPROTECT & CCPRB3 & DEBUGDIS & LVPDIS & BORDIS & MCLREN & PWRTDIS &; WDTDIS & HS); __CONFIG(0); // seconda word di configurazione |
Dal momento che qui alcuni vedranno delle cose nuove rispetto a quelle già viste, mi sento in dovere di spiegarle. In particolare c’è da dire che il 16F88 ha il modulo CCP (di cui non abbiamo ancora parlato) che può essere “dirottato” sul pin RB3 o sul pin RB1 e quindi quel CCPRB3 serve appunto per avere il modulo CCP sul pin RB3 (che comunque non utilizzeremo in questa applicazione). Il resto dovrebbe esservi noto a parte il fatto che come vedete ho disabilitato il PowerUp Timer (PWRTDIS).
Perchè l’ho disattivato quando abbiamo invece imparato che è “una cosa buona”? Per questa applicazione (e ripeto: solo per questa), a causa di motivi a me completamente oscuri e per i quali non ho trovato documentazione, l’attivazione del power up timer non mi consente il corretto funzionamento dell’UART: mi accade difatti che il pic si avvia correttamente ma l’UART resta addormentato per ben mezzo minuto dopodichè prende a funzionare, disattivando il power up timer invece mi funziona tutto correttamente da subito. Se realizzate questa applicazione fate anche voi questa prova (attivare e disattivare il power up timer) e fatemi sapere il comportamento del circuito. Ho provato anche con un 16F628 (ovviamente senza funzioni analogiche) e ho avuto lo stesso strano comportamento.
La seconda chiamata alla macro __CONFIG setta quindi la seconda word di configurazione che per noi non ha alcuna funzione utile al momento.
Proseguendo con le “diversità” c’è da dire che la scelta delle porte che dovranno avere funzione analogica qui non avverrà, come abbiamo già visto, settando i bit <0:3> di ADCON1 (che sul 16F88 sono bit inutilizzati) ma vi è invece un apposito registro denominato ANSEL con il quale possiamo scegliere singolarmente le porte da impostare come analogiche:
ANSEL=0b01000000; // Abilito solo AN6 con funzione analogica. AN6 si trova su RB7 |
Impostando i bit di tale registro ad 1 si attiva la funzione analogica sul corrispondente bit delle porte AN (cioè se metto a 1 il bit 0 di ANSEL, allora il pin avente il contrassegno AN0 funzionerà come ingresso analogico). Non dimentichiamoci di impostare anche ad 1 i bit del relativo registro TRIS nei punti in cui vogliamo la funzione analogica.
Altri pic hanno più di un registro ANSEL. Per cui come vedete non tutti i pic seguono lo stesso schema per la configurazione delle porte analogiche. Indubbiamente la presenza dei registri ANSEL è molto più proficua in quanto non ci vincola ad affettuare scelte obbligate: possiamo scegliere da noi quali pin devono funzionare come ingressi analogici (tra quelli che possono).
I bit ADCS2 (bit6 di ADCON1) e ADCS1:ADCS0 (bit 7 e 6 di ADCON0) li ho impostati per avere una frequenza di campionamento pari a Fosc/8 che, utilizzando il quarzo da 4MHz, fornisce un Tad di 2μS (abbiamo difatti imparato che deve essere minimo 1,6μS e non arrivare a valori troppo alti):
Imposto inoltre il Prescaler a 1:4 assegnandolo al Timer0, precaricato ad 8: in questo modo, col quarzo da 4MHz, avrò un interrupt ogni mS che in questa applicazione utilizzerò per decrementare un counter che avvia la lettura della sonda di temperatura ogni 100mS.
Se non ricordate come si fanno questi calcoli, c’è sempre il nostro PICTimer che può farli al posto vostro.
Anche qui, per la lettura della sonda, sfrutteremo la stessa tecnica usata nell’esempio del termostato: effettuerò 10 misure di temperatura sulle quali farò la media. In questo modo il valore è più stabile.
E’ comunque più conveniente fare un numero di misure pari ad una potenza di 2 e quindi al posto della divisione effettuare il bitshift.
La ricezione sull’UART del pic sarà gestita dall’interrupt su ricezione seriale (RCIF) in maniera da rendere le operazioni più snelle possibile ed ampliabili. Analizzerò i bytes ricevuti (memorizzati nella variabile “input”) e a seconda del dato imposterò dei flag da controllare nel main. Ad esempio: se sull’UART ricevo la lettera “T” o la lettera “t” setto un flag:
switch(input) { //... case 'T': case 't': readtemp=1; // segnalo nel main di scrivere il valore di temperatura break; //... } |
Vi ricordo che ogni lettera in realtà rappresenta un byte: una sequenza di 8 bit. Anche se “T” e “t” per gli esseri umani rappresentano la stessa lettera, non è così per i computer in quanto si tratta di due bytes (due numeri a 8 bit) differenti. Per tale motivo ecco perchè generalmente nelle mie applicazioni mi controllo sempre sia la maiuscola che la minuscola in maniera da non creare confusione “umana”.
Nel main quindi intercetterò il settaggio del flag, eseguirò il compito relativo dopodichè il flag sarà resettato:
// segnalata la lettura della temperatura if (readtemp) { printf("Temperatura: %d.%d \n\r",((temperatura*5)/10),((temperatura*5)%10)); readtemp=0; // azzero il flag }// \readtemp |
Qui in pratica sto rispondendo alla richiesta di visualizzazione della temperatura inviando sull’UART una stringa che mi mostra la scritta “Temperatura: ” seguita dalla parte intera, dal punto e dalla parte decimale.
Vediamo l’utilizzo dell’istruzione printf con altri parametri e con delle “robe strane” tra virgolette. A parte le sequenze di escape \n e \r che, come sapete, sui sistemi Windows mi realizzano il ritorno a capo (nuova linea + ritorno carrello), c’è da spiegare il significato dei %d.
Quei due %d in C prendono il nome di specificatori di formato. Il %d in particolare è una sorta di “segnaposto” per i numeri interi decimali. In pratica il processore del pic sostituirà al primo specificatore di formato il primo argomento dopo la stringa da stampare, sostituirà quindi al secondo specificatore il secondo argomento e così via.
Il primo parametro della funzione PrintF, ovvero la stringa da stampare sull’output standard (che nel nostro specifico caso è l’UART, mentre sui PC è l’uscita video), è un parametro obbligatorio. Al parametro obbligatorio seguono quindi uno o più parametri facoltativi che rappresentano appunto i valori da sostituire agli eventuali specificatori di formato presenti nella stringa.
Capite quindi come al posto del primo %d sarà stampato il numero ((temperatura*5)/10) che rappresenta la parte intera del valore di temperatura espresso in gradi Celsius (la variabile “temperatura” contiene il valore letto dal convertitore AD). Al posto del secondo %d verrà quindi stampato il risultato di ((temperatura*5)%10) che nella fattispecie è la parte decimale del valore di temperatura.
Se vi chiedete da dove vengono fuori questi calcoli è perchè non avete letto questo.
Funzionamento
Una volta testate le schede come ho detto e verificati i collegamenti, possiamo passare ad inserire un modulo XBee sull’apposito adattatore per PC (io ho utilizzato l’infallibile XBee USB Board) ed avviare HyperTerminal (o il programma che preferite per comunicare con la seriale) impostandolo come segue:
E’ ovvio che i moduli XBee, per poter comunicare tra loro, dovranno avere le stesse impostazioni come già spiegato nella prima parte dell’articolo. Anche il pic, come potrete vedere dal codice, è stato impostato per lavorare a 9600 bps
Diamo l’OK e forniamo quindi alimentazione alla nostra scheda “remota”. Dovremo vedere apparire in hyperterminal una frase di test.
Se ora da hyperterminal digitiamo la lettera S (o la s -minuscola-) richiediamo in pratica al pic di farci sapere lo stato dei due relè:
Digitando invece R (o r) seguito da 1 o 2 possiamo invertire lo stato dei relè 1 e 2, il sistema ci risponderà con “ok” seguito dal nuovo stato assunto dal relè:
Se dopo la lettera R premiamo un tasto non consentito, non accadrà nulla e ci verrà risposto di conseguenza:
In questo caso la modalità di cambio stato di relè verrà resettata per cui dovremo premere nuovamente R.
Premendo la T (o la t) ci verrà restituito il valore di temperatura:
Dal momento che di sicuro qualcuno me lo chiederà, rispondo in maniera preventiva: non è possibile includere il simbolo di grado in quanto crea problemi con la funzione PrintfF. E’ comunque inutile dal momento che queste cose si utilizzano generalmente accoppiate a software che già sanno cosa devono mostrare e quindi gli eventuali simboli non stampabili da PrintF vengono inclusi sul software lato PC.
Come avete visto non è difficile realizzare un controllo remoto avendo a disposizione i materiali giusti (e soprattutto testati). Ovviamente non è detto che dovete per forza controllare il vostro sistema remoto dal pc. Potreste infatti utilizzare anche un altro circuito basato su picmicro (tipo un telecomando insomma) in quanto basta soltanto utilizzare l’UART.
Cosa dirvi se non: buon divertimento!
Downloads
Documentazione 1000 Pads Mini 2 Relay Board
Documentazione 1000 Pads Mini XB Board
Controllo remoto Relè e temperatura con PIC16F88 e XBee (597 download) Datasheet PIC16F88 (1857 download) LM35 - Precision Centigrade Temperature Sensor (2818 download)