I generatori PWM
Cerchiamo di schematizzare quali sono i punti indispensabili per avere due generatori PWM in fase e regolabili a piacere in larghezza:
la frequenza: dipende dal tipo di motori, miei esperimenti precedenti mi hanno portato a valori sotto ai 50 Hz
il numero di "gradini" di regolazione tra "STOP" e "V-max" (siamo in un microprocessore, non esiste la regolazione "continua")
l'input del grado desiderato di ampiezza degli impulsi (o di "velocità" se vi piace: è lo stesso)
Questi tre punti saranno le chiavi di volta di tutto il sistema, inferiranno anche sulla parte che riguarda gli scambi ed i relè.
il primo ed il secondo punto sono legati fra di loro ad un livello tale da pilotare la decisione sulla frequenza del generatore quarzato del PIC, vediamo perché:
La frequenza cui mi riferisco è la frequenza dei fronti di salita dell'onda quadra generata dal PIC, ma se la durata del periodo "on" è variabile, come vogliamo ottenere, dobbiamo stabilire quante "tacche", o "gradini", avrà la nostra regolazione: diciamo 10 ? mi sembrano poche per non avere dei "saltini" in accelerazione o rallentamento tra un "grado" e l'altro della regolazione... Si potrebbe dire 100, ma in questo caso mi sembra eccessivo, sarebbe come avere un'automobile con un cambio a 30 marce... andiamo su una via di mezzo: 64 (ad esperimenti fatti si è rivelata una scelta OK).
Una volta deciso che abbiamo 64 possibili "tacche", il problema si dirama in due:
sapere da che cosa e come quante "tacche-on" dobbiamo imporre
sapere come contare, che mezzo usare per contare queste "tacche-on" e le "tacche" totali.
la prima strada ci porta verso il convertitore A/D di segnali in input che il PC 16F877 possiede: ne ha 8 e ce ne bastano due, uno per ognuna delle due sezioni principali di binario, e per chiarire come si può usare il convertitore A/D del PIC vi mando a QUESTA PAGINA (il link non è ancora attivo), la seconda strada ci costringe a parlare di un'altra frequenza: il prodotto tra i 50 Hz citati prima e le 64 "tacche": 3200 Hz.
NOTA BENE: le due "strade" DEVONO riunirsi: una ci dice "quanto", l'altra "come".
Iniziamo con questa strana moltiplicazione (il prodotto tra i 50 Hz citati prima e le 64 "tacche") ed il suo risultato (3200 Hz), il motivo di questo viene dal fatto che, per ogni "tacca" (o, più correttamente, impulso elementare) il PIC deve verificare se deve mettere ad "1" l'uscita del PWM oppure deve resettarla a "0", quindi deve fare dei conti; questo implica che il clock "della macchina-PIC" deve essere ancora maggiore, ma in quale modo possiamo calcolare la frequenza del clock con un buon tasso di tranquillità ?
Io ho usato questo sistema:
per eseguire un'istruzione del PIC ci vogliono quattro impulsi del clock del quarzo
per fare i contri tra una "tacca" e l'altra temo ci vogliano 200 istruzioni (penso, forse meno)
oltre ai conti del PWM devo pensare anche agli scambi e ai relé, pensiamo "male": altre 200
quindi: 200+200=400, 400 x 3200 = 1.280.000 Hz
Andiamo a vedere il data-sheet del PIC e vediamo che il nostro "MegaHertz-e-un-quarto" è 1/8 (un ottavo) della frequenza più facilmente utilizzabile: 10 MHz, quindi se utilizziamo un quarzo da 10 MHz e facciamo i calcoli alla rovescia otteniamo che per tutto il sistema abbiamo a disposizione più di 3000 (tremila) istruzioni per ogni "tacca": molto di più del necessario ma non dobbiamo dimenticare che, oltre ai due PWM, dobbiamo anche far funzionare scambi e relè quindi, di quelle 3000 istruzioni, un bel po' serviranno ad altre cose.
Questo, appena svolto, è un molto elementare (ma piuttosto efficace) calcolo del tempo-macchina necessario all'elaborazione del programma per realizzare lo scopo che ci siamo presifissati: finchè sarà possibile avere questi margini, non avremo problemi. Per fare un esempio estremo: i problemi comiciamo ad averli sul nostro PC quando, dopo aer usato Win Xp per qualche anno ed avere regolarmente deframmentato il disco, decidiamo di installare Vista: la macchina, praticamente, si ferma perché il numero di istruzioni per far apparire sul video tutte quelle cose e nel nuovo modo sfumato, semitrasparente (Ehi, TU!, a cosa pensi: non sto parlando degli abiti della ballerina !!!) occorrono una marea di istruzioni in più rispetto al "pop, ecco qui" di prima, poi c'è l'antivirus che deve controllare più files di prima... e tutto il resto: occorrono una quantità enorme di istruzioni in più rispetto a prima, il clock della CPU è lo stesso, quindi ho bisogno di più tempo: tra un foglio Excel e l'altro esco a cena...
Bene, abbiamo impostato, sulla carta, il clock dei PWM: come si programma il PIC per farglielo generare ?
Ci sono due strade, alternativa l'una all'altra: a "programma" oppure a "interrupt":
La prima delle due, (IO NON LA USO QUASI MAI) prevede che se il PIC deve attendere del tempo tra un fronte (di salita o discesa) e l'altro, viene utilizzato un programmino con dei contatori: finchè quei contatori, dal valore iniziale previsto, non diventano ZERO, il PIC non si occupa di altro: conta e basta: a me sembra solo una perdita di tempo.
La seconda via prevede l'uso di un sistema, comune in qualche modo a TUTTI I PROCESSORI, che usa un segnale chiamato INTERRUPT, come funziona?
Per una spiegazione dettagliata preferisco rimandarvi a QUESTA PAGINA, in questo momento basti sapere che posso programmare il PIC in modo che ogni 300 microSec si ripeta un segnale che lo obblighi ad eseguire il controllo sulle "tacche".
Per verificare se il numero di istruzioni che il PIC esegue in 300 microSec potrà essere sufficiente, facciamo un semplice calcolo:
ogni istruzione viene eseguita usando QUATTRO impulsi dell'oscillatore a quarzo (10 MHz):
( ( 1/10.000.000) x 4) = 400 nanoSec
quindi in 300 milliSec possono essere eseguite 750 istruzioni
Avevamo detto che 200 erano sufficienti (vedremo che ne servono meno), quindi abbiamo "spazio" per svolgere altre funzioni, quando ne avremo bisogno, ora vediamo la sequenza di compiti da svolgere per generare correttamente i due segnali di output dei due PWM.
all'inizio di ogni sequenza, all'impulso numero ZERO, caricheremo "63" nel contatore degli impulsi elementari, caricheremo il "valore-1", supponiamo sia 5, nel contatore "PWM-1", e caricheremo il "valore-2", per esempio 10, nel "PWM-2", infine seguiamo due controlli:
il valore scritto in PWM-1 è maggiore di zero ?
SE SI, commuta "USCITA-PWM-1" al valore "alto", cioè "ON"
SE NO, commuta "USCITA-PWM-1" al valore "basso", cioè "OFF"
il valore scritto in PWM-2 è maggiore di zero ?
SE SI, commuta "USCITA-PWM-2" al valore "alto", cioè "ON"
SE NO, commuta "USCITA-PWM-2" al valore "basso", cioè "OFF"
fine controlli, esci dalla sequenza
ad ogni successivo impulso si deve diminuire di uno il contatore degli impulsi elementari e poi controllarne il valore: è ZERO ?
SE SI, vai a ri-eseguire tutta la sequenza numerata dal primo punto
SE NO:
PWM-1 è ZERO ?
no, PWM-1 è ancora maggiore di ZERO, decrementalo: è diventato ZERO ADESSO ?
SE SI: commuta "USCITA-PWM-1" al valore "basso", cioè "OFF"
SE NO: commuta "USCITA-PWM-1" al valore "alto", cioè "ON", è una riconferma dell '"ON" già presente
si, PWM-1:commuta "USCITA-PWM-1" al valore "basso", cioè "OFF", è una riconferma dell'"OFF" già presente
PWM-2 è ZERO ?
no, PWM-2 è ancora maggiore di ZERO, decrementalo: è diventato ZERO ADESSO ?
SE SI: commuta "USCITA-PWM-2" al valore "basso", cioè "OFF"
SE NO: commuta "USCITA-PWM-2" al valore "alto", cioè "ON", è una riconferma dell '"ON" già presente
attendi l'impulso successivo, in pratica: vai a fare dell'altro
Se si prova a rileggere la sequenza eseguendo il lavoro come lo farebbe il PIC, semplicemente cambiando i segnali di uscita con dei segni su un foglio di carta e rispettare i comandi "alto" e "basso" su due righe diverse, magari, invece di 64 impulsi elementari, ne possiamo usare 20: il risultato è sicuro.
Qui sotto riporto la parte di programma, scritta in Assembler-Microchip, che realizza proprio tutta la sequenza appena vista. Da notare una cosa: le cose NON si svolgono ESATTAMENTE NELLO STESSO ORDINE.
le istruzioni sono in carattere "COURIER", le spiegazioni in "questo carattere", forse sarà più facile capire qualcosa per chi non smanetta ancora sui PIC.
====================================
;
CLRW
IORWF ON2,W ; PWM2 ATTIVO?
BTFSC ZERO
GOTO $+4 ; NO
DECFSZ ON2,F ; DECREM.,SCADE?
GOTO $+2
BCF PWM2 ; SI, OFF
;
CLRW
IORWF ON1,W ; PWM1 ATTIVO?
BTFSC ZERO
GOTO $+4 ; NO
DECFSZ ON1,F ; DECREM., SCADE?
GOTO $+2
BCF PWM1 ; SI, OFF
;
DECFSZ PWM0,F ;DECREMENTA CONT.COMUNE
GOTO NO_TMR0 ; NON SCADUTO
BSF AD_SYNC
MOVLW .64 ; SCADUTO,
MOVWF PWM0 ; REINIZIALIZZA
;
MOVF READ_VAL_1,W ;REINIT
MOVWF ON1 ; PWM1
;
BTFSC REV0_1 ; ARR.-EMG. ON ?
GOTO GO_2 ; SI
BTFSC LKAD ; NO, BLOCCO STARTUP ?
GOTO GO_2 ; SI
;
MOVF ON1,W
IORLW .0 ; DEVE ATTIVARE
BTFSC ZERO ; LA TRAZIONE ?
GOTO GO_2 ; NO, POT.=0
REV_1
BTFSC REV1OR ;BASSA ORARIO ?
GOTO REV_1A ;SI
BTFSS REV1AN ;NO, ANTIORARIO ?
GOTO REV_1B ;NO, ARR.EMG
REV_1OK
BSF PWM1 ;SI, SOLO UN SENSO, OK
GOTO GO_2
REV_1A
BTFSS REV1AN ;ANCHE ANTIORARIO ?
GOTO REV_1OK ;NO, OK
REV_1B
BSF REV0_1 ; SET FLAG ARR.EMG.
BCF PWM1 ;DOPPIO SENSO O ARR.EMG.
;
GO_2
MOVF READ_VAL_2,W ;REINIT
MOVWF ON2 ; PWM2
;
BTFSC REV0_2 ; ARR.-EMG. ON ?
GOTO NO_TMR0 ; IS
BTFSC LKAD ; BLOCCO STARTUP ?
GOTO NO_TMR0 ; IS
;
MOVF ON2,W
IORLW .0 ; DEVE ATTIVARE
BTFSC ZERO ; LA TRAZIONE ?
GOTO NO_TMR0 ; NO, POT.=0
REV_2
BTFSC REV2SA ;SALITA ?
GOTO REV_2A ;SI
BTFSS REV2DI ;NO, DISCESA ?
GOTO REV_2B ;NO, ARR.EMG
REV_2OK
BSF PWM2 ;SI, SOLO UN SENSO, OK
GOTO NO_TMR0
REV_2A
BTFSS REV2DI ;ANCHE SALITA ?
GOTO REV_2OK ;NO, OK
REV_2B
BSF REV0_2 ; SET FLAG ARR.EMG.
BCF PWM2 ;DOPPIO SENSO O ARR.EMG.
;
NO_TMR0
;
Questa prima parte esegue il compito spiegato al punto 2.2.4 : se il contenuto della cella di memoria "ON2" è già ZERO, viene eseguito un salto ($+4) che porta immediatamente sotto al successivo "punto-e-virgola", cioè non si fa nulla per il "PWM2"; se invece "ON2" è maggiore di ZERO, viene decrementato e controllato (istruzione DECFSZ), se è diventato ZERO, si spegne il "PWM2" (istruzione BCF) altrimenti si passa oltre il successivo "punto-e-virgola"
-
Questa seconda parte, eseguita SEMPRE e subito dopo la precedente, fa le stesse cose ma riferendosi all' altro PWM, cioè controlla "ON1" e "PWM1"; come si può vedere, tutto corrisponde ad eccezione degli "1" contro i "2"
-
-
Questa parte, invece, realizza il controllo sulla fine dei 64 impulsi e la reinizializzazione del ciclo: se "PWM0" non è ancora scaduto, non succede nulla, tutte le istruzioni che seguono vengono ignorate perché si salta fino in fondo alla lista: "NO_TMR0" è il punto di uscita, altrimenti si riscrive 64 nel contatore generale,
poi si va a prelevere il valore di ampiezza da assegnare a PWM1 leggendolo dalla locazione di memoria chiamata "READ_VAL_1", in pratica la parte di programma (del TUTTO INDIPENDENTE DA QUESTA) che fa funzionare il convertitore A/D l'avrà scritta qui (in "READ_VAL_1") in un altro momento.
-
-
-
-
-
-
-
-
Poi vengono eseguiti dei controlli collegati alla logica della sicurezza operativa e di avviamento-sistema (per ora non è il caso di approfondirle; poi, poco più avanti, sotto a "REV_1" si controlla la posizione dell'invertitore di polarità: deve essere uguale al valore precedentemente letto; nel caso sia in posizione opposta o nullo (al centro), il PWM viene spento: non é ammessa la retromarcia "al volo" con lo slittamento delle ruote, è troppo "da giocattolo".
-
-
-
-
-
-
Le stesse cose, con gli stessi controlli, vengono eseguite per l'altro PWM a partire da questa riga: entrambi DEVONO avere lo stesso comportamento verso l'operatore e verso le cose che controllano
-
-
-
-
-
-
-Per capire quale dei due PWM muova i treni dell'anello in basso e quale quelli della parte in alto, basta leggere: dove c'è scritto "BASSA ORARIO" vuol dire che ci si riferisce all'anello in basso, seminascosto, dove c'è scritto "SALITA" vuol dire che ci si riferisce alla salita e alla stazione di Green Valley
-
-
-
-
-
In totale non arriviamo a 60 istruzioni e MAI vengono eseguite tutte, nel caso in cui si decrementino i contatori ma no si debba prendere alcuna decisione se eseguono soltanto 12; questo vuol dire che ci occorreranno soltanto 4.8 microSec, rispetto agli oltre 300 che devono passare tra un impulso elementare e l'altro. possiamo rilassarci.
A conclusione di tutta la spiegazione possiamo dire di aver realizzato DUE generatori PWM che lavorano (quasi) in fase (c'è una differenza tra i fronti di salita che si aggira intorno a qualche centianio di nanoSec) e possono avere i duty-cycle perfettamente indipendenti tra loro e compresi tra 0% e 100%.
====================================
Ma come faccio ad eseguire tutte queste istruzioni seguendo il ciclo giusto? Uso un temporizzatore interno nel PIC, ovviamente.
Ma come fa il temporizzatore a causare l'esecuzione della sequenza di istruzioni ? Usa lo INTERRUPT
E che cos'è l'INTERRUPT?
Qui spiego cosa è e come si comporta