Wattmetro BF
© by Vittorio Crapella - i2viuWATTMETRO DI B.F. PER CARICHI 4 - 8 OHM
Quello che segue è il progetto di un Wattmetro capace di misurare potenze fino a 150W e mostrare il valore su 3 digit di tipo a 7 segmenti utilizzando un ST6220 che legge la tensione con l'ADC proveniente da un circuito di condizionamento fatto da un
Il micro ST6 prende il valore letto con ADC ne fa il quadrato e poi divide per 400 e mette il risultato a tre cifre gestendo la virgola indicando potenze da 0,01 W fino a 150 W.
Tramite un deviatore è possibile leggere potenze sia per carichi da 4 sia da 8 Ohm mantenendo lo stesso fondo scala di 150W.
La foto mostra il display che segna 14,4 Watt e il multimetro che segna i volt efficaci sul carico di 4 Ohm
Pw = V2 / R = 7,54 x 7,54 / 4 = 56,85 / 4 = 14,2 W il display segna 14,4 W
Per la taratura dei trimmer sull'entrata si può fare prendendo una tensione del secondario di un trasformatore con tensione compresa tra 9 e 15Vac ma va bene anche 18 Vac oppure direttamente prelevando la tensione su una cassa dell'ampli mentre riproduce ad un livello costante un segnale a frequenza fissa ad esempio 1Khz.
La procedura migliore è la seguente:
1- accertarsi che LM358 sia alimentato correttamente e che in uscita dia 0V quando entra 0V.
2- regolare i trimmer a metà corsa e mettere il deviatore sui 4 Ohm
3- staccare provvisoriamente l'ingresso ADC dall'uscita del 358
4- inviare il segnale d'ingresso proveniente da un trasformatore o dall'amplificatore
5- misurare la tensione alternata reale in entrata con voltmetro Vac (valore efficace)
6- misurare la tensione in continua con multimetro ai capi del 10uF in uscita del 358
7- regolare il trimmer T1 per leggere sul multimetro (punto 6) pari a Vac punto 5 diviso 5
8- deviare sugli 8 Ohm e regolare il trimmer T2 per leggere sul multimetro (punto 6)
pari a Vac punto 5 diviso 7
9- Unire ADC out con ADC in e controllare che quanto indicato sul display sia uguale ai W calcolati con la formula Vac al quadrato diviso 4 o 8 Ohm a seconda del caso, se necessario ritoccare i trimmer per una migliore taratura.
Sono state verificate misure per frequenza comprese tra 20 Hz e 8 KHz senza notare variazioni significative di potenza misurata.
Superato gli 8 KHz man mano che la frequenza sale sul display la potenza indicata tende a calare questo a causa dei diodi 1N4148 che cominciano a far sentire il loro limite.
Usare diodi più veloci sicuramente permettono misure anche a frequenza superiore, un diodo ideale già utilizzato in altre occasioni è il BA243.
Foto della realizzazione di Sergio G.
LISTATO
.title "POWER BF" ;23-12-2009 By Vittorio C. i2viu
.vers "ST62E20"
.w_on ; Abilita la memoria a finestre
a .def 0ffh ;Registro accumulatore
x .def 080h ;Registro x
y .def 081h ;Registro y
v .def 082h ;Registro v
w .def 083h ;Registro w
port_a .def 0c0h ;Registro Dati porta A
port_b .def 0c1h ;Registro Dati porta B
port_c .def 0c2h ;Registro Dati porta C
pdir_a .def 0c4h ;Registro Direzione porta A
pdir_b .def 0c5h ;Registro Direzione porta B
pdir_c .def 0c6h ;Registro Direzione porta C
popt_a .def 0cch ;Registro Opzioni porta A
popt_b .def 0cdh ;Registro Opzioni porta B
popt_c .def 0ceh ;Registro Opzioni porta C
ior .def 0c8h ;Registro Opzioni per le Interruzioni
addr .def 0d0h ;Registro Dati dell'A/D converter
adcr .def 0d1h ;Registro di Controllo dell'A/D converter
psc .def 0d2h ;Registro per il Prescaler del Timer
tcr .def 0d3h ;Registro Dati del Timer
tscr .def 0d4h ;Registro TSCR del Timer
wdog .def 0d8h ;Registro del WatchDog
drw .def 0c9h ;Registro della zona dati ROM (Rom Data Window)
;--------------------------------------
; VARIABILI usate da questo programma
;--------------------------------------
decimi .def 084h ;display
unita .def 085h ; "
decine .def 086h ; "
resto .def 087h ;divisione
risul .def 088h
aa .def 089h ;per contare le conversioni
n1 .def 08ah ;byte più significativo MSB
n2 .def 08bh ;byte meno significativo LSB
n3 .def 08ch ;divisore
rislsb .def 08dh ;risultato LSB
rismsb .def 08eh ;risultato MSB
punto .def 08fh ;virgola display
;***************************
;*** Settaggio iniziale ***
;***************************
.org 080h ;080h per 20/25 mentre 880h per 10/15
inizio ; INIZIALIZZAZIONE DELLE PERIFERICHE
ldi wdog,0ffh ; RICARICA IL WATCH DOG
clr decimi
clr unita
ldi punto,11110111b ; 0,0
ldi decine,15
;*** Setta la porta A
ldi pdir_a,11111111b ;disponibili solo pa0,1,2,3
ldi popt_a,11111111b ; tutti ouput
ldi port_a,11111111b
;*** Setta la porta B
ldi pdir_b,00011111b ;pa0,1,2,3,4 output
ldi popt_b,00011111b ;pa5 in poi ADC
ldi port_b,00100111b ; rimanenti non utilizzati conf. input
ldi adcr,0 ;DISABLE A/D INTERRUPT
ldi tscr,0 ;DISABLE TIMER INTERRUPT
ldi ior,0 ;DISABLE ALL INTERRUPT
reti ;RIPRISTINA I FLAG PRINCIPALI
jp main ;SALTA AL PROGRAMMA PRINCIPALE
;*********************************************
;* SUBRINE DI INTERRUPT *
;*********************************************
ad_int ;INTERRUPT DEL CONVERTITORE A/D
reti
tim_int ;INTERRUPT DEL TIMER
reti
BC_int ;INTERRUPT DELLE PORTE A e B
reti
A_int ;INTERRUPT DELLA PORTA A
reti
nmi_int ;INTERRUPT NON MASCHERABILE
reti
;*********************
;*** SUBROUTINE ***
;*********************
display
ld a,decimi ;cifra di destra DECIMALI
ld port_a,a ;mette sulla porta i DECIMI
res 0,port_b ;abilita trans. decimali
call delay
set 0,port_b ;disabilita tr decimali
ld a,unita ;prende UNITA`
ld port_a,a ;mette sulla porta UNITA
res 1,port_b ;abilita transiStore UNITA
call delay
set 1,port_b
ld a,decine ;DECINE
ld port_a,a ;mette sulla porta le DECINE
res 2,port_b ;abilita tr decine
call delay
set 2,port_b
rito ret ;ritorna
delay ldi y,100 ;circa 2 mS di ritardo
decy dec y
ldi wdog,255
jrnz decy
ret
;-----------------------------------------------------------------------------------------
;DIVISIONE 2 byte divisore in n1 e n2 dividendo in n3
;Divide un numero compreso tra 1 e 65025 espresso
; in due byte N1 (=msb) e N2 (=lsb)
;con un divisore a 1 byte (1-255)
;restituisce 2 byte RISMSB-RISLSB
;-----------------------------------------------------------------------------------------
divid ldi wdog,254 ;carico wdog
clr rismsb ;azz. byte risultato MSB
clr rislsb ;azzeramento risultato LSB
ld a,n3 ;divisore
jrnz ldn1
fine ret
ldn1 ld a,n1 ;carico nel reg a il byte + significativo
jrnz div ;se non e` zero salto
ld a,n2 ;altrimenti prendo byte - significativo
jrz fine
jp ancora ;e vado a dividere
div ld a,n2 ;prendo il byte - signif.
suba ldi wdog,254
sub a,n3 ;sottraggo una volta n2-n3
jrc decn1
inc rislsb ;suppongo già che n3 ci stia una volta in n2
jrnz suba
inc rismsb
jpsu jp suba ;se a>= n2 continuo a sottrarre e inc risultato
decn1 inc rislsb
jrnz decn
inc rismsb
decn dec n1 ;chiedo riporto al byte + significativo
jrz ancora ;e se n1 non e` zero continuo a sottrarre
jp suba
ancora ldi wdog,254
sub a,n3 ;sottraggo ancora
jrc ok
jrz okk_
inc rislsb ;incremento ancora il risultato
jp ancora ;e continuo fino a che n2>n3
okk_ inc rislsb
jp ldre
ok add a,n3
ldre ld resto,a ;cosi da avere in a il resto
ret
;____________________________
;LEGGE ADC e VISUALIZZA
;____________________________
attendi clr resto
clr risul
ldi aa,255
averr1 ldi wdog,255
ldi pdir_b,00011111b
ldi popt_b,00111111b ;configura pora B come ADC
ldi a,00111111b
and a,punto ;gestione punto display
ld port_b,a
ldi adcr,00110000b ;abilita A/D
att jrr 6,adcr,att ;attende conversione
nop
ld a,addr ;mette in a il valore convertito
add a,resto ;somma il precedente valore con il nuovo
jrnc averr2 ;se non c’è riporto salta
inc risul ;altrimenti incrementa
averr2 ld resto,a
ld a,aa ;verifica se ha eseguito 255 conversioni
jrnz decaa
jp averr4 ;se si salta
decaa dec aa ;altrimenti un conversione in meno
ldi popt_b,00011111b
call display
jp averr1 ;continua a convertire
averr4 ld a,resto ;arrotonda
cpi a,127 ;se a <127 salta
jrc averr3 ;altrimenti arrotonda incrementando risul
inc risul ;valore mediato 255 volte va in a
averr3 ld a,risul
ret
;FA IL QUADRATO
quadrat ldi wdog,255
clr v ;azzera reg v
ld w,a ;per contare quante volte sommare
dec w
ld x,a ;valore in x da usare per sommare ad a
somma add a,x ; somma a+x
jrnc decw
inc v ;MSB
ldi wdog,255
decw dec w ;conta le volte
jrnz somma ;se non ha finito salta
ld n2,a ;n2= LSB
ld a,v ;mette MSB in a
ld n1,a ;n1=MSB
ret
;DIVIDE PER 4
div4 ldi n3,4 ;altrimenti divide per 4
call divid
set 3,punto ;punto decimale 0,0X
res 4,punto
clr decine
clr unita
ld a,rislsb
ld decimi,a
ret
;******************************************
;PROGRAMMA PRINCIPALE
;******************************************
main ldi wdog,255
call attendi ;legge tensione
cpi a,2
jrnc calqua ;se minore di 1 potenza troppo bassa e ricomincia
clr decimi
clr unita
ldi decine,15 ;decine spente
ldi punto,11110111b ; 0,0
jp main
calqua call quadrat ;fa il quadrato di ADC
cpi a,0 ;a contiene MSB e se MSB>0
jrnz div40 ;salta e divide per 40
ld a,n2 ;altrimenti verifica LSB
cpi a,40
jrnc div40 ;se >= 40 va a dividere per 40
call div4
jp main
div40 ldi n3,40 ;n1 e n2 sono già messi quando fa quadrato
call divid
ld decimi,a ;a=resto resto in decimi
ld a,rismsb ;verifica se non è 0
jrz cpia10 ;se non è 0 allora
ld n1,a ;riprende rismsb e lo mete in n1 per dividerlo
ld a,rislsb
jp ldn2
cpia10 ld a,rislsb
cpi a,10
jrnc div10
set 3,punto ;punto decimale 0,XX
res 4,punto
clr decine
ld unita,a ;risul in unita
call aggiust
jp main
div10 clr n1 ;prepara x divisione
ldn2 ld n2,a ;rislsb in n2
ldi n3,10 ;divisore
call divid ;1a divisone x 10
;ld decimi,a ;ricorda resto
ld a,rislsb ;rismsb è sicuramente 0 riprende
cpi a,10 ;pertanto verifica solo risLSB
jrnc div10_ ;se >= 10 salta e divide ancora
set 3,punto ;altrimenti punto decimale X,XX
res 4,punto
jp main_
div10_ clr n1 ;prepara x divisione
ld n2,a ;e rislsb in n2
ldi n3,10 ;divisore
call divid ;2a divisone x 10
ld a,rislsb
cpi a,10
jrnc ldare ;se >= salta
res 3,punto
set 4,punto ;punto decimale XX,X
jp main_
ldare ld a,resto ; a= resto ultia divisione
ld decimi,a
clr n1 ;prepara per divisone
ld a,rislsb
ld n2,a
ldi n3,10
call divid ;3a divisione
res 3,punto ;senza virgola
res 4,punto
ld a,resto
ld unita,a ;secondo resto
ld a,rislsb
ld decine,a
jp main
main_ ;DUd (D)ecine (U)nita (d)ecimi
ld a,resto ;XXX
ld unita,a ;secondo resto
ld a,rislsb
ld decine,a
call aggiust
jp main
aggiust ld a,decimi
cpi a,4
jrc ret_
clr n1 ;prepara x divisione
ld n2,a ;rislsb in n2
ldi n3,4 ;divisore
call divid
ld a,rislsb
ld decimi,a
ret_ ret
;-------------------------
;VETTORI DI INTERRUPTS
;-------------------------
.org 0ff0h
jp ad_int ;A/D int vector #4
jp tim_int ;timer int vector #3
jp BC_int ;port B & C int vector #2
jp A_int ;port A int vector #1
.org 0ffch
jp nmi_int ;nmi int vector #0
jp inizio ;reset vector
.end