Sito Web di Vinicio Coletti

Controllo motore per barca radiocomandata

Indice progetti PIC Sito IK0WRB Sito di Vinicio Coletti

Descrizione generale

Questa scheda controller fa parte del progetto complessivo di una barca radiocomandata, che ho realizzato nel corso dell'estate 2002. La propulsione della barca è data da un motore elettrico in corrente continua di tipo 600BB e la scheda controllo stabilisce la velocità ed il verso (marcia avanti o indietro) del movimento.
Per una descrizione completa del progetto della barca radiocomandata, guarda qui.

Alimentazione e caratteristiche del circuito

Tutta la barca è alimentata da un accumulatore al piombo da 6 V 4.0 Ah. La tensione a batteria carica è di circa 6,7 Volt e ho quindi inserito, come unica regolazione della tensione, un diodo in serie, che protegge il circuito da inversioni accidentali di polarità e fa cadere la tensione di circa 0,7 V. I 6 V massimi risultanti, anche se un pò eccessivi per il PIC 16F84A (che non dovrebbe eccedere 5,5 V), non danno alcun problema e la scheda funziona perfettamente.
L'oscillatore utilizzato è quello classico per i PIC, con un quarzo da 4 MHz e due condensatori, per cui si ottiene un tempo di esecuzione per le istruzioni di 1 microsecondo.
La scheda controllo ha le seguenti connessioni e funzioni:

Misura degli impulsi

La funzione principale del programma che gira sul PIC è quella di misurare gli impulsi che arrivano dal ricevitore radio, calcolando quindi la velocità desiderata, che viene impostata attraverso adeguati impulsi pwm (pulse width modulation) sull'alimentazione del motore.
Ma è forse bene ricorda innanzitutto come funziona un radiocomando proporzionale. Se abbiamo a che fare, come nel mio caso, con un trasmettitore a 4 canali, esso avrà di solito due leve, ognuna con movimento orizzontale e verticale, per un totale di 4 comandi, appunto. Il trasmettitore legge la posizione di ogni leva e trasmette di continuo la seguente sequenza:

  1. Un impulso di almeno 4 millisecondi, per indicare l'inizio della sequenza
  2. Una pausa di 1 ms
  3. La posizione della prima leva, codificata come un impulso di lunghezza variabile da 1 ms (min) a 2 ms (max)
  4. Una pausa di 1 ms
  5. I passi 3 e 4 sono repetuti altre 3 volte, per inviare tutti e 4 i canali
una intera sequenza dura così al massima circa 17 ms e se il trasmettitore non fa pause ulteriori, ciò risulta in 59 comandi di posizione inviati ogni secondo, direi abbastanza anche per gli aeromodelli più veloci.
Il ricevitore radio demultiplexa i 4 canali su 4 differenti connettori, da dove escono degli impulsi TTL compresi tra 1 e 2 ms. La scheda è progettata per leggere tutti e 4 i canali, anche in parallelo (anche se come si vede gli impulsi sono sequenziali), ma per ora il software gestisce il solo canale 2 (controllo motore).
La maggiore difficoltà nella scrittura del programma di gestione è venuta dalf atto che il 16F84 ha un solo timer a bordo (escludendo il watchdog, che ha un uso dedicato) e quindi ho dovuto usarlo per tutte le funzioni, cioè sia per leggere gli impulsi in input che per generare quelli di output (ed anche altro!).

Come funziona

Quando arriva l'inizio di un impulso TTL, viene generato un interrupt sulla porta B e la routine di servizio dell'interrupt si limita a salvare il valore corrente di Timer0. Quanto l'impulso finisce viene generato un secondo interrupt e questa volta la routine calcola la differenza tra il valore corrente di Timer0 e quello salvato, la memorizza in una variabile ed attiva un flag di validità.
Nel loop principale del programma, quando viene rivelato il flag di validità per il canale 2 attivato, una subroutine azzera il flag, legge la durata dell'impulso, la elabora per produrre il valore da utilizzare per la pwm in output ed inoltre attiva o disattiva il relay che controlla la direzione del movimento.
Quanto Timer0 va in overflow (ogni circa 4 ms, visto che ho impostato il prescaler a 16x) se il valore pwm non è zero, il motore è attivato. Quando poi nel loop principale viene rivelato un valore di Timer0 superiore al valore pwm impostato, il motore viene spento. La frequenza degli impulsi pwm è quindi di 250 Hz, forse un valore un po' troppo basso, ma comunque funzionale.
Timer0 viene anche utilizzato per incementare alcuni contatori "lenti", usati in altre parti del programma. Ad esempio, quando mancano interrupt sulla porta B per circa 1 secondo, ciò indica l'assenza del segnale dal radiocomando e quindi il motore viene spento. Il programma quindi ricerca nuovi impulsi stabili e, quando arrivano, viene ripresa la normale elaborazione.
Per pilotare l'uscita motore utilizzo 4 pin della porta B in parallelo, per avere una corrente di 80 mA. Questa corrente va sulla base di un transistor 2N3055, la cui uscita va sulle basi di altri 3 transistor 2N3055 connessi in parallelo. Ho utilizzato questa configurazione super-Darlington semplicemente perché avevo a disposizione un modulo usato, con 4 2N3055 montati su un dissipatore e quindi pronti all'uso.

Il bug

La prima versione del programma aveva un difetto piuttosto serio: il motore non era mai completamente fermo, neanche quando la leva era in posizione perfettamente centrale e c'erano sempre degli impulsi errati che portavano brevemente il motore al massimo dei giri. Tutti i controlli sul programma furono assolutamente inutili, finché non pensai bene di andarmi a rileggere i manuali Microchip, sul funzionamento degli interrupt della porta B. Mi resi così conto che quando modificavo lo stato del motore, scrivendo sulla porta B, facevo partire degli interrupt errati, perché la scrittura sulle porte di I/O implica anche una loro lettura automatica!
Purtroppo avevo già costruito e testato il circuito, altrimenti probabilmente avrei utilizzato un pin della porta A ed un transistor, come output. E' bastato però modificare in modo adeguato il programma, sostituendo alla semplice istruzione clrf PORTB per fermare il motore, il seguente blocco:

bcfINTCON,RBIE; disabilita interrupt su PORTB
clrfPORTB; ferma motore
movfPORTB,f; rilegge PORTB per eliminare discordanza dei pin
bcfINTCON,RBIF; azzera PORTB interrupt flag, nel caso si sia attivato
bsfINTCON,RBIE; abilita di nuovo interrupt su PORTB
Lo stesso metodo è utilizzato quanto il motore viene attivato. Più economico di un transistor, direi.
Oltre al giusto modo di manipolare la porta B ho anche aggiunto dei filtri sulla durata degli impulsi, soprattutto nel caso che si utilizzi un radiocmando diverso da quello che ho attualmente. Così gli impulsi più corti di 0,9 ms o più lunghi di 2,1 ms sono ignorati, mentre quelli di 0,9-1,0 ms sono normalizzati ad 1 ms e quelli di 2,0-2,1 ms sono normalizzati a 2 ms.

Sviluppi futuri

Ci sono molte possibilità, se uno vuole veramente complicarsi la vita:

Il circuito


Per un disegno a risoluzione più alta, premi qui.

Lista dei componenti

Al di fuori della scheda di controllo


Indice progetti PIC Sito IK0WRB Sito di Vinicio Coletti

Crea il tuo counter