Wattmetro BF

© by Vittorio Crapella - i2viu

WATTMETRO 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