Tutorial: utilizzo moduli radio con PIC - Esempio completo

Vediamo ora un esempio completo (e funzionante) di trasmissione wireless secondo quanto detto finora.
Colleghiamo attraverso due comuni moduli radio due PIC16F628A. Il trasmettitore agisce quando viene premuto un pulsante, inviando il byte "0x55" (01010101 in binario).
Il ricevitore decodifica il segnale e lo mostra su un display LCD.

Lo schema delle connessioni da effettuare e' davvero banale poiche' bisogna connettere solamente un pulsante a un PIC e un LCD ad un altro e i moduli radio TX/RX ai PIC rispettivi. Il circuito va alimentato a 5 V.

Nello schema sottostante i moduli radio sono rappresentati genericamente dalle due antenne, poiche' in genere questi moduli sono molto diversi fra loro e non e' possibile prevedere le modalita' di collegamento di ognuno. Per ulteriori informazioni sulla connessione dei moduli radio ai PIC, consultare i datasheet.


(clicca sull'immagine per vederla piu' grande)

Il firmware per i microcontrollori è stato scritto in C in ambiente mikroC. Per la comprensione di questo esempio si richiede una discreta conoscenza dei microcontrollori in generale, delle periferiche interne (GPIO e Timer soprattutto) e del linguaggio C.

Scegliamo di utilizzare la codifica OOK perche' molto diffusa in questo genere di applicazioni. Inoltre, per assecondare il problema del tempo di aggancio del ricevitore inviamo, prima dei dati, un'onda quadra per un periodo pari a 5 volte la durata di un bit e non inviamo niente (bit a 0) per un ulteriore tempo di durata di un bit, per permettere al ricevitore di sincronizzarsi.
La frequenza che utilizziamo come modulante sara' a 3 kHz (periodo 333 uS) perche' e' praticamente accettata da tutti i moduli di questo genere. La durata di un bit e' in questo caso di 10 millisecondi.
L'invio di un byte di informazione sara' quindi in uscita dal PIC trasmettitore (e, idealmente, in entrata al PIC ricevitore): 50 millisecondi di onda a 3 kHz, 10 ms di assenza segnale, poi il byte vero e proprio dall'LSB all'MSB. Ossia, essendo il byte 01010101, 10 ms di onda a 3 kHz, 10 ms di assenza segnale, e così via per quattro volte.

La figura seguente chiarisce questo concetto (dato lo zoom, l'onda quadra a 3 kHz viene rappresentata come area uniforme di colore giallo):

Come generare questa forma d'onda (da inviare al modulo radio trasmettitore che la inviera' a sua volta via radio) col microcontrollore trasmettitore?
Io per avere una maggiore precisione ho scelto di utilizzare il Timer0 interno e degli interrupt. Sono necessari alcuni brevi calcoli, ma la precisione del risultato ottenuto e' senza dubbio maggiore di quella ottenibile con molti altri metodi.

Abbiamo detto che la frequenza e' 3 kHz, quindi il periodo T = 1/f = 333 uS. Cio' significa che per generare un'onda quadra dobbiamo alterare il pin ogni 333 uS / 2 = 166 uS.

Utilizziamo il Timer0 interno con clock dal processore: F(timer0) = Fclock / 4 = 1 MHz visto che la frequenza di clock e' 4 MHz (oscillatore interno, o esterno per una maggiore precisione).
Tclock = 1 / Fclock = 1 uS. Quindi il Timer0 si incrementa ogni 1 uS. Siccome e' un timer ad 8 bit, dara' interrupt per overflow dopo 1 uS * (2 ^ 8) = 256 uS.
Per avere invece un interrupt ogni 166 uS, dopo un interrupt dobbiamo fare ripartire il Timer0 non da 0 ma da 256-166 = 90.

La routine di invio non dovra' fare altro che abilitare l'interrupt dal timer. Questo interrupt alterna lo stato del pin se e solo se il bit da inviare vale "1", carica nel Timer0 il valore 90 e ritorna al ciclo principale. Quando questo viene fatto un numero tale di volte da aver raggiunto i 10 ms (Tbit), si passa ad un nuovo bit. Nel nostro caso, perche' siano passati 10 ms occorre che il numero di interrupt gestiti sia di 10000 uS / 166 uS = 60.

Trovi qua di seguito il codice sorgente (scritto in C o compilato in hex) che mette in pratica questo ragionamento:



Codice sorgente (.c): Codice sorgente Trasmettitore

Codice gia' compilato (.hex): File compilato Trasmettitore




Anche il funzionamento del ricevitore e' semplice: esso controlla costantemente, in polling, se vi sono dati in arrivo dal modulo ricevitore. in caso ve ne siano, controlla l' "header", ossia i 5 bit alti seguiti dal bit basso. Se la temporizzazione del segnale in ingresso rientra nei limiti di tolleranza massimi (da tarare sperimentalmente) allora procede alla lettura dei bit seguenti. Altrimenti classifica il segnale come disturbo e lo scarta.

Grazie alle specifiche imposte dall' "header" di sincronizzazione e' quasi impossibile validare come dato leggibile un disturbo. Inoltre una buona taratura manuale delle tolleranze (visibili in seguito nel codice sorgente) permette una buona sensibilita' anche in condizioni difficili.

Quando il ricevitore capta un dato in arrivo, lo legge e, se considerato valido, lo mostra sul display alla prima linea. Sulla seconda linea, invece, mostra il numero di dati validi ricevuti finora.

Il funzionamento della routine di ricezione e' semplicemente quello di leggere piu' volte ad intervalli regolari il pin di ingresso, e considerare "attivo" il segnale in ingresso se il numero di letture a livello logico alto e' superiore ad una certa soglia.

Per entrambi i microcontrollori, i cosiddetti "fuses" vanno impostati per attivare il clock interno (a meno che si inserisca un quarzo esterno e si modifichi di conseguenza il codice) e disattivare il pin di RESET (in alternativa e' possibile inserirvi un pull-up con una resistenza del valore non critico di una decina di kOhm, come si vede nello schema).

Trovi qua di seguito il codice sorgente (scritto in C o compilato in hex) per il microcontrollore ricevente:



Codice sorgente (.c): Codice sorgente Ricevitore

Codice gia' compilato (.hex): File compilato Ricevitore






Con questo ho terminato l'esempio pratico ed il tutorial. In caso di dubbi o problemi potete ovviamente contattarmi direttamente.

Buona sperimentazione a tutti :)

Trovate ulteriori approfondimenti sui seguenti siti:

Tutorial codifica manchester
Codifica manchester su wikipedia
Codifica OOK su wikipedia
Codifica FSK su wikipedia
Mio precedente articolo con moduli radio
Altro mio precedente articolo con moduli radio