Controllo radio per tabellone segnapunti

Salve a tutti, in quest’articolo voglio esporre il progetto che io e un mio compagno abbiamo portato all’esame di maturità.

Si tratta della costruzione di un sistema per il controllo wireless del tabellone segnapunti utilizzato nella nostra ex palestra scolastica.

(clicca sull'immagine per vederla più grande)

Il tabellone segnapunti in questione, costruito da altri allievi nel lontano 1997, è costituito principalmente da 12 shift register SI-SO/PO 74HC595 disposti a cascata. Le loro uscite pilotano, attraverso degli array di transistor Darlington ULN2803, i display a sette segmenti corrispondenti.

I 595 sono divisi in tre sezioni, ognuna delle quali gestisce quattro display: la sezione dedicata al punteggio dei locali, la sezione dedicata al punteggio degli ospiti e la sezione dedicata al conteggio del tempo.

Tale sistema è controllato da 5 linee di comando: dati, clock, strobe locali, strobe ospiti, strobe tempo (più la massa).

La linea dati e quella di clock sono comuni a ciascuna delle tre sezioni, mentre gli strobe sono specifici per ognuna di esse.Ogni colpo di clock fa acquisire al primo buffer di ciascuna delle tre sezioni il dato; a trasmissione ultimata si può inviare un comando di strobe per aggiornare il ramo desiderato.

Lo stadio d’ingresso del tabellone prevedeva, per ogni linea, una resistenza di pull-up, un condensatore di filtro verso massa e un 74HC14 usato per adattare il livello della tensione di comando (12 V) a quello della logica TTL (5 V).

Ecco uno schema che riassume la costituzione interna del tabellone (sulla sinistra è visibile il circuito di alimentazione con un 7805 per la logica TTL e un lm317 per i display a led. In realtà è presente un lm317 per ogni display ma ne è riportato uno solo per semplicità):

(clicca sull'immagine per vederla più grande)

In precedenza il tabellone segnapunti era controllato attraverso la porta parallela di un vecchio computer da un programma scritto in pascal. I segnali in uscita dalla porta parallela venivano “potenziati” da un circuito a MOSFET che alzava la tensione da 5 a 12 V in modo da poterli trasmettere lungo tutti i cento metri di cavo STP che collegavano il tabellone al pc.

Pur funzionando bene questo sistema di controllo aveva numerosi problemi:

  • Il computer era molto vecchio, così come il software ed il linguaggio di programmazione utilizzato per scriverlo. Si sarebbero incontrati numerosi problemi se uno qualsiasi di questi elementi avesse presentato qualche malfunzionamento;
  • Il cavo di trasmissione, essendo molto lungo ed arrotolato intorno alla linea della rete elettrica, era soggetto a numerose interferenze e distorsioni;
  • L’operatore che utilizzava il computer era costretto a starne in prossimità, molto distante dal campo di gioco.

Un altro intervento di manutenzione necessario era la riparazione dell’avvisatore acustico (un vecchio clacson di una seicento) che, da molto tempo, non era più funzionante a causa di un componente della scheda di controllo che si era bruciato.

Il nostro progetto ha operato la sostituzione del computer di gestione con un radioricevitore collegato direttamente allo stadio d’ingresso del tabellone e posto il più vicino possibile ad esso.

Per comandarlo è prevista una stazione di controllo alimentata a batteria e dal basso dispendio energetico. In alternativa è stato realizzato un telecomando che può essere utilizzato per comandare il tabellone nel caso vi sia un guasto alla stazione trasmittente, mentre questa viene riparata.

Il ricevitore controllerà anche un avvisatore acustico di fine tempo che, dato il suo moderato assorbimento (circa 0,5 A @ 230 Vac), sarà dotato di una scheda d’interfaccia e di una connessione di alimentazione 230 Vac dedicata.

Sia i dispositivi di trasmissione che quello di ricezione contengono dei microcontrollori adeguatamente programmati e facilmente riprogrammabili, in modo da aggiungere versatilità e facilità di aggiornamento a tutto il sistema.

Il software per i dispositivi trasmittenti è scritto in assembly, mentre quello del ricevente è scritto in C (ambiente mikroC) a causa delle numerose operazioni di elaborazione che deve compiere e della non trascurabile complessità del codice che renderebbe proibitivo scriverlo in assembly: risulterebbe troppo complicato sia da leggere che da capire e strutturato in modo eccessivamente contorto.


La comunicazione dai dispositivi trasmittenti al dispositivo ricevente avviene via radio grazie a dei moduli Aurel che lavorano ad una frequenza di 433.92 MHz.

Questa frequenza, trovandosi in banda radio libera, è molto utilizzata dai dispositivi che lavorano in radiofrequenza (apri-cancelli, telecomandi di autoveicoli, radio-citofoni, ecc.).

Abbiamo dunque dovuto prevedere un solido protocollo che potesse permettere al ricevitore di distinguere i dati inviati dai dispositivi trasmittenti dalle numerose interferenze. Oltre a questo si sono anche dovuti includere dei sistemi di controllo degli errori, per non interpretare in modo sbagliato i dati in arrivo.

I moduli utilizzati, a riguardo dei quali non si trovano molte informazioni né sul datasheet né sul web, dispongono di uno stadio di ingresso accoppiato in alternata. Non possono pertanto trasmettere un livello logico alto per molto tempo, cosa che rende impossibile l’utilizzo di un protocollo di comunicazione standard come, ad esempio, il RS232.

È invece necessario inviare un segnale che preveda numerose transizioni di livello logico per ciascun bit e che abbia dunque componente continua minima.

Un protocollo che per questi motivi è largamente utilizzato in questo contesto è la codifica Manchester in cui ogni bit contiene due transizioni e la cui componente continua è nulla.

Questo protocollo, seppur ampiamente utilizzato nei dispositivi di comando a radio frequenza, nel nostro caso non è adatto perché non presenta una sufficiente immunità ai disturbi e richiederebbe l’installazione di un sistema di ritrasmissione. Si è dunque reso necessario progettare appositamente un protocollo che rispondesse ai requisiti specifici del progetto.

Il protocollo che abbiamo utilizzato prevede che i dati inviati al modulo trasmettitore siano codificati mediante modulazione ASK-OOK.

Per indicare il livello logico alto è inviata al trasmettitore un’onda quadra a frequenza di 3.5 kHz (in accordo col valore massimo riportato nel datasheet); per indicare il livello logico basso non è inviato alcun segnale.

In questo modo, ogni bit contiene numerose transizioni e la componente continua è minima.

La durata di un bit in trasmissione (quindi il tempo per cui questa frequenza viene inviata o meno) deve essere abbastanza lunga da poter essere discriminata rispetto alle brevi interferenze, ma un tempo troppo lungo rischierebbe di allungare eccessivamente il ritardo tra la pressione di un tasto sul dispositivo trasmittente e l’effettiva esecuzione del comando corrispondente, ossia il tempo totale di trasmissione.

Il valore scelto per la durata di un bit è: Tbit = 25 ms.

Dato che il numero di comandi necessari è limitato, per distinguerli è sufficiente inviare 6 bit anziché 8; le combinazioni restano abbastanza per distinguere fra 26 (64) comandi di cui circa i tre quarti utilizzati. Grazie alla riduzione dei bit inviati è stato possibile ridurre il tempo di trasmissione dei comandi.

I dispositivi trasmittenti inviano i dati in questo modo:

1 bit di start, livello logico alto; 6 bit che formano il codice di comando (dall'MSB all'LSB); 6 bit che formano il codice di controllo del comando (sempre dall'MSB all'LSB)

Il bit di start segnala al ricevitore che è iniziata una trasmissione dati, segue l’invio del comando.

Il codice di controllo, introdotto per l’individuazione degli errori, è costituito dalla negazione del codice di comando. Questo permette un controllo degli errori praticamente infallibile e insensibile alle interferenze ripetitive. Tuttavia non si tratta di un codice a correzione d’errore: un eventuale codice errato è semplicemente scartato ed ignorato.Il tempo totale di trasmissione di un comando è quindi di (1+6+6) * 25 = 325 ms.

L’immagine qui di seguito rappresenta il segnale digitale NRZ da inviare e come esso sia inviato al modulo trasmettitore. Conseguentemente dovrebbe essere lo stesso presente all’uscita del modulo ricevitore.

Supponiamo di voler inviare il comando numero 10, in binario 001010.

La prima metà del segnale è formata dal bit di start e dai 6 bit del comando, ordinati dal più significativo a quello meno significativo.

La seconda metà è costituita dal comando di controllo (il complemento del comando inviato), sempre dal bit più significativo al meno significativo.

Il segnale in uscita dal modulo ricevitore, teoricamente uguale al segnale in entrata al modulo trasmettitore, è quindi composto da una frequenza di 3.5 kHz per indicare il livello logico alto e dall‘assenza di segnale per rappresentare il livello logico basso.

In ricezione, da tale segnale dobbiamo riottenere il segnale binario NRZ, convertendo quindi la frequenza di 3.5 kHz in una tensione continua.

Una volta che si è riottenuto il segnale originale è possibile inviarlo al microcontrollore ricevente perché sia letto ed elaborato.

È quindi necessario un circuito di conversione frequenza - tensione che soddisfi i seguenti requisiti:

  • Velocità di risposta, sia sul fronte di salita sia su quello di discesa;
  • La più alta immunità ai disturbi possibile.

Abbiamo preferito progettare un circuito su misura piuttosto che utilizzarne uno standard presente in commercio per disporre di una maggiore conformità ai requisiti specifici del nostro progetto e di una maggiore conoscenza del suo funzionamento.

Lo schema del circuito progettato, visibile in seguito nello schema elettrico del ricevitore, è il seguente. Lo analizzeremo ora nel dettaglio.

La prima sezione, costituita dal filtro HP di primo ordine R1 - C1, ha la funzione di trasformare il segnale a onda quadra in ingresso in un segnale impulsivo, grazie alla capacità di fare da derivatore che tale filtro possiede quando vi è applicata in entrata un segnale digitale ad onda quadra.

Il diodo D1 è utilizzato per rimuovere, o comunque limitare all’ampiezza di -Vd (-0.7V), i picchi negativi di tensione generati dal circuito rc, mantenendo soltanto quelli positivi.

Il motivo per cui si è resa necessaria una tale trasformazione del segnale sarà spiegato in seguito, nella parte riguardante la reiezione ai disturbi.

In condizioni di riposo (ingresso a livello logico basso) il condensatore C2 è carico, il transistor Q2 ha così 5V sulla base ed è in saturazione, portando l’uscita a livello logico basso.

Quando in ingresso è presente un’onda quadra, che viene trasformata in un treno d’impulsi dal filtro R1 - C1 – D1, si verifica che ognuno di tali impulsi riesca a portare in saturazione il transistor Q1 per un breve istante, comunque sufficiente a scaricare il condensatore C2, portando in interdizione il transistor Q2 e alzando, di conseguenza, il livello logico dell’uscita.

Quando l’impulso si esaurisce il transistor Q1 torna in interdizione, permettendo al condensatore C2 di iniziare a caricarsi con una costante di tempo dipendente dal valore R3 e di C2. Fino a quando la tensione sul condensatore C2 non supera la tensione necessaria a polarizzare il transistor Q2 attraverso R4, tale transistor è in interdizione e l’uscita rimane alta. Al superamento di tale soglia l’uscita torna a livello logico basso.

Il principio di funzionamento di questo circuito si basa sul fatto che la distanza temporale tra un impulso e l’altro non sia tale da permettere al condensatore di caricarsi abbastanza da portare l’uscita a massa. È possibile osservare questo funzionamento dal grafico seguente.

È perciò necessario dimensionare in modo opportuno più parametri del circuito:

  • La costante di tempo R3-C2;
  • La resistenza di polarizzazione R4;
  • La frequenza che indica il livello logico alto.

È opportuno che tali valori non siano soltanto il risultato di una progettazione teorica, ma che vengano corretti da osservazioni pratiche, per compensare alle immancabili tolleranze dei componenti. Queste sono particolarmente rilevanti nel caso dei condensatori, che ricoprono un ruolo importante in questo circuito, e della differente tensione di soglia Vbe che i transistor utilizzati possiedono.

Nel nostro caso i valori finali sono stati ottenuti mediante calcolo preventivo con l’aiuto di programmi di simulazione e corretti da prove pratiche grazie all’uso di oscilloscopi a memoria.

Il primo requisito di questo circuito, ovvero la velocità di risposta dell’uscita, è pienamente rispettato: l’uscita passa a livello alto quasi immediatamente alla ricezione del primo impulso.

La velocità di risposta non è invece immediata nel caso del fronte di discesa: l’uscita diventa bassa solo quando non arrivano più impulsi da un tempo variabile a seconda della costante di tempo R3-C2 e della resistenza di polarizzazione del secondo transistor, ossia il tempo necessario al condensatore per caricarsi a una tensione tale da poter mandare in saturazione il transistor Q2.

Da queste considerazioni si evince che il valore della costante di tempo R3-C2 dovrebbe essere abbastanza alto da non causare una prematura caduta dell’uscita a massa ma, più tale valore aumenta, maggiore diventa il tempo impiegato dall’uscita per commutare livello logico. Il valore scelto dovrà quindi rappresentare una via di mezzo fra le due opposte necessità di reattività ed affidabilità.

Il valore dell’intervallo di tempo necessario all’uscita per alternarsi fra il livello logico alto e quello basso è un parametro che deve essere noto a priori per poter sincronizzare correttamente il ricevitore con i trasmettitori.

È possibile calcolarlo matematicamente o mediante simulazione ma, data la complessità dei calcoli e l’alta incidenza della tolleranza dei componenti sul risultato ottenuto, ne risulterebbe un valore che non corrisponderebbe alle reali prestazioni del circuito. È dunque opportuno ricavare tale valore attraverso misurazioni empiriche effettuabili mediante l’ausilio di un oscilloscopio, come abbiamo effettivamente fatto noi.

La seconda caratteristica richiesta a questo circuito è una buona reiezione ai disturbi. Le misure attuate per perseguire tale obiettivo sono:

  • L’invio del codice di controllo per individuare gli errori;
  • Il filtro R1-C1 utilizzato per trasformare l’onda quadra in un treno d’impulsi;
  • Un’apposita routine implementata nel microcontrollore ricevente per leggere più volte ogni bit, diminuendo le probabilità di leggere dati errati.

Il filtro R1-C1 è stato inserito al solo scopo di rendere impulsivo il segnale in ingresso perché ciò conferisce un notevole aiuto nell’eliminazione dei disturbi, per questo motivo:

A seguito di varie osservazioni pratiche mediante oscilloscopi a memoria, si è giunti alla conclusione che i disturbi captati dal ricevitore hanno l’effetto di portare a livello alto l’uscita in momenti imprevedibili e di mantenerla così per tempi relativamente molto lunghi (a volte anche centinaia di millisecondi).

Se non fosse prevista nessuna misura contro tutto ciò, un disturbo in grado di forzare alta l’uscita per un tempo così notevole sarebbe in grado di invalidare completamente un comando.

Il microcontrollore non eseguirebbe comunque azioni indesiderate poiché il codice ad individuazione d’errore gli permetterebbe d’accorgersi del problema, però vi sarebbe comunque la perdita del comando inviato.

Il grafico seguente mostra come la rete di condizionamento trasformerebbe l’onda ricevuta in questo caso (nessuna misura precauzionale):

(il disturbo è evidenziato in rosso; le temporizzazioni sono solo indicative, non in scala)

Come si può vedere, il dato letto dal microcontrollore sarebbe completamente sbagliato.

Lo stesso identico disturbo, elaborato dalla rete di ricezione con il filtro R1-C1, sarebbe derivato; restando a interferire soltanto sui suoi fronti di salita:

(Nota che l’onda trasformata mostra l’effetto di derivazione sul solo disturbo per semplicità di disegno, ma tale effetto viene applicato anche a tutti i fronti di salita del segnale ook).

L’influenza del disturbo, le cui dimensioni rappresentano un interferenza tra le più pesanti e influenti che possiamo avere, viene, come si può notare, drasticamente ridotta applicando il filtro in ingresso.

In questo modo si può proteggere il sistema da eventuali disturbi dovendo, però, accettare una costante di tempo R3-C2 maggiore e incrementando il ritardo dell’uscita nella transizione verso il livello logico basso.

Questo perché il tempo in cui il condensatore C2 è mantenuto scarico è pari al tempo per cui il segnale in entrata resta alto.

Utilizzando il filtro il segnale viene derivato facendo tendere questo tempo a zero, in questo modo il condensatore C2 ha un tempo per caricarsi maggiore.

Se non ci fosse il filtro il tempo disponibile al condensatore C2 per caricarsi tra gli intervalli alti sarebbe appena la metà di quello attuale (dipenderebbe dal duty cycle dell'onda ricevuta).

Ciò che resta dei disturbi non è sufficiente a causare un errore nella lettura del comando poiché ciascun bit viene letto otto volte a intervalli regolari dal microcontrollore che considera un livello logico alto solo quando almeno cinque delle otto letture risultano tali.

La rete di condizionamento utilizzata dispone così, in associazione alle procedure implementate nel software del microcontrollore ricevente, di una buona protezione contro disturbi ed interferenze.

Il segnale all’uscita del circuito è inviato direttamente al PIC ricevitore e ogni suo primo fronte di salita (il bit di start) genera un interrupt a bassa priorità, costringendo il microcontrollore ad interrompere le eventuali attività in corso per dedicarsi a ricezione e decodifica.

Una volta ricevuto l’interrupt il PIC legge i bit ricevuti e controlla che il codice del comando sia uguale alla negazione del codice di controllo inviato. Se ciò si verifica il comando è eseguito e il tabellone viene aggiornato.

Il motivo per cui il codice di controllo viene inviato negato rispetto al codice di comando è semplice:

Si pensi ad un disturbo in grado di forzare alta l’uscita del modulo ricevitore per molto tempo, facendo leggere al ricevitore il codice binario 111111.

Se si utilizzasse un semplice protocollo di controllo errori a maggioranza anche il codice di controllo risulterebbe 111111 ed il microcontrollore commetterebbe uno sbaglio, validando un dato non corretto.

Utilizzando un codice di controllo negato questo errore non può essere commesso.

Allo stesso modo si potrebbe avere un disturbo in grado di forzare un bit a livello logico alto mentre in realtà è stato trasmesso a livello logico basso.

Se lo stesso disturbo, o un altro, forzasse a uno anche il corrispondente bit del codice di controllo, un semplice codice a maggioranza non individuerebbe l’errore.

Negando il codice di controllo è possibile accorgersi del problema.

Come accennato in precedenza ciascun bit viene letto dal PIC più volte, otto per la precisione. Si tratta di un accorgimento necessario per evitare che una piccola interferenza possa invalidare un intero comando sopravvenendo in contemporanea ad un qualsiasi istante di decisione.

La temporizzazione seguita dal microcontrollore nell’attuazione di questa procedura è descritta nella figura che segue.

Dal grafico si può notare come la durata di un bit sia in realtà di 26 ms mentre quella dichiarata in precedenza ed implementata nei trasmettitori è di 25 ms.

Questo perché, per ottenere una buona sincronizzazione, sono state effettuate delle misurazioni che ci hanno permesso di ricavare sperimentalmente la vera durata di un bit in ricezione, alterata rispetto al valore ideale dalla modalità di funzionamento dei moduli radio e dalle tolleranze dei componenti utilizzati nella rete di condizionamento, nonché dalle inevitabili approssimazioni numeriche compiute nello scrivere il firmware dei trasmettitori.

Il primo fronte di salita del segnale scatena l’interrupt. Il bit di start viene controllato in modo più accurato per essere certi di bloccare eventuali interferenze in già questa fase e non oltre. Questo meticoloso controllo avviene leggendo 20 volte il valore, ogni 1 ms. Terminata questa fase, se il bit è valido, segue una pausa di 10 ms che porta il ricevitore al quarto millisecondo del bit successivo. Qui ha inizio la routine di controllo dei bit che esegue otto letture a distanza di due millisecondi, terminando quindi al 20° millisecondo. Una nuova pausa di 10 ms porta al 4° ms del bit successivo e la routine si ripete così per ogni bit.

Si evita in questo modo di posizionare gli istanti di decisione in prossimità del limite fra un bit ed un altro, come ulteriore misura precauzionale per contrastare eventuali problemi di sincronizzazione.


La stazione di comando è stata progettata come dispositivo alimentato da batterie, dotato di un’ ampia superficie d’appoggio, con tasti numerosi e comodi da utilizzare, permettendo l’invio di un gran numero di comandi per il controllo a distanza del tabellone.

Tali comandi, inviabili via pulsanti appositi o attraverso specifiche combinazioni di altri tasti col tasto Funzione permettono comandi aggiuntivi oltre a quelli normalmente utilizzati come, ad esempio:

  • Configurazione avvisatore acustico (Attivo/disattivo, memorizzata nella EEPROM del ricevitore);
  • Modalità di debug avanzata;
  • Modalità di test del canale;
  • Reset parziale;
  • Reset completo;
  • Modalità salvaschermo (test dei segmenti);
  • Modalità di power-saving;
  • Modalità di prova avvisatore acustico;
  • Conteggio punti in “modalità pallapugno”

Tutte queste funzionalità sono spiegate ampiamente nella sezione relativa al ricevitore.

Sono presenti inoltre alcuni led di segnalazione quali:

  • Power on (dispositivo acceso);
  • Trasmissione in corso;
  • Errore (o “Batteria scarica”).

Il dispositivo può essere attaccato alla rete elettrica mediante trasformatore quando non utilizzato, in modo che il circuito interno provveda alla ricarica e al mantenimento della batteria se necessario.


L’intero circuito di trasmissione, realizzato su millefori doppia faccia, è posto all’interno di una scatola metallica molto resistenze, approssimativamente delle dimensioni di 19*15*6 cm.

La parte anteriore del contenitore è inclinata verso il basso di circa 30°, garantendo all’utilizzatore una maggiore ergonomia.

I pulsanti sono disposti sulla superficie e divisi a seconda della loro area di influenza:

  • A sinistra i pulsanti relativi ai locali;
  • A destra quelli per gli ospiti;
  • In alto i pulsanti per il comando del tempo e i tasti ausiliari.

Sono stati inoltre colorati in modo diverso e la superficie del dispositivo è stata serigrafata in modo che esso risulti di immediata comprensione.

L’alimentazione, proveniente da pacco di batterie ricaricabili (6x1.2V 2100 mAh), è interrotta da un interruttore posto sul retro. Quando questo è chiuso la tensione viene stabilizzata a 5 V da un regolatore lineare integrato a bassa corrente di riposo (MCP1700-5002) che ci permette di avere, in condizioni di non utilizzo, un consumo di corrente totale pari a circa 0.8 mA più i 5 che scorrono nel led di power-on, incrementando notevolmente la durata della batteria.

Un comune stabilizzatore di tensione della serie 78xx dispone di una corrente di riposo minima pari a circa 5 mA, il che lo rende inadeguato per essere utilizzato in dispositivi alimentati a batterie (o, se non proprio inadeguato, perlomeno sconveniente).

I due condensatori in parallelo al regolatore sono necessari per stabilizzare ed eliminare l’eventuale ripple residuo. Il loro valore può essere alzato fino a circa 1 µF, come specificato dal datasheet.

Il microcontrollore utilizzato è un PIC16F628A che è incaricato della lettura dei pulsanti e dell’invio dei codici corrispondenti al modulo trasmettitore.

I pulsanti sono connessi a matrice in modo che il PIC sia facilitato nella loro gestione e che il numero dei pin utilizzati a tale scopo non sia troppo alto. La tastiera così formata richiede infatti appena 11 ingressi/uscite digitali per la gestione dei suoi 28 tasti.

Uno dei pulsanti della tastiera è adibito a pulsante Funzione: premendolo assieme ad un altro pulsante si attiverà la funzionalità secondaria del pulsante premuto.

Nonostante si disponga di un oscillatore interno, il clock è fornito da un oscillatore al quarzo esterno da 4 MHz, stabilizzato con due condensatori ceramici da 22 pF perché è necessario avere una temporizzazione molto precisa per realizzare una trasmissione che rispetti esattamente le tempificazioni decise in fase di progetto.

Il modulo trasmettitore è un modulo Aurel TX-433/SAW s-Z funzionante a 433.92 MHz. Il datasheet indica chiaramente che la massima frequenza accettabile per l’onda modulante non può eccedere i 4 kHz.

Il modulo è dotato di un piano di massa (la superficie della scatola) per l’antenna dimensionata a quarto d’onda e di un condensatore di bypass sull’alimentazione (100nF).

I tre led visibili indicano la presenza di alimentazione (Power-on), lo stato di trasmissione (Tx) e l’eventuale stato di scarica critica della batteria (Err).

Quest’ultimo led è controllato da un circuito comparatore con LM311: vengono comparate la tensione ai capi della batteria, che arriva dimezzata attraverso un partitore resistivo, con una tensione regolabile su di un trimmer predisposto. La tensione sul trimmer resterà sempre stabile dato che è posto dopo lo stabilizzatore di tensione del circuito (a meno di un calo eccessivo della tensione che impedisca il corretto funzionamentto di quest'ultimo).

Quando la tensione delle batterie scende sotto la soglia impostata, il led viene acceso per segnalare che è necessario attaccare la stazione trasmittente alla rete elettrica perché si auto ricarichi.

Il dispositivo è dotato di un circuito di carica controllato automaticamente: quando non è utilizzato può essere collegato mediante un comune trasformatore (230Vac-12Vdc), alla rete elettrica. Internamente, un microcontrollore PIC12F675 è dedicato alla gestione della carica delle batterie: se sono scariche, mediante un relè ed un LM317 utilizzato come limitatore di corrente, esse sono ricaricate. Quando ciò non è necessario o è appena stato completato un ciclo di carica, il relè viene aperto e le batterie non vengono caricate ulteriormente.

A livello software è previsto un certo valore d’isteresi, utile per evitare continue attivazioni e disattivazioni, quando la tensione delle batterie si trova prossima al valore limite.

Non sussiste quindi rischio di sovraccarico ed il conseguente pericolo di surriscaldamento delle batterie nel caso esse vengano lasciate troppo in carica: il dispositivo potrà essere lasciato permanentemente collegato alla rete elettrica, tranne quando utilizzato, e gestirà autonomamente la carica / scarica delle batterie.

In questo modo non sarà necessario sostituire le batterie una volta scariche, né aprire il dispositivo per prelevarle e ricaricarle separatamente.

È stato infine predisposto un connettore ICSP (In-Circuit-Serial-Programming) per programmare il PIC attraverso un programmatore PicKit 2 o successivi senza doverlo rimuovere dal circuito.

Data la dimensione significante del circuito, esso sarà diviso in sezioni per essere presentato in modo più conciso.

Lo schema elettrico del sistema di lettura della tastiera e trasmissione è il seguente:

(clicca sull'immagine per vederla più grande)

Sulla sinistra è presente il connettore ICSP utilizzato per la programmazione in-circuit.

I pin del microcontrollore che sono collegati alla matrice di pulsanti sono raggruppati nel BUS per semplicità di disegno e di comprensione.

Il modulo radio ricevitore posto sopra al microcontrollore è direttamente collegato a quest’ultimo.

Infine sono visibili in alto a destra i tre led di segnalazione visiva e le loro connessioni. L’ultimo di questi, dedicato alla segnalazione d’insufficiente carica delle batterie, è controllato dal circuito di comparazione che viene presentato qui di seguito.

Il circuito dedicato all’alimentazione e al controllo della tensione delle batterie è il seguente:

La tensione proveniente dal pacco batterie (6 elementi Ni-Mh da 1.2 V nominali) è stabilizzata dall’integrato MCP1700-5002 (stabilizzatore di tensione 5V low drop-out a basso consumo di corrente) e dai condensatori in poliestere richiesti per la rimozione del ripple residuo.

Attraverso un partitore (di alto valore resistivo per non aggiungere un eccessivo consumo di corrente) la tensione delle batterie viene dimezzata e confrontata con una impostabile attraverso il trimmer. Quest’ultimo dispone di una tensione stabile ai suoi capi perché è posto dopo il regolatore. Se la tensione delle batterie è inferiore alla soglia impostata, il led Err viene chiuso a massa dal LM311N, accendendosi per indicare la necessità di autoricarica.

Il circuito di autogestione della carica è il seguente:

(clicca sull'immagine per vederla più grande)

(il diodo segnato come 1N4148 in realtà è un diodo 1N4937. Voglio anche dire che per il circuito di limitazione della corrente del 317 ho preso spunto da un articolo che avevo letto qui su grix, non mi ricordo l'autore ma lo ringrazio comunque.)

Il funzionamento di questo circuito è semplice.

Quando il dispositivo è connesso al trasformatore esterno, la tensione continua di 12 V fornita è stabilizzata a 5V da uno stabilizzatore integrato LM7805 che è utilizzato per alimentare il PIC12F675.

Esso riceve in ingresso la tensione presente sulle batterie, dimezzata attraverso un partitore resistivo, e in uscita controlla il relè che collega il circuito di ricarica alle batterie.

Il microcontrollore decide in modo intelligente quando attivare il relè per poter caricare le batterie solo quando è necessario, prevenendo sovraccarichi che potrebbero danneggiarle in modo grave.

Questa decisione avviene comparando la tensione delle batterie a due soglie estreme. Se la tensione è superiore alla soglia superiore, la carica viene interrotta. Se invece è minore della soglia inferiore, la carica viene avviata. Per tutti i valori intermedi non è prevista alcuna azione da parte del PIC che si limita a mantenere lo stato precedente, conferendo così una discreta e necessaria isteresi.

Il circuito di ricarica è costituito da un LM317 in configurazione limitatrice di corrente. Le batterie utilizzate sono di tipo Ni-Mh, devono quindi essere caricate attraverso una corrente costante pari ad un decimo della loro capacità.

Nel nostro caso, essendo la loro capacità pari a 2100 mAh, dovremo caricarle con una corrente costante di 210 mA. Ci manterremo un po’ sotto questo valore, limitando il flusso di corrente ad un massimo di 167 mA calcolato nel seguente modo:

La resistenza si calcola secondo la formula:

R = 1.25 V / Ic [A]

Dove Ic è la corrente di carica (C/10 della batteria) e 1.25 V è il valore di dropout interno dell’LM317, fornito dal costruttore nel datasheet del componente.

Inoltre è necessario calcolare la potenza dissipata dalla resistenza secondo la formula:

P = V x I = 1.25 V x Ic

Per avere una corrente nominale di 210 mA si dovrebbe usare una resistenza pari a:

R = 1.25 V / 0.21 A = 6 Ohm

Che dissiperebbe una potenza pari a:

P = 1.25 V x 0.21 A = 0.26 W

Scegliamo una resistenza lievemente superiore del valore di 7.5 Ohm costituita ponendo in parallelo due resistenze di valore commerciale pari a 15 Ohm 0.25W (per sicurezza, poiché la potenza dissipata è prossima al limite nominale di 0.25W di una singola resistenza) ottenendo una corrente di carica pari a:

Ic = 1.25 V / 7.5 Ohm = 167 mA

Ed una potenza dissipata pari a:

P = 1.25 V x 0.167 A = 0.21 W

Le soglie di tensione che determinano l’intervento del microcontrollore sulla carica/scarica delle batterie sono state determinate osservando i grafici delle curve caratteristiche di carica tensione/corrente.

Ogni pila Ni-Mh ha una tensione pari a circa 1.38 V quando completamente carica e, alla tensione di 1.25 V, si trova già in fase di scarica rapida.

Si è scelto quindi di avviare la carica qualora la tensione fosse inferiore agli 1.30 V per elemento e di bloccarla quando raggiunga gli 1.35 V.

Il codice sorgente compilato e caricato nel PIC12F675 è presentato nel capitolo seguente.


Data la necessità di controllare in modo rigido la temporizzazione e la relativa semplicità del compito da svolgere, il software del trasmettitore è stato scritto in assembly.

L’ambiente di sviluppo utilizzato è stato PIC Simulator IDE, dotato di editor, compilatore assembly, simulatore di CPU e di periferiche.

Per permettere il corretto funzionamento del programma, i fuses vanno impostati nel modo seguente:

Brown-out reset: abilitato
Flash program memory code protection: disabilitato
Data EEPROM memory code protection: disabilitato
Power-up timer: abilitato
Watchdog timer: disabilitato
Low voltage in-circuit serial programming: disabilitato
RA5/MCLR pin function select: digital input
Oscillator selection: XT

La struttura del programma è riassunta nel diagramma di flusso seguente:

Viene attivata un’uscita alla volta e sono letti gli ingressi. Se un ingresso è attivo viene salvato il codice corrispondente nel registro W. Questa operazione è ripetuta per ognuna delle 5 uscite dopodiché, se il codice in W non è uguale a 0, significa che è stato premuto un tasto. In questo caso al radiotrasmettitore vengono inviati il codice ed il suo complementare. Segue una breve pausa e poi la routine riparte da capo.

(clicca sull'immagine per vederla più grande)

Il tasto Funzione, pur facendo parte della tastiera, non viene controllato durante la sua lettura ma è gestito semplicemente incrementando di 1 il comando da inviare nel caso sia premuto. Per poter permettere quest’operazione tutti i codici corrispondenti ai pulsanti sono multipli di 2, come si vedrà nel codice sorgente.

Se si attiva il tasto funzione da solo, non viene inviato nessun comando.

Per inviare un comando alternativo è necessario premere e mantenere premuto il pulsante Funzione per poi attivare il secondo tasto della combinazione.

Il PIC ricevitore assocerà il codice del tasto alla sua funzione primaria ed il codice del tasto aumentato di 1 alla procedura da eseguire quando quel pulsante viene premuto insieme al tasto Funzione.

Se desiderassimo che la pressione del tasto Funzione e del tasto ±1’’ decrementasse di un secondo il timer, potremmo implementarlo facilmente senza dover modificare il codice anche sul trasmettitore.

Se il codice corrispondente a ±1’’ fosse 4, premendo quel tasto da solo si invierebbe 4 ma, tenendo premuto il tasto Funzione e premendo quel pulsante, si invierebbe il comando 5.

All’interno del ricevitore il comando 5 sarà dedicato alla diminuzione dei secondi del timer.

Qui di seguito puoi scaricare il codice sorgente in assembler o il file esadecimale già compilato.


Codice Sorgente


La ricarica automatica del dispositivo è gestita da un microcontrollore a 8 pin PIC12F675.

Vengono semplicemente eseguite delle letture periodiche della tensione sulle batterie, decidendo di conseguenza se sussiste o meno la necessità di caricarle.

Il codice sorgente è stato scritto in C (ambiente di sviluppo mikroC). Per permetterne il corretto funzionamento i fuses del dispositivo devono essere impostati nel modo seguente:

Oscillator: Internal RC no clock
Watchdog timer: disabilitato
Power-up timer: disabilitato
Master clear enable: disabilitato
Brown-out reset: disabilitato
Code protect: disabilitato
Data EE read protect: disabilitato

La struttura logica del programma è relativamente semplice ed è riassunta nel diagramma di flusso seguente:

(clicca sull'immagine per vederla più grande)

Il codice sorgente scritto per attuare queste procedure è riportato qui sotto:


Codice Sorgente


La scatola metallica è stata comprata dall'istituto scolastico sul sito di RS. Per costruire la pulsantiera abbiamo praticato dei fori nella scatola e in una sottile lastra di plexiglass trasparente adatti ad accogliere i pulsanti. Tra il plexiglass e la scatola abbiamo interposto un foglio di carta lucida su cui abbiamo stampato la serigrafia illustrativa delle varie funzioni dei tasti.

Una volta posizionati i pulsanti, abbiamo creato manualmente la matrice interna (con molta pazienza :D ) e fissato il circuito principale. In seguito abbiamo anche costruito e fissato il circuito di ricarica.

Ecco una vista interna in cui è visibile la millefori doppiafaccia del circuito principale, il pacco batterie e il circuito di ricarica.

(clicca sull'immagine per vederla più grande)


Progettato all’insegna della comodità di utilizzo, il telecomando è un dispositivo sufficientemente piccolo e leggero da poter comodamente essere tenuto nel palmo di una mano. Alimentato a batteria, è in grado di controllare il tabellone segnapunti a distanza, da un qualsiasi punto della palestra.

È un valido dispositivo di comando alternativo nel caso il dispositivo principale, ossia la stazione trasmittente, presentasse dei malfunzionamenti.


L’intero circuito, realizzato su basetta ramata, è custodito all’interno di una piccola scatola di derivazione per esterni su cui è stata solidamente incastrata una tastiera a 20 tasti (matrice 4x5). I tasti sono stati colorati in modo diverso in modo che la comprensione delle varie funzioni risulti più facile ed intuibile, anche al primo colpo d’occhio.

L’alimentazione proviene da una batteria da 9V posta internamente, attraverso un interruttore posto lateralmente.La tensione viene stabilizzata da un regolatore lineare integrato a basso dropout e bassa corrente di riposo MCP1700-5002, con annessi condensatori in poliestere per l’eliminazione del ripple, che ci permette di avere, quando il telecomando non viene utilizzato ma è acceso, un consumo di corrente totale pari ad appena 800 µA, incrementando significativamente la durata della batteria.

Il cuore del circuito è il microcontrollore PIC16F628A a cui è delegato il compito di leggere i pulsanti premuti ed inviare al modulo trasmettitore il segnale corrispondente.La tastiera è letta dal microcontrollore attivando una colonna alla volta e leggendo i pin di ingresso collegati alle righe. Il PIC dispone di pull-up interni abilitati sui pin interessati in modo da non dover aggiungere resistenze esterne.Come per la stazione trasmittente, per aumentare il numero dei comandi disponibili uno dei pulsanti della tastiera è adibito a pulsante Funzione: premendolo assieme ad un altro pulsante si attiverà la funzionalità secondaria del pulsante premuto.I comandi inviabili in questo modo permettono di accedere a funzionalità speciali che saranno elencate in seguito.

Il clock è fornito da un oscillatore al quarzo esterno da 4 MHz, stabilizzato con due condensatori ceramici da 22 pF per disporre di una temporizzazione precisa necessaria per realizzare una trasmissione che rispetti esattamente le tempificazioni decise in fase di progetto.

Il modulo trasmettitore è uguale a quello utilizzato nella stazione trasmittente, un modulo Aurel TX-433/SAW s-Z funzionante a 433.92 MHz con piano di massa per l’antenna in cavo smaltato dimensionata a quarto d’onda e condensatore di bypass.

È stato infine predisposto un connettore ICSP per poter programmare il PIC attraverso un programmatore PicKit 2 o successivi senza doverlo rimuovere dal circuito.

(clicca sull'immagine per vederla più grande)

È visibile il modulo radio trasmettitore sulla destra, il connettore ICSP sulla sinistra e il BUS che rappresenta le connessioni dei pin del microcontrollore alla tastiera.

Ho omesso di riportare il regolatore di tensione perché è lo stesso utilizzato nella stazione di comando.

Ecco una vista del circuito interno:

(clicca sull'immagine per vederla più grande)


Esistendo le medesime necessità di controllo stretto delle temporizzazioni esposte a riguardo della stazione trasmittente, il software è stato scritto in assembly.

L’ambiente di sviluppo utilizzato è stato ancora PIC Simulator IDE.

Per permettere un corretto funzionamento del programma, i fuses andranno impostati nel seguente modo:

Brown-out reset disabilitato
Flash program memory code protection disabilitato
Data EEPROM memory code protection disabilitato
Power-up timer abilitato
Watchdog timer disabilitato
Low voltage in-circuit serial programming disabilitato
RA5/MCLR pin function select digital input
Oscillator selection XT

Il programma è praticamente identico a quello scritto per la stazione trasmittente, tanto che il diagramma di flusso mostrato in precedenza è valido per entrambi i dispositivi. Viene attivata una riga alla volta e sono letti gli ingressi. Se uno di essi è attivo viene salvato il codice corrispondente nel registro W. Questa operazione è ripetuta per ogni uscita dopodiché, se il codice in W non è uguale a 0, significa che è stato premuto un tasto, quindi al radiotrasmettitore vengono inviati il codice comando ed il suo complementare. Dopo una breve pausa la routine rincomincia.Il tasto Funzione è gestito semplicemente incrementando di 1 il comando da inviare nel caso sia premuto.Per inviare un comando alternativo è necessario premere e mantenere premuto il pulsante Funzione per poi scegliere il secondo tasto della combinazione.

Questa funzionalità è già stata descritta precedentemente a riguardo della stazione trasmittente pertanto sarebbe inutile ripetere la spiegazione.

Qui di seguito puoi scaricare il codice sorgente in assembler o il file esadecimale già compilato.


Codice Sorgente


La centralina ricevente si occupa della ricezione, della decodifica e dell’esecuzione dei comandi oltre che dell’aggiornamento del tabellone segnapunti e della gestione dell’avvisatore acustico (interfacciandosi con l’apposita scheda di comando).


Il circuito, realizzato su basetta ramata, è inserito in un contenitore metallico schermato esternamente e internamente.

Accanto ad esso si trova una sirena 230 V con la sua scheda di controllo.

La scatola utilizzata, approssimativamente a forma di parallelepipedo e fissata alla parete della palestra, apparteneva ad un vecchio elaboratore programmabile Olivetti.

L’alimentazione è fornita esternamente dal circuito che raddrizza la tensione presente sull’avvolgimento secondario dei toroidi presenti all’interno del tabellone (circa 22 V) ed è stabilizzata per la scheda con un LM7805.

Il cervello del sistema di controllo è costituito da un potente microcontrollore PIC18F4620 che si occupa della ricezione e della decodifica dei comandi.

La ricezione è affidata al modulo AC-RX della Aurel (operante, ovviamente, alla frequenza di 433.92 MHz) ed alla rete di trasformazione del segnale da ASK-OOK a NRZ-TTL presentata precedentemente.

Sebbene sia presente un oscillatore interno, si utilizza un quarzo esterno da 4 MHz con i relativi condensatori ceramici da 33 pF poiché è necessaria un’alta stabilità del clock per avere una buona precisione nella lettura dei comandi ricevuti.

Per la trasmissione dei dati dal PIC al tabellone è utilizzato un cavo multipolare a sei conduttori più schermatura esterna (dato, clock, i tre strobe, la massa e la messa a terra).

È stato predisposto un connettore ICSP che permette la riprogrammazione del PIC attraverso un programmatore PicKit 2 o successivi, senza dover smontare l’intero contenitore del circuito.

Lo schema elettrico del sistema ricevente è presentato di seguito:

(clicca sull'immagine per vederla più grande)

È visibile in basso sulla sinistra il connettore del cavo multipolare utilizzato per la trasmissione dei dati e la connessione di attivazione dell’avviso acustico, che è direttamente collegata alla relativa scheda di controllo.

In alto sulla destra è presentato il circuito di stabilizzazione della tensione ai 5 V richiesti dal microcontrollore come tensione di alimentazione ottimale, sotto tale circuito è visibile il ricevitore radio con la rete di condizionamento già presentata precedentemente.

Infine, in alto sulla sinistra è presente il connettore ICSP per la programmazione in-circuit. A fianco del circuito di ricezione è posizionato quello dedicato alla gestione dell’avvisatore acustico presentato nel capitolo seguente.


La sirena da noi selezionata e montata è un avvisatore acustico da cantiere, funzionante a tensione di rete, comodamente gestita dal PIC attraverso un’apposita interfaccia di potenza a relè.

Tale scheda è composta di un transistor BJT NPN Darlington BDX53C (hfe circa 750), controllato direttamente in base dal microcontrollore, che chiude un relè con bobina a 12 V e contatti capaci di portare 10A a 230V. Questo valore è ampiamente sovradimensionato, dato che la sirena ha un assorbimento limitato a soli 490 mA.

Lo schema della scheda di controllo (costruita su basetta millefori) è il seguente:

(clicca sull'immagine per vederla più grande)

La tensione in entrata (circa 22 V) viene stabilizzata da un regolatore integrato lineare LM7812 dotato di condensatori in poliestere per eliminare ogni residuo di ripple.

Il segnale di controllo (trigger) proveniente dal microcontrollore porta in saturazione il transistor BDX53C il quale chiude il relè attivando la sirena per il tempo in cui tale segnale resta alto.

Ecco una foto dell'interno della scatola metallica in cui è visibile sulla destra il ricevitore, sulla sinistra la sirena e al centro, in posizione verticale, la scheda di controllo di quest'ultima:

(clicca sull'immagine per vederla più grande)

In basso sulla destra è visibile il connettore ICSP sotto forma di connettore RJ45. In alto sulla destra trova posto il modulo ricevitore con la rete di condizionamento, mentre in alto sulla sinistra della scheda è presente la morsettiera che connette i sei cavi dati al cavo multipolare. A sinistra di questa, un'altra morsettiera riceve in ingresso la tensione che viene stabilizzata "a bordo" dal 7805.


Per quanto riguarda il ricevitore, abbiamo implementato a software molte funzionalità aggiuntive.

Configurazione avvisatore acustico Permette l’attivazione o la disattivazione dell’avvisatore acustico a seconda della necessità di disporre o meno dell’avviso di fine tempo. L’impostazione è salvata nella EEPROM così che sia ricordata anche spegnendo il tabellone. Il tabellone visualizzerà per qualche secondo la scritta “S On” oppure Soff” sui display del tempo per informare l’utente del cambio d’impostazione. La stessa comunicazione avviene ad ogni avvio del sistema.
Modalità di debug avanzato Permette la visualizzazione sul tabellone di informazioni utili al debug invece che dei punteggi. In questo modo è possibile capire la causa della maggior parte dei malfunzionamenti senza avere accesso fisico al circuito. Questa funzionalità verrà spiegata in seguito.
Reset completo Richiama una procedura di reset che riavvia il sistema di ricezione. Va usato il meno possibile, solo nei casi in cui il sistema non risponda più correttamente.
Modalità salvaschermo (test dei segmenti) Visualizza un’animazione sul tabellone. Dato che questa comporta l’accensione e lo spegnimento periodico di tutti i segmenti e dei punti luminosi, può essere utile per testare il buon funzionamento di tutti i LED e degli shift register. La pressione di un tasto qualsiasi su un dispositivo trasmittente terminerà la modalità salvaschermo.
Modalità power-saving Attivando la modalità di risparmio energetico il tabellone spegnerà tutti i segmenti, lasciando lampeggiare soltanto un punto luminoso con duty cycle pari al 20% (200 ms on, 800 ms off).Questa modalità è stata introdotta dato che il consumo del tabellone è considerevolmente elevato: in ciascun segmento scorre una corrente pari a circa 70 mA, i segmenti sono 7 per ogni display, i display interi sono 10 ed in più vi sono altri 4 segmenti ed i 7 punti luminosi (con identico consumo).

70 mA×81 segmenti = 5.67 A utilizzati solamente per l’illuminazione (con tutti i digit attivi).

In condizione normale, con tutti i punteggi a zero, i segmenti accesi sono 43, il consumo è quindi: 43 × 70 mA = 3.01 A.

Quando il tabellone non è usato questa modalità permette di ridurne drasticamente il consumo senza doverlo spegnere. La pressione di un tasto qualsiasi su un dispositivo trasmittente pone fine alla modalità di power-saving.

Standby automatico Quando il tabellone non riceve comandi per un certo periodo di tempo (30 minuti, impostabile a software) ed il tempo non sta scorrendo, viene attivata automaticamente la modalità power-saving. Ciò permette un elevato risparmio energetico quando il tabellone non è utilizzato o nel caso in cui fosse dimenticato acceso per un lungo periodo.
Modalità test acustico Per verificare il corretto funzionamento dell’avvisatore acustico e della scheda di controllo è disponibile un comando apposito che lancia una segnalazione acustica dopo un conto alla rovescia di 3 secondi.
Modalità test del canale Per analizzare la quantità di disturbi presenti sul canale di trasmissione è disponibile questo apposito comando.

Lanciando la modalità test del canale, il tabellone visualizzerà la scritta “Att” (“Attendere”) e si fermerà 3 secondi per effettuare la misurazione. Al termine della misurazione, che avviene monitorando il pin di uscita del modulo ricevitore, il tabellone visualizza per qualche secondo sul display dei punti locali una cifra esadecimale che rappresenta la quantità di disturbi presenti sul canale per un massimo di FFh (255).

Modalità di conteggio punti in "modalità pallapugno" Utilizzando i normali tasti di conteggio dei punti assieme al tasto funzione, è possibile contare i punti secondo la successione tipica del suddetto sport: 15, 30, 40, 0. Al passaggio da 40 a 0 verrà automaticamente incrementato il corrispondente numero dei set.

Date la relativa complessità del codice e le elaborazioni necessarie, il software del microcontrollore ricevente è scritto in C.

L’ambiente di sviluppo utilizzato è il compilatore mikroC pro versione 4.15.0.0.

Per permettere il corretto funzionamento del programma, i fuses vanno impostati nel modo seguente:

Oscillator: XT
Fail-Safe Clock Monitor Enable: Disabled
Internal External Switch Over Mode: Disabled
Power Up Timer: Disabled
Brown Out Detect: Disabled in hardware, SBOREN disabled
Brown Out Voltage: 2.0V
Watchdog Timer: Disabled-Controlled by SWDTEN bit
Watchdog Postscaler: 1:32768
CCP2 Mux: RB3
PortB A/D Enable: PORTB configured as digital I/O on RESET
Low Power Timer1 Osc enable: Disabled
Master Clear Enable: MCLR Disabled, RE3 Enabled
Stack Overflow Reset: Enabled
Low Voltage Program: Disabled
Extended Instruction Set Enable bit: Disabled
Background Debug: Disabled
Code Protect: Disabled

Tutte le protezioni della memoria (write, read, EEPROM, table) disabilitate.

Il programma si può suddividere indicativamente in tre sezioni:

  • La routine principale;
  • La routine di interrupt a bassa priorità;
  • La routine di interrupt ad alta priorità.

La routine principale si occupa inizialmente dell’impostazione, dell’inizializzazione delle periferiche interne e della configurazione degli interrupt, dopodiché entra in un ciclo perpetuo in cui controlla il flag che indica la necessità di aggiornare il tabellone, se tale flag è attivo viene lanciato un aggiornamento e lo si azzera.

In secondo luogo il ciclo principale si occupa anche di lanciare il salvaschermo (modalità power-saving o test dei segmenti) quando è necessario.

La routine di interrupt a bassa priorità si occupa della ricezione via radio, della decodifica e dell’esecuzione dei comandi. Quando viene ricevuto un comando, ne viene controllata la validità e, in caso sia corretto, viene eseguita l’azione corrispondente e si attiva il flag di richiesta refresh.

Il refresh non è svolto nella routine di interrupt, ma nel ciclo principale attraverso l’utilizzo del flag di richiesta, per il semplice fatto che il sistema deve essere in grado di ricevere dei comandi anche mentre effettua l’aggiornamento del tabellone. Se il microcontrollore fosse impegnato in quest’operazione durante l'arrivo di un comando, il PIC lo decodificherebbe immediatamente, per poi riprendere l’aggiornamento da dove l’aveva lasciato prima di gestire l’interrupt.

Infine, la routine di interrupt ad alta priorità è dedicata alla gestione del tempo attraverso il timer interno (TIMER0). Questa routine è responsabile dello scorrimento del tempo (ogni volta che passa un secondo, il tempo viene aggiornato e viene richiesto un refresh) e di tutto quello che ha a che fare con la temporizzazione come, ad esempio, la funzione della modalità di standby automatico o le routine di lampeggio.

Per la gestione di questi due interrupt è stato necessario impostare un sistema di priorità a causa della lunga durata della routine di lettura dei dati ricevuti: approssimativamente 360 ms.

Gli interrupt da TIMER0 arrivano ogni 65.536 ms e, se mancasse un sistema a priorità, sarebbe servito solo il primo interrupt arrivato. Nel caso in cui, durante lo scorrimento del tempo, fosse ricevuto un comando, si entrerebbe nella routine di lettura dei dati per 360 ms (ignorando 5 interrupt del timer) col risultato di rallentare lo scorrere del tempo di 328 ms per ogni comando ricevuto.

Dando una priorità bassa all’interrupt relativo alla ricezione ed una priorità alta all’interrupt del timer questa situazione non rappresenta più un problema, poiché l’interrupt del timer può interrompere la lettura dei dati.

Questa decisione potrebbe sembrare inopportuna perché ogni interrupt del timer arresta temporaneamente la lettura dei dati in arrivo, rischiando di interrompere la sincronia degli istanti di decisione. In realtà la durata della routine relativa all’interrupt del timer è minima (qualche decina di microsecondi) e, in quanto tale, non è assolutamente in grado di interferire con la lettura dei dati in arrivo.

Seguono i diagrammi di flusso delle tre routine correlati dalle relative spiegazioni. Essi sono soltanto un riassunto delle principali operazioni svolte nel programma, disegnare un diagramma comprensivo di tutte le funzioni sarebbe lungo ed inutile dato che tali informazioni sono facilmente reperibili nel codice sorgente.

Il seguente diagramma di flusso schematizza lo svolgimento della routine principale:

Dopo l’inizializzazione e la configurazione delle periferiche e delle porte, si entra nel ciclo principale. Questo ciclo prevede il controllo del flag di richiesta di aggiornamento e, in caso sia attivo, esegue un aggiornamento.

In seguito viene controllato anche il flag di richiesta della modalità salvaschermo/power-saving.

Se tale flag è attivo si entra nella routine salvaschermo.

Questa routine, non descritta nei diagrammi di flusso, dura finché il flag di richiesta del salvaschermo resta attivo.

Siccome si svolge come una parte del ciclo principale può essere interrotta regolarmente dagli interrupt.

In questo modo, quando un comando viene ricevuto e convalidato, il flag di salvaschermo viene azzerato e la routine termina istantaneamente, tornando al ciclo principale del programma.

Per scelta progettuale, ogni comando ricevuto in modalità salvaschermo la interrompe ma non viene eseguito. Così è possibile interrompere il salvaschermo premendo un tasto qualsiasi senza preoccuparsi delle conseguenze.

La routine relativa all’interrupt del timer è la seguente:

(clicca sull'immagine per vederla più grande)

Si controlla se il tabellone è inattivo da almeno mezz’ora e che non stia scorrendo il tempo. In questo caso viene abilitato il flag di richiesta salvaschermo (modalità power-saving automatica).

Viene poi verificato il flag che indica se il tempo stia scorrendo o meno:

In caso negativo, la routine termina qui.

In caso positivo, si incrementa un contatore e, se tale contatore ha raggiunto il valore di 16, si considera passato un secondo.

Nel codice sorgente sono visibili alcuni aggiustamenti per fare sì che questa temporizzazione sia precisa al microsecondo, in sostanza viene modificato il valore di preload del timer ad ogni interrupt.

Essendo passato un secondo, il tempo viene decrementato e il flag di richiesta refresh viene impostato.

Se il tempo è arrivato a zero il suo scorrimento viene fermato e, nel caso sia abilitata, viene lanciata la segnalazione acustica.

La routine dell’interrupt a bassa priorità si occupa della ricezione, della decodifica e dell’attuazione dei comandi ricevuti via radio:

Innanzitutto viene verificato il primo bit ricevuto: in caso questo non sia valido, la routine termina. In caso contrario, si procede alla lettura e al salvataggio del codice di comando e del codice di controllo.Se i due codici corrispondono il comando viene eseguito, altrimenti viene ignorato.

In ogni caso viene abilitato il flag di richiesta aggiornamento prima di ritornare al ciclo principale.

Qui di seguito puoi scaricare il codice sorgente in assembler o il file esadecimale già compilato.


Codice Sorgente


Il sistema implementato prevede delle funzionalità software dedicate all’individuazione dei problemi che possono, in associazione con delle corrette procedure analitiche, permettere l’identificazione dei malfunzionamenti senza dover avere accesso fisico al sistema.

Ciò è particolarmente utile per non dover rimuovere l’intera struttura in caso sopraggiunga un problema: attraverso tali procedure si procede all’individuazione del problema e, una volta trovata la sezione responsabile, è possibile un’azione di manutenzione mirata, rapida ed efficace. Se il sistema di ricezione riceve comandi errati o li riceve in modo saltuario, è possibile tentare di attivare la modalità di debug avanzato mediante la pressione della seguente combinazione di tasti sulla stazione trasmittente:

Tasto funzione “ ƒ ” + Tasto “ Avvio Tempo ”

Una volta entrato in modalità debug, il tabellone mostrerà la scritta “debg” sul display del tempo. Questa modalità visualizza molte informazioni utili invece dei punteggi. In particolare i dati visualizzati sono i seguenti:

  • Display set locali: registro flagr contenente i flag del programma;
  • Display punti locali: ultimo comando ricevuto (esadecimale);
  • Display punti ospiti: ultimo codice di controllo ricevuto (esadecimale);
  • Display set ospiti: il numero di zeri letti nell’ultimo bit di start. Il massimo valore accettato è 3, se il numero visualizzato è questo significa che l’ultimo dato letto era un disturbo ed è stato ignorato.

Queste informazioni permettono di capire l’origine dei problemi che interferiscono con la ricezione o la impediscono senza dover fisicamente intervenire sul sistema. E' inoltre disponibile un sistema di automatico in grado di misurare i disturbi nel canale di trasmissione e mostrare all’utente i risultati. Questo sistema, che risulta molto utile per capire se vi siano disturbi che possono influire sul corretto funzionamento del ricevitore, è descritto in seguito.

La visualizzazione del registro flagr sul primo display risulta estremamente utile perché i flag sono molto utilizzati nel programma e la loro lettura permette di capire che cosa stia eseguendo il PIC.

Siccome il registro contiene 8 flag, uno per bit, si è scelto di far corrispondere ad ogni segmento un flag. La mappatura del display è riportata a titolo di curiosità nella figura che segue:

Il segmento G (“Debug attivo”) dovrebbe risultare sempre acceso dato che indica la modalità di debug.

Il segmento A (“Refresh richiesto”) dovrebbe risultare sempre acceso perché indica la richiesta di refresh, la quale viene impostata ogni 65 ms se si è in modalità debug (provocando un refresh continuo).

Il segmento B (“Tempo avviato”) indica se il tempo sta scorrendo o meno.

Il segmento C (“In impostazione tempo”) è acceso se si è in modalità di impostazione tempo.

Il segmento D (“Usa avvisatore acustico”) indica se l’avviso acustico è abilitato o no.

Il segmento E (“Salvaschermo attivo”) indica se è attivo un salvaschermo. Siccome tale funzione è inibita durante la modalità di debug, questo segmento dovrebbe risultare sempre spento.

Il segmento F (“Refresh completo richiesto”) indica la necessità di eseguire un refresh completo alla fine della modalità di debug. Dovrebbe risultare sempre acceso.

Il punto decimale potrebbe essere associato ad un ulteriore flag utilizzato all’interno del programma, ma i led che lo compongono non sono presenti a livello circuitale.

Sul display delle centinaia di punti dei locali viene visualizzato un 1 fisso.

Sui display corrispondenti a decine ed unità di punti dei locali è visualizzato, in esadecimale, l’ultimo codice di comando ricevuto.

Sul display delle centinaia di punti degli ospiti viene visualizzato un 1 fisso.

Sui display corrispondenti a decine ed unità di punti degli ospiti è visualizzato, in esadecimale, l’ultimo codice di controllo ricevuto.

Per quanto riguarda il display corrispondente ai set degli ospiti, il numero visualizzato è il numero di campioni errati letti nell’ultimo bit di start verificato.

Un valore pari a 0 indica che il bit di start dell’ultimo comando ricevuto era completamente corretto. Nel caso arrivi un disturbo, questo numero può diventare al massimo 3 (oltre il PIC classifica il segnale come disturbo e lo ignora).

Un buon utilizzo delle informazioni visualizzate su questi display può permettere l’individuazione del problema senza necessità di intervenire fisicamente sul sistema. Ad esempio, se il display set ospiti mostra un 1 od un 2 al posto dello 0 subito dopo una trasmissione, probabilmente vi è un problema nella rete di ricezione e condizionamento. Oppure, se il codice comando non corrisponde al codice di controllo, può essere presente un malfunzionamento nella stessa sezione.


Se il sistema di ricezione presenta dei problemi che ne impediscono il regolare funzionamento può essere utile verificare l’eventuale presenza di disturbi sul canale di trasmissione.

Questa modalità visualizza sui display del tempo la scritta “Att” (“Attendere”) e mette in pausa l’intero sistema per 3 secondi durante i quali viene effettuata la misurazione. Si raccomanda di non inviare alcun comando durante questo tempo, perché non sarebbe interpretato e falserebbe i risultati. Al termine della misurazione, il tabellone visualizza per qualche secondo sul display dei punti locali una cifra esadecimale che rappresenta la quantità di disturbi presenti sul canale su un massimo di FFh (255).

In condizioni di regolare funzionamento, il risultato mostrato dovrebbe essere idealmente 00 o al limite pari a qualche unità. Un numero significativamente maggiore è indice di disturbi sul canale di trasmissione:

in pratica potrebbe essere presente qualche dispositivo che impedisce la regolare ricezione dei comandi, trasmettendo sulla stessa frequenza utilizzata dal sistema o su quelle immediatamente accanto.


Il dispositivo ricevente dispone di un ulteriore sistema di debug a cui si può accedere attraverso il connettore ICSP preposto.

Questo prevede che, mentre il sistema sta lavorando, un computer portatile si connetta mediante PicKit2 alla suddetta porta.

A questo punto è necessario avviare l’applicazione PicKit2 sul PC, e dal menu “Tools” selezionare “UART Tool” per avviare il terminale seriale RS232. Verrà così creato un canale che metterà in comunicazione diretta il computer con il microcontrollore ricevente mediante protocollo seriale RS232 a livelli di tensione TTL, rendendo possibile la visualizzazione sullo schermo dei messaggi prodotti dal sistema.

Tali messaggi dipendono dal firmware caricato sul PIC, pertanto per comprendere propriamente questa modalità di debug è necessario leggere e capire appieno il codice sorgente.

Ad esempio, alla ricezione di ogni comando il microcontrollore invierà il codice di comando, il codice di controllo ricevuto ed un terzo byte che sarà 11h nel caso i due codici siano coerenti (il codice di controllo sia cioè uguale al codice di comando negato), oppure 88h nel caso siano discordi.

Grazie a tali informazioni è possibile comprendere se, ad esempio, i dati trasmessi arrivino al PIC o meno, se essi vengano interpretati in modo corretto, ed altre informazioni utili, il tutto senza dover rimuovere il sistema dalla sua locazione.

Questa modalità può essere attivata o disattivata a piacere poiché il suo utilizzo è determinato da una costante inserita nel software del PIC ricevitore:

#define USA_SERIALE 1          // Flag per il debug via seriale

Impostando questo flag a 1 o a 0 si decide se mantenere o meno questa funzione.

Un’ulteriore possibilità offerta dal debug via cavo consiste nell’utilizzo dell’analizzatore logico integrato nel programmatore PicKit2 per visualizzare la temporizzazione di acquisizione dei dati in arrivo.Sempre connettendo il PicKit2 alla porta ICSP, avviare l’applicazione e dal menù “Tools” selezionare “Logic Tool” per accedere all’analizzatore logico a tre canali.

I primi due canali visualizzano le forme d’onda relative alla comunicazione seriale RS232 precedentemente descritta, mentre il terzo canale è connesso ad un pin del microcontrollore che quest’ultimo attiva durante la routine di acquisizione di ogni bit.

Il pin del PIC che si sta monitorando viene pilotato in questo modo:

quando il microcontrollore riceve un comando, viene verificato il bit di start. Se il bit di start è valido, ogni bit viene letto otto volte, come è stato mostrato nel capitolo relativo al protocollo di trasmissione in una figura che è riportata di seguito:

(clicca sull'immagine per vederla più grande)

Il pin collegato al terzo canale è normalmente basso e viene portato alto quando si entra nella routine che gestisce gli otto istanti di decisione.

In pratica, questo pin sarà dunque alto dal 4° al 20° millisecondo di ciascun bit. Dunque l’onda che dovrebbe comparire sul terzo canale dell’analizzatore logico è quella evidenziata in rosso nella figura che segue.

(clicca sull'immagine per vederla più grande)

La visualizzazione di questa forma d’onda permette di capire se il microcontrollore entra nella procedura di lettura dei comandi o se l’invio degli stessi si fermi prima della procedura di validazione del bit di start.

Si tratta di un ulteriore metodo di debug che rende possibile l’individuazione di eventuali malfunzionamenti senza dover rimuovere l’intero sistema di ricezione e comando.


Mi scuso per eventuali errori nella formattazione che mi possono essere sfuggiti, l'articolo è lungo e non ho ancora avuto tempo di rileggerlo tutto!

So che questo progetto può non essere immediatamente utile a tutti (quanti di voi hanno in casa un tabellone segnapunti da risistemare? :-D ) ma penso che possa avere un certo valore almeno come spunto didattico, trattandosi di un progetto completo che coinvolge vari aspetti dell'elettronica.

Spero che il progetto vi sia piaciuto e che non abbiate trovato l'articolo eccessivamente noioso.

Un saluto a tutti