Può capitare di avere bisogno di un indicatore per una grandezza di cui
non è indispensabile conoscere il valore, bensì se esso è all' interno di
un certo range o al disotto di un dato limite.
In questi casi un display a caratteri (che deve essere letto) sarebbe meno
efficace di qualche LED (che è immediatamente apprezzabile).
In passato era stato realizzato un circuito con i classici comparatori,
genere LM311 o LM339, e un operazionale quadruplo, genere LM324 che forniva su
un LED bicolore le seguenti indicazioni:
- LED verde fisso - valore bassa
- LED verde lampeggiante - valore in salita
- LED lampeggiante verde/rosso - valore medio
- LED rosso lampeggiate - valore alto
- LED rosso fisso - valore eccessivo
In questo modo, con un solo punto su cui concentrare l' attenzione, è possibile visualizzare 5 diverse situazioni di una tensione che può arrivare da un partitore o da uno shunt o da un qualsiasi sensore o punto del circuito.
Nella pratica, questo genere di indicatore è sempre risultato efficace, nonostante la sua semplicità, perchè è di immediata lettura e permette all' utilizzatore una rapida valutazione. Le situazioni di lampeggio, poi, attirano l' attenzione molto più di una indicazione numerica da leggere ed interpretare.
Dato che all'ingresso abbiamo una tensione, possiamo discriminare anche lo stato
di carica di batterie, i livelli di tensioni in arrivo da sensori di pressione o corrente,
ma anche come indicatore di limiti di velocità, sulla tensione in uscita di convertitori F/V e ogni altra applicazione dove occorre individuare a prima vista lo stato di un segnale.
Con lo sviluppo attuale dei microcontroller, dotati di convertitore AD, una
revisione del circuito non poteva che passare dal tutto-analogico al
tutto-digitale, con il vantaggio di un numero molto minore di componenti e la
possibilità di variare i punti di commutazione senza aver bisogno di
calcolare partitori e disporre di resistori di valori poco comuni.
Il microcontroller analogico-digitale
Un caso pratico si può verificare con un dissipatore di calore per semiconduttori, del
quale occorre sapere se la temperatura supera un dato valore, per poter, ad
esempio, agire sulle regolazioni o inserire un sistema di ventilazione.
Data la necessità di valutare una tensione analogica, utilizziamo un
microcontroller dotato di modulo ADC, modulo che è
disponibile anche sui minuscoli PIC della serie 10F.
In particolare, lo troviamo in
10F220/22 , chip analoghi che si differenziano solamente per la quantità di
memoria disponibile.
Possiamo, ovviamente, utilizzare qualsiasi altro microcontroller con ADC,
ma, dato che servono solamente due pin per il comando del LED e uno per l'
ingresso della tensione da monitorare, i PIC10F a 6 pin (4 I/O) sono più che
adeguati, oltre ad avere un costo minimo e ad occupare uno spazio quanto mai
ridotto (nella versione SOT23-6).
Il circuito elettrico è, ovviamente, extra semplice:
|
IC1 è un comune 78L05 per fornire una tensione stabilizzata al PIC,
indispensabile dato che il suo ADC usa la Vdd come Vref per la
conversione.
In questo modo il circuito è alimentabile a partire da 7V circa, fino a oltre 24V. Se è già disponibile una tensione di 5V con poche decine di milliampere, IC1 e C3 possono essere omessi (ma C2 no).
C1 100nF
C2 2.2uF-10uF
C3 10uF-100uF
R1/2 220ohm |
IC1 (o una Vdd ben stabilizzata) è indispensabile: anche se il PIC è alimentabile di per sè a partire da 2V e non richiede una particolare
stabilità della Vdd, serve comunque una tensione di alimentazione precisa e di buona qualità, dato che essa è la Vref per la lettura
AD, altrimenti avremo difficoltà ad interpretare i risultati della
conversione.
Il modulo ADC dei PIC10F22x è a 8 bit e, in una applicazione semplificata come questa, la precisione della tensione di riferimento fornita da un lineare a tre terminali è sufficiente per la conversione.
Però, se necessitasse una conversione a 10 bit 0 12 bit, sarebbe indispensabile un diverso
microcontroller, dotato di ingresso per una Vref esterna, fornita da un riferimento di tensione di precisione (LM4040 e simili), oltre ad una Vdd a basso
rumore.
Il LED è un bicolore a tre pin, con un elemento rosso ed uno verde; in dipendenza dal tipo
usato, occorre variare le resistenze R1 e R2 per ottenere la luminosità voluta, ovviamente non superando i 25mA limite della corrente erogabile dai pin del microcontroller.
Il LED indica all' utilizzatore lo stato della temperatura
raggiunta, passando dal verde al giallo al rosso con l' aumentare della
temperatura stessa, la cui situazione è di lettura immediata. Sono state fissate le seguenti condizioni:
Temperatura |
LED |
Situazione |
T<40°C |
Verde |
Temperatura bassa |
40°C<T<50°C |
Verde/Giallo lampeggiante |
Temperatura in salita |
50°C<T<60°C |
Giallo |
Temperatura media |
60°C<T<70°C |
Giallo/Rosso lampeggiante |
Temperatura alta |
70°C<T |
Rosso |
Sovratemperatura |
Il "giallo" è il coloro che appare facendo commutare verde e
rosso con un duty cycle del 50% circa.
"giallo/rosso lampeggiante" è ottenuto mantenendo acceso il LED
rosso e commutando il verde; così pure il "verde/giallo
lampeggiante" è ottenuto mantenendo acceso il verde e commutando il
rosso.
Il "giallo lampeggiante" è ottenuto commutando contemporaneamente
rosso e verde.
Si potranno con facilità ottenere altri effetti, combinando i tempi di
accensione e spegnimento dei due LED.
Il funzionamento è semplice: il microcontroller legge la tensione da valutare e,
in base ai limiti impostati, comanda l'accensione dei LED.
Possiamo anche impiegare una uscita per un relay oppure utilizzare un
microcontroller con un numero maggiore di I/O per comandare una barra di LED e
così via.
Il programma
Ovviamente, dato il tipo di chip usato, che è un Baseline con risorse minimali, il programma è in Assembly ed è pure extra semplice.
|
Il flow chart del programma, anche nel caso di un semplice programma come questo, è un elemento importante per il programmatore, dato che la sua stesura permette di avere una immagine chiara di cosa si vuole ottenere e consente di trasformare il percorso logico in istruzioni in modo molto più semplice che se non lo si fosse disegnato.
Il programma "attivo" consiste essenzialmente in un loop che ricicla alla cadenza di circa 1/4 di secondo le seguenti operazioni:
-
lettura dell' ADC
-
valutazione del risultato secondo la tabella vista prima
comando dei LED
- temporizzazione
La temporizzazione determina la velocità di lampeggio. Variandola, si otterranno cadenze diverse. Dato che è una subroutine, può essere sostituita con semplicità .
|
Nel nostro caso, la tensione da misurare arriva da un economico sensore
attivo, MCP9701 di Microchip:
|
In particolare, l' uscita proporzionale alla temperatura
consiste in una tensione che varia di 19.5 mV/°C.
Il componente è disponibile nel classico contenitore TO-92, ma
anche in SOT23 e in SC70 per SMD.
Può valutare da -40°C a +150°C, con una accuratezza di ±2°C
tra 0 e 70°C.
|
|
E' previsto per una connessione diretta con l' ingresso
analogico del microcontroller e non richiede alcun circuito di
condizionamento o linearizzazioni particolari nel campo di letture
previsto.
Ovviamente è possibile impiegare altri sensori analoghi, come MCP9700 o LM35, adeguando i valori a cui si
effettua il passaggio di stato dei LED. |
Osserviamo che la risoluzione di uno step del valore in uscita del
convertitore AD a 8 bit, con 5V di tensione di riferimento è:
Vstep = Vref / step = 5 / 256 = 0.019531V
ovvero proprio i 19.5mV previsti dal costruttore. Questo semplificare grandemente il software, dato
che non servono particolari tarature o calcoli complicati.
MCP9701 ha un offset a 0°C pari a 400mV, il che gli permette di misurare
anche temperature al di sotto dello 0°C.
Quindi, la tensione ad una data temperatura superiore a 0°C è pari a:
Vt = .400 + (0.0195 * T)
Ad esempio, quella a 50°C sarà data da:
Vout50 = (19.5 x 50) + 400 = 975 + 400 = 1375 mV
Possiamo facilmente stilare una tabella che indica il rapporto tra la
temperatura e la tensione in uscita dal sensore:
Temperatura |
Tensione |
30°C |
0.985V |
40°C |
1.18V |
50°C |
1.375V |
60°C |
1.57V |
70°C |
1.765V |
Ma, in pratica, per quanto detto prima, non ci interessa neppure sapere il
valore della tensione, in quanto possiamo effettuare la valutazione
direttamente in base al valore a 8 bit risultante dalla conversione AD:
Temperatura |
Tensione |
ADC |
dec |
hex |
30°C |
0.985V |
50 |
32 |
40°C |
1.18V |
60 |
3C |
50°C |
1.375V |
70 |
46 |
60°C |
1.57V |
80 |
50 |
70°C |
1.765V |
90 |
5A |
I valori sono arrotondati, dato che nell' applicazione non importa una
precisione maggiore, ottenibile comunque con algoritmi di correzione un poco
complicati (bitwise) e descritti nelle Application elencate al fondo di queste
pagine.
Vediamo ora come trasformare il flowchart in istruzioni.
All' inizio trova posto la solita testata introduttiva-esplicativa, che è di aiuto per comprendere lo scopo del programma, oltre a tratteggiare le connessioni tra chip e resto dell' hardware.
;********************************************************************
;--------------------------------------------------------------------
;
; Titolo : Indicatore di
temperatura per dissipatori.
;
PIC10F220/222 + sensore MCP9701
; Versione : V0.0
; Ref. hardware : 110T4
; Autore : afg
;
;--------------------------------------------------------------------
;********************************************************************
;
; Impiego pin :
; ----------------
; 10F220/2 @ 8 pin DIP
6 pin SOT-23
;
; |¯¯\/¯¯|
*¯¯¯¯¯¯|
; NC -|1 8|- GP3
GP0 -|1 6|- GP3
; Vdd -|2 7|- Vss
Vss -|2 5|- Vdd
; GP2 -|3 6|- NC
GP1 -|3 4|- GP2
; GP1 -|4 5|- GP0
|______|
; |______|
;
;
DIP SOT
; NC
1 - -
; Vdd
2 5 Vdd
; GP2/T0CKI/FOSC4 3 4 Out
LED G
; GP1/AN1/ICSPCLK 4 3
Out LED R
; GP0/AN0/ICSPDAT 5 1
Analog In
; NC
6 - -
; Vss
7 2 Vss
; GP3/MCLR/VPP 8 6
MCLR
;
;
;********************************************************************
;################################################################## |
Ora selezioniamo il processore.
Siccome PIC10F220 e 10F222 si differenziano solamente per la quantità di memoria disponibile, la cosa più pratica è quella di creare un sorgente adatto per entrambi. La selezione del processore nella barra di comando di MPLAB garantisce il funzionamento dell' automatismo, gestito con #ifdef che seleziona gli include adeguati.
;--------------------------------------------------------------------
#ifdef __10F220
list p=10F220
, r = DEC
#include "p10f220.inc"
#endif
#ifdef __10F222
list p=10F222
, r = DEC
#include "p10f222.inc"
#endif |
In sostanza, se in MPLAB si è scelto nella creazione del progetto o attraverso il
comando Configure/Select Device il PIC10F220
la struttura #ifdef farà si che il compilatore esegua solamente le righe evidenziate:
;--------------------------------------------------------------------
#ifdef __10F220
list p=10F220
, r = DEC
#include "p10f220.inc"
#endif
#ifdef __10F222
list p=10F222
, r = DEC
#include "p10f222.inc"
#endif |
Nel caso in cui fosse selezionato il 10F222:
;--------------------------------------------------------------------
#ifdef __10F220
list p=10F220
, r = DEC
#include "p10f220.inc"
#endif
#ifdef __10F222
list p=10F222
, r = DEC
#include "p10f222.inc"
#endif |
Da notare che la definizione del processore appare nella lista dei simboli (file
.lst risultante dalla compilazione) preceduto da una doppia sottolineatura __ , che, nella convenzione di Microchip, indica una label
riservata dell' ambiente di compilazione.
In questo semplice modo si potrà scrivere un solo sorgente automaticamente adattabile a due processori differenti.
Da notare che stabiliamo il riferimento generale per i valori numerici alla radice decimale,
r = DEC, che è più "naturale" rispetto al default
esadecimale.
Passiamo ora alla Configuration Word , che è semplice, date le limitate risorse disponibili nel chip. In particolare:
;####################################################################
;
;====================================================================
;=
CONFIGURAZIONE
=
;====================================================================
__config _CP_OFF
& _MCLRE_ON & _IOFSCS_4MHZ & _MCPU_ON & _WDT_OFF |
- _MCPU_ON abilita un pull up interno sul pin MCLR, evitando la necessità di cablarne uno esterno
- _MCLRE_ON abilita GP3 come MCLR
- _IOFSCS_4MHZ fissa il clock a 4MHz con l' oscillatore interno
- _WDT_OFF e _CP_OFF disabilitano rispettivamente il Watchdog e la protezione
Osserviamo che questo chip consente di:
- avere un clock interno a 4MHz, condizione indispensabile dato il bassissimo numero di pin: se ne venissero dedicati 2 ad un oscillatore esterno ne rimarrebbero solamente altri due disponibili come I/O. Tra l' altro il clock può essere accessibile dall' esterno attraverso uno dei pin; qui questa opzione non è abilitata dato che servono tutti gli I/O disponibili.
- predisporre il pin MCLR sia come reset esterno che come I/O. Qui lo lasciamo alla funzione MCLR, per la quale non occorre neppure aggiungere una resistenza esterna di pull-up, dato che con _MCPU_ON abilitiamo quella integrata. Un componente risparmiato.
Assegniamo ora i valori limite dei gradini relativi alle varie modalità di funzionamento
;********************************************************************
;*
ASSEGNAZIONI LOCALI
*
;********************************************************************
; Uscita LMCP9701 19.5 mV/°C + 400mV
;
temp Vout ADCdec
ADChex
k1 equ .60 ;
40°C -> 1.180V -> 60 -> 3Ch
k2 equ .70 ;
50°C -> 1.375V -> 70 -> 46h
k3 equ .80 ;
60°C -> 1.570V -> 80 -> 50h
k4 equ .90 ;
70°C -> 1.765V -> 90 -> 5Ah
k5 equ .100 ;
80°C -> 1.960V -> 100 -> 64h |
Se si usano altri sensori (MCP9700, LM35, ecc) o altri step di temperatura, basterà variare di conseguenza questi valori.
Definiamo ora l'impiego dei GPIO e della memoria RAM.
In particolare, il comando dei LED in uscita si riferisce, come simbolo, direttamente alla shadow utilizzata per evitare il problema R-M-W.
Così nella RAM si deve riservare una locazione per questa shadow.
Usare in un caso così semplice una shadow di I/O non è strettamente necessario: essendo il carico costituito solamente da LED, il problema R-M-W non si presenta, ma è comunque opportuno utilizzare per principio la corretta procedura di accesso all' I/O dei PIC privi di registro LAT.
;====================================================================
;
DEFINIZIONE DI IMPIEGO DEI PORT
;====================================================================
;sGPIO map
; | 3 | 2 | 1 | 0 |
; |-----|-----|-----|-----|
; | in | LEDG| LEDR| AN0 |
;
#define LED_R GP1
;
posizione LEDR in GPIO
#define LED_G GP2 ;
" LEDG " "
#define LEDR sGPIO,LED_R ;
LED R tra pin e Vss
#define LEDG sGPIO,LED_G ;
LED G tra pin e Vss
;#define GPIO,GP0
; AN0
;#define GPIO,GP3
; MCLR |
In RAM sono riservate anche due locazioni per i contatori richiesti dalla routine di temporizzazione.
;####################################################################
;====================================================================
;= MEMORIA RAM =
;====================================================================
; RAM senza banchi
#ifdef __10F222
;Zona di 24 bytes
;----------------
CBLOCK 0x09 ;
area RAM da 0x08 a 0x1F
sGPIO ;
shadow I/O
d1 ;
contatori per Delay
d2
ENDC
#else ;
10F220 - meno RAM
;Zona di 16 bytes
;----------------
CBLOCK 0x10 ;
area RAM da 0x10 a 0x1F
sGPIO ;
shadow I/O
d1 ;
contatori per Delay
d2
ENDC
#endif |
Per semplificare l' uso della shadow ed evitare il ripetere di identiche istruzioni che renderebbero pesante la lettura del listato, può essere utile una piccola macro per trasferire la shadow nel registro di I/O.
;
local MACRO
; Copy shadow into GPIO
EXEC MACRO
movf
sGPIO, W ;
carica shadow in WREG
movwf GPIO ;
copia nel GPIO
ENDM |
Possiamo aggiungere alcune altre macro di comando dei LED; non sono indispensabili, ma sono utili per rendere più chiaro possibile il listato:
;
accende led Verde
Verde_on MACRO
bsf
LEDG
ENDM
; accende led Rosso
Rosso_on MACRO
bsf
LEDR
ENDM
; spegne led Verde
Verde_of MACRO
bcf
LEDG
ENDM
; spegne led Rosso
Rosso_of MACRO
bcf
LEDR
ENDM
; toggle led Verde
Verde_tg MACRO
movlw
LED_G ; b'00100' toggle
green
xorwf
sGPIO, f
ENDM
; toggle led Rosso
Rosso_tg MACRO
movlw LED_R ; b'00010'
toggle red
xorwf
sGPIO, f
ENDM |
Il lampeggio è effettuato cambiando stato al LED o ai LED interessati. Questo si ottiene con un toggle (inversione dello stato) del valore del bit corrispondente nel registro di I/O. I toggle sono effettuati con la funzione XOR; ricordiamo che XOR con 1 inverte il valore del bit.
Il programma vero e proprio inizia con la classica scrittura del valore di calibrazione dell' oscillatore interno.
Da comprendere bene che per questi PIC il vettore di reset non punta a 00h, ma all' ultima locazione della Flash, dove il costruttore, in fase di test del chip, scrive il valore di calibrazione dell' oscillatore, sotto forma di un opcode:
movlw valore_calibrazione
Quindi la prima istruzione che il PIC esegue dopo il reset non è quella che si trova a 00h, ma questa movlw .
Al clock successivo, il wrap around del program counter porta il suo valore a puntare a 00h, ovvero all' area di istruzioni inserite dall' utente.
Dato che WREG è caricato con il valore adeguato per la calibrazione dell' oscillatore interno, la cosa più semplice è quella di trasferire questo valore al registro OSCCAL.
La linea andlw 0xFE ha lo scopo di annullare l'eventuale uscita Fosc/4 dove questa è disponibile (se non viene utilizzata, come in questo caso).
;####################################################################
;====================================================================
;= RESET ENTRY =
;====================================================================
; Sicurezza per il valore di calibrazione
RCCAL ORG 0x1FF
res 1
; Reset Vector
ORG 0x00
; calibrazione oscillatore interno
andlw
0xFE ;
clear bit0: no Fosc out
movwf
OSCCAL |
Questa azione non sarebbe indispensabile, dato che l' attività del micro in questa applicazione non necessita di alcuna precisione particolare nel tempo di ciclo, ma anche qui è buona norma non saltare istruzioni che in altre occasioni possono essere indispensabili. Seguire una procedura precisa è indispensabile per non ritrovarsi con problemi le cui cause a volte sono individuabili con difficoltà.
Il programma principale inizia con il setup dell' OPTION_REG e della direzione dei pin.
Da osservare che i Baseline necessitano delle istruzioni particolari OPTION e
TRIS, cosa che è obsoleta per i PIC delle famiglie superiori.
Una semi-grafica aiuta a comprendere la funzione di vari bit ed assegnare il giusto valore. Qui l' uso del numero binario è molto più chiaro che non esprimendo il valore in esadecimale o decimale.
;####################################################################
;====================================================================
;=
MAIN PROGRAM
=
;====================================================================
MAIN:
; inizializzazioni I/O al reset
; OPTION default '11111111'
movlw
b'11010111'
;
1------- GPWU disabilitato
; -1------
GPPU disabilitato
;
--0----- clock interno
; ---1----
done
; ----0---
prescaler al timer
; -----111
1:256
OPTION ;
al registro OPTION
; ADCON0 default '11001100'
movlw
b'01000001' ;
ADC abilitato, GP0 = AN0
;
0------- ANS1
; -1------
ANS0
;
--00---- 0
; ----00--
CH 0
; ------0-
GO/DONE
;
-------1 ADC enabled
movwf
ADCON0
; GPIO
clrf
GPIO ;
preset GPIO latch a 0
clrf
sGPIO ;
e anche la shadow
movlw
b'1001' ;
GP1/2 = out
tris
GPIO |
La valutazione del risultato della conversione AD è effettuato con una sottrazione rispetto ai valori fissati per le varie gamme.
Va osservato che occorre usare subwf dato che i Baseline non hanno l'opcode sublw.
skpc (skip next line on carry
set) è una delle pseudo istruzioni supportate dall' Assembler MPASM e che è di lettura più immediata dell' equivalente btfss STATUS, C.
Verde_of
;
LED off
Rosso_of
EXEC ; esegue
in GPIO
ml call
ReadAD ;
read ADC
;range evaluation
movlw
k1 ;
< k1?
subwf
ADRES, w
skpc
goto
sel1
n1 movlw
k2 ;
< k2?
subwf
ADRES, w
skpc
goto
sel2
n2 movlw
k3 ;
< k3?
subwf
ADRES, w
skpc
goto
sel3
n3 movlw
k4 ;
< k4?
subwf
ADRES, w
skpc
goto
sel4
n4 goto
sel5 ;
> k4?
; LED driving
sel1:
Verde_on
;
T<40°C verde fisso
Rosso_of
goto
selxec
sel2: ;
40<T<50°C lampeggio verde/giallo
Verde_on
;
verde fisso +
Rosso_tg
;
toggle rosso
goto
selxec
sel3: ;
50<T<60°C giallo fisso
Verde_on ;
verde + rosso
Rosso_on
goto
selxec
sel4: ;
60<T<70°C lampeggio giallo/rosso
Rosso_on
;
rosso fisso +
Verde_tg ;
toggle verde
goto
selxec
sel5: ;
T>70°C rosso fisso
Verde_of
Rosso_on
selxec EXEC ;
drive LED
call
Delay025s ; 250ms
delay
goto
ml ;
loop |
Può essere interessante notare come la colorazione del testo, facilmente realizzata da un editor per programmazione, consente una immediata valutazione delle componenti di ogni riga.
Ad esempio, osserviamo come l' impostazione della colorazione (default tipico per i listati PIC) distingua in blu gli opcode, in verde il commento e in nero label e macro.
Aggiungiamo ora un paio di subroutines, una relativa alla conversione AD e l' altra alla generazione del ritardo voluto.
Sempre extra semplice è la gestione del modulo ADC: non occorre tempo di acquisizione tra una lettura AD e la successiva dato che esse sono già ampiamente cadenzate dalla routine di ritardo.
Il ritardo è del solito tipo waste time, dato che i Baseline non hanno interrupt; la struttura è derivata dal sito
di Golovchenko e potrà essere variata a volontà per ottenere un lampeggio a frequenza diversa.
Ovviamente si potrà anche usare il Timer0, che in questa applicazione non
alcuna altra funzione.
L' indispensabile END termina la compilazione.
;********************************************************************
;====================================================================
;=
SUBROUTINES
=
;====================================================================
;********************************************************************
; Read ADC
ReadAD bsf
ADCON0, 1 ;
avvia conversione
lpAD nop
btfsc
ADCON0, 1 ;
wait per fine conversione
goto
lpAD
retlw
0
; Delay = 0.25 seconds
; Clock frequency = 4 MHz
; 0.25 seconds = 250000 cycles
Delay025s: ;249993
cycles
movlw
0x4E
movwf
d1
movlw
0xC4
movwf
d2
Delay025s_0:
decfsz
d1, f
goto
$+2
decfsz
d2, f
goto
Delay025s_0
goto
$+1 ;3
cycles
nop
retlw
0 ;4
cycles (including call)
;
===================================================================
; =
THE END
=
;===================================================================
END |
Da notare che il ritorno dalla subroutine richiede retlw, dato che return non c'è nel set di istruzione dei Baseline. Si potrebbe pensare di introdurre un equate :
RETURN = RETLW
per mantenere uniformità di scrittura con altri PIC, ma questo è del tutto inutile: possiamo anche scrivere direttamente return, dato che MPASM esegue ugualmente la compilazione senza errori, operando la sostituzione automatica col giusto opcode (e segnalando l'operazione con un warning).
Comunque il consiglio è quello di utilizzare il set di istruzioni del chip che si sta impiegando; questo consente di avere una maggiore coscienza di cosa si sta facendo in relazione all' hardware.
Quanto all' accensione dei LED, si potrebbe pensare a gestirli con due PWM in modo da avere un passaggio del colore verde-giallo-rosso uniforme, ma si è visto che nella pratica il passaggio con il lampeggio è molto più efficace per l' operatore che identifica immediatamente con questo un momento di transizione da una certa situazione ad un'altra.
Invece, volendo, un pwm potrà essere applicato allo stato on dei LED, aggiungendo un altro loop di temporizzazione a frequenza maggiore di 100 Hz, allo scopo di ridurre i consumo, dove necessario, dato che i LED bicolori
solitamente necessitano di più di 10mA per avere una luminosità soddisfacente.
Ovviamente una struttura del genere può essere usata anche per comandare piccoli relais, opto isolatori o cicalini, creando uscite di allarme o attenzione in relazione al valore misurato. In questo caso è necessario aggiungere una isteresi sufficiente a scongiurare il saltellare dei contatti per variazioni minime attorno ai valori di soglia.
La realizzazione
Data
l' estrema semplicità del circuito, la realizzazione può essere a piacere o
secondo la necessità dell' applicazione.
Qui un paio di esempi di circuiti stampati (scala 2:1 circa):
La
versione SMD è ovviamente la più piccola, ma non di molto, dovendo
utilizzare un circuito stampato a singola faccia.
|
Però
sono usati componenti passivi SMD anche per la versione con il chip
in package DIP8 per avere una piccola superficie del circuito
stampa. Il regolatore a tre terminali è comunque in TO92.
Nella
versione in foto, lo zoccolo del chip è sostituito con pin singoli
(non sono inseriti quelli relativi ai pin non internamente connessi
al chip è nella versione DIP8).
Un
connettore a pettine passo 2.54 permette di collegare la schedina
con cavi i direttamente su un altro circuito stampato.
Dato
il bassissimo numero di componenti necessari, si potrà realizzare il circuito
in mille altri modi, anche su una millefori.
|
Variazioni
sul tema
Vediamo
una possibile variazione: indicare lo stato di una tensione, ad esempi quella
di una batteria da 12V.
Facciamo
pervenire all' ingresso analogico la tensione da valutare, attraverso un
partitore:
|
R3
e R4 sono il partitore di ingresso. In questo caso potrebbe avere un
valore di 1:4, rendendo possibili tensioni di ingresso fino a 20V.
In questo modo abbiamo Vin = 20V -> Vgp0 = 5V.
Potrebbero
essere rispettivamente 6k2 e 2k2 ohm o 11k e 3k9 o altre
combinazioni in rapporto 1:4.
Se
è il circuito è collegato alla batteria di un veicolo, si potrà
mettere un diodo zener (5V6-1/4W) in parallelo a C1 per evitare che
la tensione in ingresso raggiunga un limite pericoloso per
microcontroller. Se
non si prevede che la tensione in ingresso superi i 20V, lo zener può
essere omesso.
|
Ovviamente
il partitore potrà essere adeguato alla tensione che si vuole misurare e la
stessa struttura adattata ad altri range di tensione in ingresso.
Stabiliamo le seguenti condizioni del LED:
Tensione |
LED |
Vin
< 10.5V |
Rosso lampeggiante |
10.5
< Vin < 11.5V |
Rosso |
11.5
< Vin < 12V |
Giallo |
12
< Vin < 14.5V |
Verde |
14.5V
< Vin |
Rosso/verde lampeggiante |
Anche
qui i valori indicati sono del tutto adattabili alle gamme che si vogliono
valutare. Basta cambiare di conseguenza i valori delle costanti relative.
Assegniamo
allora i valori limite delle varie modalità di funzionamento del LED:
;********************************************************************
;*
ASSEGNAZIONI LOCALI
*
;********************************************************************
; Partitore 1:4
;
Vin ADCdec ADChex
k1 equ .134 ;
10.5V -> 134 -> 86h
k2 equ .146 ;
11.5V -> 146 -> 92h
k3 equ .153 ;
12V -> 153 -> 99h
k4 equ .184 ;
14,5 -> 184 -> B8h |
Modifichiamo
l' analisi del risultato della conversione per adeguarla alle nuove
condizioni.
;
LED driving
sel1:
Verde_of
;
Vin < 10.5V Rosso
Rosso_tg ;
rosso lampeggiante
goto
selxec
sel2: ;
10.5 < Vin < 11.5V
Verde_of
;
rosso fisso
Rosso_on
goto
selxec
sel3: ;
11.5 < Vin < 12V
Verde_on ;
giallo fisso
Rosso_on
goto
selxec
sel4: ;
12 < Vin < 14.5V
Rosso_of
;
verde fisso
Verde_on
goto
selxec
sel5: ;
Vin > 14.5 rosso/verde lampeggiante
btfss sGPIO,GP1
; se GP1 e 2 sono uguali, differenziali
goto a1 ;
per usare il ciclo come cadenza per il
btfss sGPIO,GP2 ;
lampeggio
goto
lamp
goto
adj
a1 btfsc
sGPIO, GP2
goto
lamp
adj: ;
GP1=GP2 - differenzia
Rosso_on
Verde_of
lamp:
Verde_tg ;
rosso/verde lampeggiante
Rosso_tg
selxec EXEC ;
drive LED
call
Delay025s ;
250ms delay
goto
ml ;
close loop |
Una
leggera complicazione è inserita per ottenere il lampeggio verde/rosso.
Il problema che si può generare è il seguente: in mancanza di interrupt, per
poter sfruttare il ciclo come cadenza del lampeggio con il sistema del toggle,
occorre che i due bit di comando dei LED siano differenti in quanto è
necessario che la prima entrata nella selezione sel5 abbia
valori diversi per i due bit che comandano il LED rosso e quello Verde.
Se si passa da sel4
a sel5 ,
ovvero con una tensione crescente, non c'è problema. In sel4
i due bit di comando dei LED
hanno valore diverso, quindi il loro toggle produce un lampeggio alternato.
Un flow chart rende evidente la cosa.
|
Se si passa direttamente da sel3 a sel5 per un aumento rapido di tensione (il ciclo di acquisizione è molto "lento"), si arriva con i due bit dello steso valore, il cui toggle porterebbe ad un lampeggio del colore giallo e non all' alternanza rosso/verde voluta.
Occorre quindi che all' ingresso della fasesel5 i due bit siano di valore diverso. Se così non fosse, il ciclo dei toggle non permetterebbe il lampeggio rosso/verde.
Non ha alcuna importanza come siano settati la prima volta, perchè i passaggi successivi del ciclo ne invertono lo stato e questo garantisce il lampeggio.
|
Certamente
si possono utilizzare altri percorsi logici per generare il lampeggio, ma
quella usata è la più banale e semplice in assoluto.
Ovviamente, se si
preferisce una diversa reazione del LED, basta variare le operazioni
effettuate ad ogni selezione.
Anche qui si può
pensare al collegamento di relais che si inseriscono/disinseriscono a seconda
della tensione (sempre ricordando di inserire una minima isteresi nei punti di
commutazione).
Una ulteriore
variazione potrebbe essere quella di utilizzare il GP3 come
ingresso digitale e selezionare con il valore di tensione applicato due diverse
configurazioni del set di intervento e/o del funzionamento dei LED, potendo
così usare uno steso chip per due diverse applicazioni.
Come
si vede, una semplicissima programmazione in Assembly su un PIC tra i più
piccoli disponibili (non solo per le dimensioni, ma anche come risorse)
permette risultati sensibili.
Il
programma potrà servire come base per realizzare ogni genere di indicatori.
Si potranno associare diverse condizioni di accensione dei LED e diverse
soglie di intervento, con uscite diverse dal LED bicolore usato.
Documentazione
Passare il sorgente ad un altro PIC.
Possiamo passare il sorgente ad altri PIC?
Certamente sì: vediamo qualche
esempio.
|