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 finestrea .def 0ffh ;Registro accumulatorex .def 080h ;Registro x y .def 081h ;Registro yv .def 082h ;Registro vw .def 083h ;Registro wport_a .def 0c0h ;Registro Dati porta A port_b .def 0c1h ;Registro Dati porta Bport_c .def 0c2h ;Registro Dati porta Cpdir_a .def 0c4h ;Registro Direzione porta Apdir_b .def 0c5h ;Registro Direzione porta Bpdir_c .def 0c6h ;Registro Direzione porta Cpopt_a .def 0cch ;Registro Opzioni porta Apopt_b .def 0cdh ;Registro Opzioni porta Bpopt_c .def 0ceh ;Registro Opzioni porta Cior .def 0c8h ;Registro Opzioni per le Interruzioniaddr .def 0d0h ;Registro Dati dell'A/D converteradcr .def 0d1h ;Registro di Controllo dell'A/D converterpsc .def 0d2h ;Registro per il Prescaler del Timertcr .def 0d3h ;Registro Dati del Timertscr .def 0d4h ;Registro TSCR del Timer wdog .def 0d8h ;Registro del WatchDogdrw .def 0c9h ;Registro della zona dati ROM (Rom Data Window);--------------------------------------; VARIABILI usate da questo programma ;--------------------------------------decimi .def 084h ;displayunita .def 085h ; "decine .def 086h ; "resto .def 087h ;divisionerisul .def 088haa .def 089h ;per contare le conversionin1 .def 08ah ;byte più significativo MSB n2 .def 08bh ;byte meno significativo LSB n3 .def 08ch ;divisorerislsb .def 08dh ;risultato LSBrismsb .def 08eh ;risultato MSBpunto .def 08fh ;virgola display;***************************;*** Settaggio iniziale ***;*************************** .org 080h ;080h per 20/25 mentre 880h per 10/15inizio ; 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 retitim_int ;INTERRUPT DEL TIMER retiBC_int ;INTERRUPT DELLE PORTE A e B retiA_int ;INTERRUPT DELLA PORTA A retinmi_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_brito ret ;ritornadelay ldi y,100 ;circa 2 mS di ritardodecy 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 ldn1fine retldn1 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 rismsbjpsu jp suba ;se a>= n2 continuo a sottrarre e inc risultatodecn1 inc rislsb jrnz decn inc rismsbdecn dec n1 ;chiedo riporto al byte + significativo jrz ancora ;e se n1 non e` zero continuo a sottrarre jp subaancora 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>n3okk_ inc rislsb jp ldreok add a,n3ldre ld resto,a ;cosi da avere in a il resto ret ;____________________________ ;LEGGE ADC e VISUALIZZA;____________________________attendi clr resto clr risul ldi aa,255averr1 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 incrementaaverr2 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 convertireaverr4 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 QUADRATOquadrat 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 asomma add a,x ; somma a+x jrnc decw inc v ;MSB ldi wdog,255decw 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 4div4 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 maincalqua 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 maindiv40 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 ldn2cpia10 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 maindiv10 clr n1 ;prepara x divisioneldn2 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 mainmain_ ;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 mainaggiust 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,aret_ 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