Menu:

PPTEA Guida Galattica


di MarKoZaKKa


Questa è la discussione originale.


Indice:

Capitolo 6:
Un, due, tre... stella!

Bene, il led ora lampeggia a comando, o meglio lampeggia fino a che gli diamo il comando.
Pensiamo invece ad una cosa un pò piùraffinata, un led che si accende quando arriva il comando su una linea, e si spegne quando il comando arriva su un'altro input, avete qualche idea?
Innazitutto, teniamo buona la configurazione degli i/o, dato che già abbiamo quanto ci serve, cambio solo la notazione, perché quella bitmap mi stressa, conoscete tutti la numerazione esadecimale, vero?
No? peccato... lasciando perdere.
la matematica che sta dietro (nascosta e con un randello in mano), per quanto ci interessa ora, possiamo solo dire alcune cose:
la numerazione decimale utilizza 10 simboli per comporre i numeri (0,1,2,3,4,5,6,7,8,9), quella esadecimale ne usa 16 (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F), quella binaria ne usa due (0,1).
Per i nostri scopi, possiamo dire che usare la notazione esadecimale permette di esprimere un numero binario in maniera più compatta ed immediata, vediamo una tabellina di equivalenza tra le varie notazioni:

Notate che per passare da un numero espresso in binario alla notazione esadecimale, è in pratica sufficiente imparare a memoria la corrispondenza tra cifra hex e combinazione di 4 bit, mentre per passare da bin a dec bisogna eseguire dei calcoli.
In più, passando da numeri a 8bit a numeri a 16bit, il metodo non cambia; si prendono i bit a 4 a 4 e si sostituiscono con la cifra hex corrispondente.
Quindi la nostra SETIO espressa in hex sarà:

10 SETIO=&H7FFF

Meglio, no? Bene, abbiamo il led sul bit15, un input sul bit14, usiamo il bit13 per l'altro input, e diciamo che se il bit14 va H (alto) il led si accende e rimane acceso, se il bit13 va H il led si spegne e rimane spento.
Quindi il nostro programma diventerà:

10 SETIO=&H7FFF
20 IF (INPBIT(14)=LOW AND INPBIT(13)=LOW) THEN 20
30 IF INPBIT(13)=LOW THEN 50
40 GOTO 80
50 IF INPBIT(14)=LOW THEN 70
60 GOTO 110
70 GOTO 20
80 OUTBIT(15)=LOW
100 GOTO 20
110 OUTBIT(15)=HIGH
130 GOTO 20

Come dite? Non capite la riga 20?
Beh, non è sicuramente colpa vostra se non stavate attenti a scuola...
Allora, ricordate come funziona l'IF...THEN?
Bene, in questo caso, la condizione da verificare è più complessa, e dovrò parlare di OPERATORI LOGICI, ma lo farò nel prossimo capitolo, intanto imparatevi la corrispondenza tra hex e bin.

Torna all'indice

Capitolo 7:
to Be OR NOT to Be?

Allora, conosciamo bene nel nostro linguaggio il significato di quelle paroline che non ricordo come si chiamano (perché IO stavo attento, quando c'erano le materie tecniche, me la viaggiavo durante le lezioni di italiano e storia) e che sono "E", "O", "NON".
Bene, ci fu un tale di nome Boole che, avendo evidentemente molto tempo libero e campando di rendite immobiliari, si inventò l'algebra dei numeri binari, e da quel momento il mondo non fu più lo stesso.
In parole mooOoolto semplici, se A e B sono proposizioni semplici (oh, mamma...) che possono essere ciascuna o VERA o FALSA, esse possono essere combinate tra loro con degli operatori per ottenere una proposizione complessa che a sua volta potrà essere VERA o FALSA.
Gli operatori che individuò sono AND ("E"), OR ("O"), NOT ("NON"). Per farla breve e capirci qualcosa, si possono scrivere le cosiddette "Tavole della verità" (no, i testi sacri non c'entrano) degli operatori:

Vediamo quindi che NOT A è vero quando A è falso (e che scoperta, se non piove e io dico "piove", o sono pirla o sto mentendo...), che A AND B è vero solo quando sia A che B sono veri, che A OR B è vero quando almeno una tra A e B è vera.
Sia l'operatore AND che l'operatore OR possono operare su più operandi (operbacco!), ed esistono delle regole noiosissime che permettono di calcolare espressioni che contengono combinazioni di AND, OR e NOT, ma non ho nessuna intenzione di spiegarvele.
Vi faccio solo l'esempio della disuguaglianza logica, ovvero una espressione il cui valore è VERO solo se uno solo degli operandi è vero, e falsa in tutti gli altri casi:

Questa espressione è tanto utile che viene normalmente indicata con il nome di XOR; pertanto A XOR B = (A AND (NOT B)) OR (NOT A) AND B).

Quando poi un'altro tizio di nome Shannon intuì che l'algebra di Boole ed i circuiti commutatori avevano molto in comune, il mondo fu definitivamente diverso.
Tornando al nostro codice, adesso la capite la riga 20?

Se entrambi gli ingressi sono bassi, il programma rimane sulla riga 20, appena uno và alto, l'esecuzione prosegue; a questo punto si verifica quale delle linee è andata alta, e lo faccio controllando quale è rimasta bassa (perché mi piace complicare le cose semplici, anni di esperienza all'UCAS :-) ), e si esegue l'operazione appropriata.
Questo codice, pur facendo quanto ci siamo proposti, ha alcuni piccoli problemini, che però vedremo nel prossimo capitolo.

Torna all'indice

Capitolo 8:
al peggio non c'è limite

Mentre è molto difficile migliorare qualcosa, e più lo si migliora, più è difficile migliorarlo ancora, per peggiorare qualcosa che funziona ci vuole un'attimo.
Il codice visto nell'ultimo esempio, è già funzionante, fà quello che ci siamo proposti, però ha IMHO ancora due punti di miglioramento possibili:

1) si può ottimizzare il codice, rendendolo più "leggero" in termini di token occupati
2) se dallo stato bit13=H, bit14=H si passa allo stato bit13=L, bit14=H, l'uscita va immediatamente alta.
Se questo fosse il comando di una macchina, in caso di blocco del comando di start, si rischierebbe di stoppare e far ripartire immediatamente la macchina non appena si levasse il dito dal pulsante di stop.

Punto 1: dato che le condizioni lavorano sullo stato "L" degli input, è possibile ottimizzarle con l'uso dell'operatore NOT, nell'EABASIC, basta anteporre un "!" all'operando, così

10 SETIO=&H7FFF
20 IF (!INPBIT(14) AND !INPBIT(13)) THEN 20
30 IF !INPBIT(13) THEN 50
40 GOTO 80
50 IF !INPBIT(14) THEN 70
60 GOTO 110
70 GOTO 20
80 OUTBIT(15)=LOW
100 GOTO 20
110 OUTBIT(15)=HIGH
130 GOTO 20

Inoltre, è possibile eliminare la riga 20, senza modificare il funzionamento del codice.

Punto 2: per evitare questo problema, una delle strade possibili potrebbe essere quella di imporre il ritorno allo stato bit13=L, bit14=L prima di riprendere a controllare lo stato delle linee:

10 SETIO=&H7FFF
20 IF !(!INPBIT(14) AND !INPBIT(13)) THEN 20
30 IF (!INPBIT(14) AND !INPBIT(13)) THEN 30
40 IF !INPBIT(13) THEN 60
50 GOTO 90
60 IF !INPBIT(14) THEN 80
70 GOTO 110
80 GOTO 20
90 OUTBIT(15)=LOW
100 GOTO 20
110 OUTBIT(15)=HIGH
120 GOTO 20

vedete però che così, abbiamo perso la possibilità di portare il bit15 basso anche in presenza di bit13 alto... quindi se si bloccasse il famoso pulsante di start, stavolta non avremmo possibilità di stoppare la macchina, se non togliendo alimentazione.

A questo punto, occorre una bella boccata d'aria fresca, distrarsi un poco, per poi tornare a pensare al nostro problema:

se ho bit14 alto e bit13 basso, devo portare alto bit15

se ho bit13 alto, devo portare bit15 basso, e lasciarlo così indipendentemente da cosa succede a bit14.
dopo profonda riflessione, otteniamo questo:

1 SETIO=&H7FFF
2 IF (INPBIT(14) AND !INPBIT(13)) THEN 42
3 IF INPBIT(13) THEN 6 ELSE 2
4 OUTBIT(15)=HIGH
5 GOTO 2
6 OUTBIT(15)=LOW
42 IF (INPBIT(14) OR INPBIT(13)) THEN 42 ELSE 2

Azz... meno righe e pure meno token rispetto alle versioni precedenti... e funziona pure meglio!!!
In effetti, la risposta a tutto è la riga 42.
Al prossimo capitolo... se ci sarà

Torna all'indice

Capitolo 9:
convertiamoci col PPTEA

Bene, dopo aver giocato con gli I/O digitali del PPTEA, passiamo a parlare dei suoi ingressi analogici.
Ma prima di questo dobbiamo parlare dei Convertitori Analogico/Digitale, ovvero di quei circuiti che permettono di convertire una grandezza elettrica (solitamente una tensione) in un numero binario ad n bit.
Vi sono varie metodologie costruttive e tecniche raffinate per realizzare un ADC che sia più o meno veloce, preciso e lineare, e di sicuro non mi metterò a spiegarvi quali; per i nostri scopi è sufficiente capire come funziona un ADC.

Allora, immaginiamo il nostro segnale che vogliamo digitalizzare; si tratta di una rampa che aumenta linearmente tra 0 e 5V, per poi tornare a zero.
Se lo inviamo all'ingresso di un ADC a 4bit, questo lo convertirà in un numero tra 0 e 15, e spero sia chiaro a tutti perché... ecco, lo sapevo, encefalogramma piatto... allora se abbiamo 4 bit, le possibili combinazioni saranno 2ˆ4 (perché abbiamo 2 simboli, "0" e "1", elevato alla 4 potenza perché abbiamo quattro "posizioni" da usare per le combinazioni... se non ci credete, come vi ho già detto in passato, andate a cercare la matematica che se ne sta sempre lì dietro, nell'ombra, pronta con il randello) ovvero 16 combinazioni, di cui la prima sarà "0000" e l'ultima "1111"... e come sappiamo, il numero binario "1111" equivale a 15 in decimale.
Di quanto dovrà aumentare il segnale perché l'uscita binaria dell'ADC aumenti di 1? Lo otteniamo facendo la seguente operazione:

5V (massima escursione del segnale) / 15 (massimo numero binario) = 0,3333333333333...V

Quindi, ogni volta che il segnale in ingresso aumenterà di circa 0,333V, avremo un incremento di 1 del numero binario in uscita; quindi la nostra rampa continua tra 0 e 5V, verrà trasformata in una rampa di gradini binari, ciascuno dei quali equivarrà ad un range di valori dell'ingresso:

out binario input tensione
0000 da 0 a 0,333
0001 da 0,333 a 0,666
0010 da 0,666 a 0,999
...
1110 da 4,333 a 4,666
1111 da 4,666 a 5

Avrete sicuramente capito che per avere una maggiore raffinatezza di conversione, bisogna aumentare il numero di bit del convertitore.
Per quanto riguarda il PPTEA, i cinque convertitori a/d di cui è dotato, chiamati CAD, restituiscono valori binari a 10bit per segnali di ingresso tra 0 e 5V; dato che 10bit->1024combinazioni->1023 intervalli, avremo una risoluzione di
5V/1023=0,0048875855327468230694037145650049V, ovvero poco meno di 5mV.

Vediamo come utilizzare i CAD nel nostro codice.
Innanzitutto, dobbiamo dire quali sono le linee di I/O che possono essere usate come ingressi analogici: sono i bit 0,1,2,3,5 corrispondenti ai pin 2,3,4,5 e 7 del circuito integrato PIC18F2550 con il firmware PPTEA a bordo.
Abbiamo una istruzione che ci consente di dichiarare quanti CAD vogliamo usare nel codice, e si tratta della istruzione CADS:

CADS=0 nessun I/O configurato come ingresso analogico
CADS=1 bit0 configurato come ingresso analogico
CADS=2 bit0 e bit1 configurati come ingresso analogico
...
CADS=5 bit0, bit1, bit2, bit3, bit5 configurati come ingressi analogici

è importante sapere che nel debugger, l'istruzione CADS= prevale sulla SETIO, quindi se scrivo

10 CADS=5
15 SETIO=&H0000

oppure

10 SETIO=&H0000
15 CADS=5

nonostante siano in conflitto (la SETIO definisce tutti i bit come uscite, la CADS= ne definisce 5 come ingressi analogici) il risultato sarà sempre quello di avere 5 CAD configurati, indipendentemente dall'ordine in cui sono state scritte, anche se la logica vorrebbe che nel primo caso, definendo prima gli ingressi analogici e poi dichiarando tutti i bit come output, o il compilatore mi restituisce un warning, oppure prevale l'ultima istruzione... non ho mai fatto esperimenti in merito, per verificare che la stessa cosa avvenga in hardware, bisognerebbe chiedere lumi al cappellaio, pardon, elettricista matto... comunque, la seconda sintassi non dovrebbe dare problemi, quindi prima la SETIO e poi la CADS=, si sa mai.

Perfetto, ora non rimane che sapere come fare a leggere il valore binario corrispondente alla tensione applicata al CAD che ci interessa.
A questo ci pensa l'istruzione CADSx dove x è il numero (da 1 a 5) del convertitore che vogliamo leggere, quindi CADS1 per il primo, CADS2 per il secondo e così via.
Abbiamo anche una sintassi diversa, utile ad esempio per leggere i convertitori in un ciclo for...next, che è la CADSIND(x) dove la x puo essere una variabile che, ovviamente, deve assumere valori interi da 1 al massimo dei CADS configurati.

Visto che abbiamo già un bel programmino funzionante, perché non sfruttarlo?
Sostituiamo i due ingressi digitali con due ingressi analogici, e vediamo cosa accade...

10 SETIO=&H7F00
15 CADS=2 'configuro bit0 e bit1 come input analog
20 IF CADS1>=512 AND CADS2<512 THEN 40 'se bit1>2,5V e bit2>2,5V, uscita va HI
30 IF CADS2>=512 THEN 60 ELSE 20 'se bit2>2,5V uscita va LOW
40 OUTBIT(15)=HIGH
50 GOTO 20
60 OUTBIT(15)=LOW
70 IF (CADS1>=512 OR CADS2>=512) THEN 70 ELSE 20 'se bit1 oppure bit2 sono >2,5V, rimango sulla linea

Come funziona il programma, già lo sappiamo; abbiamo solo che ora vi è una soglia di commutazione per i due ingressi, pari al valore binario 512, ovvero 5V/1023*512=2,5V circa, per cui se la tensione applicata all'ingresso è inferiore a 2,5V tutto funziona come nel caso precedente di ingresso digitale LOW, se è uguale o superiore, funziona come nel caso precedente di ingresso digitale HI.
Nel compiler, potete usare i cursori per simulare l'ingresso analogico e vedere il funzionamento; in hardware, dovete collegare un potenziometro con il cursore sull'ingresso analogico, un estremo ai 5V e l'altro a massa:

5V
|
|
X
X
X
X<--- CAD
X
|
|
GND


Posso anche assegnare il valore del CADS ad una variabile, con la sintassi X=CADS1 oppure X=CADSIND(Y); in questa maniera "congelerò" la lettura dell'ingresso analogico nella variabile, al momento dell'esecuzione della riga.

Al prossimo capitolo, che è ora di nanna...

Torna all'indice

Capitolo 10:
CADS & The Measure...

Ora che siamo entrati nel favoloso mondo della conversione A/D sul PPTEA, vediamo quali possono essere i pericoli che possiamo incontrare.
Innanzitutto, la tensione di ingresso sull'I/O (che sia configurato come input analogico o digitale) non deve superare la tensione di alimentazione del PPTEA, ovvero 5V, pena problemi che possono arrivare anche al danneggiamento irreversibile; inoltre, per avere una misura affidabile, sarebbe opportuno che la tensione di alimentazione del PPTEA sia la più stabile possibile, ed il più possibile centrata sui 5,000V, questo perché per calcolare il valore dell'ingresso partendo dal risultato della conversione, nella formuletta vista prima, quei 5V che troviamo indicati sono proprio il riferimento di tensione del convertitore A/D, ovvero l'alimentazione del PPTEA;
se utilizziamo nella formula un valore di 5V, ma il convertitore ha il suo riferimento a 4,8V oppure 5,2V, avremo delle differenze tra valore del segnale reale e valore calcolato dal risultato della conversione.

Facciamo un'esempio ideale:
con ingresso a 2,50000V abbiamo come conversione 2,500*(1023/5)=511,5;
quindi nella realtà solo per questo motivo la lettura come minimo "ballerà" tra 511 e 512 a causa del rumore; se la Valim=4,8V, con lo stesso ingresso, avremo che il convertitore restituirà
2,500*(1023/4,8)=532,8125 ovvero 533;
se nel programma EABasic non teniamo conto del valore di tensione dell'alimentazione, ma facciamo i calcoli come se il riferimento fosse a 5V, otterremmo una misura pari a 533*(5/1023)=2,60508V, ovvero 105mV più del reale.
Le soluzioni possibili possono essere diverse:
realizzare una alimentazione stabile a 5,000V;
utilizzare il valore reale della alimentazione nelle conversioni (ovviamente, dimenticandosi delle costanti di conversione già predisposte dall'Elettricista nell EABasic, ovvero CAD_TO_VOLT e CAD_TO_TEMP, che sono valide solo con una tensione di alimentazione di 5,00V);
usare un riferimento di tensione per "calibrare" gli ingressi analogici prima di ogni misura, limitando così le variazioni della sorgente di alimentazione; la scelta del metodo dipenderà dalla precisione richiesta dalla misura e da quanto ci preoccupiamo della deriva dell'alimentazione.

Tornando nel mondo reale, poi, dobbiamo tenere presente il rumore a cui siamo sottoposti; rumore che ha diverse origini, la più importante delle quali è quella di natura elettromagnetica causata dalle innumerevoli sorgenti RF che ci circondano, e che può venire captato dai collegamenti del nostro circuito, andando a variare la tensione misurata dal CAD.
Una buona norma è quella di non limitarsi ad una lettura "one shot", ma eseguirne una serie per poi calcolare il valor medio "limando" quindi i picchi dei disturbi. Per questo, l'Illuminato ha creato l'istruzione CADSEQ, che permette con una sola istruzione EABasic di catturare una serie di letture del CADS.
Nel proseguo vedremo come utilizzare queste nozioni; alla prossima.

P.S. rileggendomi a partire dal capitolo 1, ho notato come abbia via via preso il tono di un docente... non preoccupatevi, è solo un calo di zuccheri...

Torna all'indice



Valid XHTML 1.0 Strict



[ Back to top ] [ Home ]