×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
• Talk With Other Members
• Be Notified Of Responses
• Keyword Search
Favorite Forums
• Automated Signatures
• Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

#### Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

# a.c. 50Hz voltage measurement trouble

## a.c. 50Hz voltage measurement trouble

(OP)
I have written code in assembly language which can read a voltage and current and display it on my LCD with scaling factors for the application I need. Its fine but I cant figure out how to store numbers and use interrupts in asm. The inputs are from voltage and current transducer circuits including summer amps etc, that I have made so the input range is unipolar 0-5 volts to suit the PIC18F452 microcontroller I am using. The ac inputs need to be sampled 20 times per 50Hz cycle, that being 1000 samples
a second. The samples need to be squared, summed, the mean found and finally the square root is found to get the rms values. I am having great difficulty in doing this.So I need to make the timer read the samples 20 times per second, then store the samples. Thats the basic bit I need, and am stuck with.
Any ideas would be good. the ra0 ACD input on the PIC is fine for the voltage, which is the single part I am working on now. So in summary, I need to store the input at ra0,  and at the end of the 20 stored values, just divide the total of the 20 samples by 20. Its really
simplified down but this is as far as I have managed to get on my own.

This is the working code so far, which shows the instantaneous voltage and current in real time.
-------------------------------------------------------

list p=18f452
#include p18f452.inc

;Program Configuration Registers
__CONFIG    _CONFIG1H, _OSCS_OFF_1H & _EC_OSC_1H
__CONFIG    _CONFIG2L, _BOR_OFF_2L & _PWRT_ON_2L
__CONFIG    _CONFIG2H, _WDT_OFF_2H
__CONFIG    _CONFIG3H, _CCP2MX_OFF_3H
__CONFIG    _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L
__CONFIG    _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L
__CONFIG    _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
__CONFIG    _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L
__CONFIG    _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
__CONFIG    _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L
__CONFIG    _CONFIG7H, _EBTRB_OFF_7H

#define    scroll_dir    TRISA,4
#define    scroll        PORTA,4        ;Push-button RA4 on PCB
#define    select_dir    TRISB,0
#define    select        PORTB,0        ;Push-button RB0 on PCB

EXTERN    LCDInit, temp_wr, d_write, i_write, LCDLine_1, LCDLine_2
EXTERN    UMUL0808L, FXD1608U, AARGB0, AARGB1, BARGB0

ssprw    macro                ;check for idle SSP module routine
movlw    0x00
andwf    SSPCON2,W
sublw    0x00
btfss    STATUS,Z
bra    $-8 btfsc SSPSTAT,R_W bra$-2
endm

variables    UDATA
ptr_pos        RES 1
ptr_count    RES 1
temp_1        RES 1
temp_2        RES 1
temp_3        RES 1
cmd_byte    RES 1
LSD        RES 1
MsD        RES 1
MSD        RES 1

NumH        RES 1
NumL        RES 1
TenK        RES 1
Thou        RES 1
Hund        RES 1
Tens        RES 1
Ones        RES 1

STARTUP CODE
NOP
goto    start
NOP
NOP
NOP
PROG1     CODE

stan_table                ;table for standard code
;    "XXXXXXXXXXXXXXXX"
;                ptr:
data    " Voltage Output "    ;0
data    " S3 for reading "    ;160
data    "  GENSET OUTPUT "      ;32
data    "Waiting........."    ;48
data    "    S3=Select   "    ;64
data    "RA4= --> RBO= ++"    ;80
data    " RESET to EXIT     "    ;96
data    "Volts =         "    ;112
data    "    Current     "    ;128
data    "Current =       "      ;144

start
call LCDInit

movlw    B'10100100'        ;initialize USART
movwf    TXSTA            ;8-bit, Async, High Speed
movlw    .25
movwf    SPBRG            ;9.6kbaud @ 4MHz
movlw    B'10010000'
movwf    RCSTA

bcf    TRISC,2            ;configure CCP1 period
movlw    0x80            ;initialize PWM duty cycle
movwf    CCPR1L
bcf    CCP1CON,CCP1X
bcf    CCP1CON,CCP1Y

movlw    0x05            ;postscale 1:1, prescaler 4, Timer2 ON
movwf    T2CON

bsf    TRISA,4            ;make switch RA4 an Input
bsf    TRISB,0            ;make switch RB0 an Input

;**************** STANDARD CODE MENU SELECTION *******************
;Introduction
movlw    .32            ;send "Microchip" to LCD
movwf    ptr_pos
call    stan_char_1

movlw    .48            ;send "PICDEM 2 PLUS" to LCD
movwf    ptr_pos
call    stan_char_2
call    delay_1s        ;delay for display
call    delay_1s        ;delay for display

;------------------ VOLT MEASUREMENT  ----------------------------
btfss    scroll            ;wait for RA4 release
goto    $-2 btfss select ;wait for RB0 release goto$-2

movlw    0x00            ;voltmeter
movwf    ptr_pos
call    stan_char_1

movlw    .48                ;RA4=Next  RB0=Now
movwf    ptr_pos
call    stan_char_2
v_wait
btfss    select            ;voltmeter measurement ??
bra        voltmeter
btfsc    scroll            ;next mode ??
bra        v_wait            ;NO
btfss    scroll            ;YES
bra        $-2 ;wait for RA4 release ;------------------ CURRENT MEASUREMENT ---------------------------- menu_current btfss scroll ;wait for RA4 release goto$-2
btfss    select            ;wait for RB0 release
goto    $-2 movlw .128 ;voltmeter movwf ptr_pos call stan_char_1 movlw .48 ;RA4=Next RB0=Now movwf ptr_pos call stan_char_2 c_wait btfss select ;voltmeter measurement ?? bra current btfsc scroll ;next mode ?? bra c_wait ;NO btfss scroll ;YES bra$-2                ;wait for RA4 release

;-------------------------------------------------------------------
return

;*******************************************************************

;************* STANDARD USER CODE **********************************

;------------- Voltmeter----------------------------

voltmeter
btfss    select            ;wait for RB0 release
bra        $-2 movlw B'01000001' ;configure A/D converter movwf ADCON0 ;turn A/D on movlw b'10001110' ;RA0 = analog input movwf ADCON1 movlw .112 ;send "Volts = " to the LCD movwf ptr_pos call stan_char_1 volts_again bsf ADCON0,GO ;start conversion again btfsc ADCON0,GO goto again movf ADRESH,W ;ADRESH --> WREG movwf AARGB0 ;move ADRESH into AARGB0 movlw 0x64 ;19.5mV/step 0xC3 = 195 movwf BARGB0 call UMUL0808L movlw 0x64 ;divide result by 200 (0x128) movwf BARGB0 call FXD1608U movf AARGB0,W ;prepare for 16-bit binary to BCD movwf NumH movf AARGB1,W movwf NumL call bin16_bcd ;get volts ready for LCD call LCDLine_2 ;display A/D result on 2nd line movf Hund,W ;get hunds call bin_bcd movf LSD,W ;send high digit from LSD movwf temp_wr movwf temp_wr call d_write movf Tens,W ;get tens call bin_bcd movf LSD,W ;send low digit x.#x movwf temp_wr call d_write movf Ones,W ;get ones call bin_bcd movf LSD,W ;send low digit x.x# movwf temp_wr call d_write movlw A'V' ;send "V" unit movwf temp_wr call d_write movlw 0x20 ;3 spaces movwf temp_wr call d_write movlw 0x20 movwf temp_wr call d_write movlw 0x20 movwf temp_wr call d_write movlw A'R' ;send "RB0=Exit" to LCD movwf temp_wr call d_write movlw A'E' movwf temp_wr call d_write movlw A'S' movwf temp_wr call d_write movlw A'=' movwf temp_wr call d_write movlw A'E' movwf temp_wr call d_write movlw A'x' movwf temp_wr call d_write movlw A'i' movwf temp_wr call d_write movlw A't' movwf temp_wr call d_write movlw 0x20 ;2 spaces movwf temp_wr call d_write movlw 0x20 movwf temp_wr call d_write movlw "\r" ;move data into TXREG movwf TXREG ;carriage return btfss TXSTA,TRMT ;wait for data TX bra$-2
btfss    select        ;exit volt measurement ??
bra    volts_again    ;NO, do conversion again

;------------- Currentmeter--------------------------------------------
current
btfss    select        ;wait for RB0 release
bra        $-2 movlw B'01000001' ;configure A/D converter movwf ADCON0 ;turn A/D on movlw b'00001110' ;RA0 = analog input movwf ADCON1 movlw .144 ;send "Volts = " to the LCD movwf ptr_pos call stan_char_1 current_again bsf ADCON0,GO ;start conversion again1 btfsc ADCON0,GO goto again1 movf ADRESH,W ;ADRESH --> WREG movwf AARGB0 ;move ADRESH into AARGB0 movlw 0xC3 ;19.5mV/step 0xC3 = 195 movwf BARGB0 call UMUL0808L movlw 0xAA ;divide result by 100 (0x64) movwf BARGB0 call FXD1608U movf AARGB0,W ;prepare for 16-bit binary to BCD movwf NumH movf AARGB1,W movwf NumL call bin16_bcd ;get volts ready for LCD call LCDLine_2 ;display A/D result on 2nd line movf Hund,W ;get hunds call bin_bcd movf LSD,W ;send high digit from the LSD #.xx movwf temp_wr call d_write movf Tens,W ;get tens call bin_bcd movf LSD,W ;send low digit x.#x movwf temp_wr call d_write movlw A'.' ;send decimal point "." movwf temp_wr call d_write movf Ones,W ;get ones call bin_bcd movf LSD,W ;send low digit x.x# movwf temp_wr call d_write movlw A'A' ;send "A" unit movwf temp_wr call d_write movlw 0x20 ;3 spaces movwf temp_wr call d_write movlw 0x20 movwf temp_wr call d_write movlw 0x20 movwf temp_wr call d_write movlw A'R' ;send "RB0=Exit" to LCD movwf temp_wr call d_write movlw A'E' movwf temp_wr call d_write movlw A'S' movwf temp_wr call d_write movlw A'=' movwf temp_wr call d_write movlw A'E' movwf temp_wr call d_write movlw A'x' movwf temp_wr call d_write movlw A'i' movwf temp_wr call d_write movlw A't' movwf temp_wr call d_write movlw 0x20 ;2 spaces movwf temp_wr call d_write movlw 0x20 movwf temp_wr call d_write movlw "\r" ;move data into TXREG movwf TXREG ;carriage return btfss TXSTA,TRMT ;wait for data TX bra$-2

bra    current_again    ;NO, do conversion again

;------------------------
inc_dc
btfss    scroll        ;wait for button release
bra    $-2 inc_ccpr1l btfsc select ;increment CCPR1L ??? goto ccpr1l_out ;NO call delay_100ms ;YES call delay_100ms incf CCPR1L,F ;increment CCPR1L ccpr1l_out movlw 0x8C ;move cursor into position movwf temp_wr call i_write col1 btfss scroll ;exit? bra pwm_out btfsc select ;wait for RB0 press bra col1 movf CCPR1L,W ;send PR2 register to conversion call bin_bcd movf MSD,W ;send high digit movwf temp_wr call d_write movf MsD,W ;send middle digit movwf temp_wr call d_write movf LSD,W ;send low digit movwf temp_wr call d_write bra inc_ccpr1l pwm_out movlw 0 movwf CCP1CON ;turn buzzer off ;******************************************************************* ;************************** ROUTINES ****************************** ;----Standard code, Place characters on line-1-------------- stan_char_1 call LCDLine_1 ;move cursor to line 1 movlw .16 ;1-full line of LCD movwf ptr_count movlw UPPER stan_table movwf TBLPTRU movlw HIGH stan_table movwf TBLPTRH movlw LOW stan_table movwf TBLPTRL movf ptr_pos,W addwf TBLPTRL,F clrf WREG addwfc TBLPTRH,F addwfc TBLPTRU,F stan_next_char_1 tblrd *+ movff TABLAT,temp_wr call d_write ;send character to LCD decfsz ptr_count,F ;move pointer to next char bra stan_next_char_1 movlw "\n" ;move data into TXREG movwf TXREG ;next line btfss TXSTA,TRMT ;wait for data TX goto$-2
movlw    "\r"        ;move data into TXREG
movwf    TXREG        ;carriage return
btfss    TXSTA,TRMT    ;wait for data TX
goto    $-2 return ;----Standard code, Place characters on line-2-------------------------- stan_char_2 call LCDLine_2 ;move cursor to line 2 movlw .16 ;1-full line of LCD movwf ptr_count movlw UPPER stan_table movwf TBLPTRU movlw HIGH stan_table movwf TBLPTRH movlw LOW stan_table movwf TBLPTRL movf ptr_pos,W addwf TBLPTRL,F clrf WREG addwfc TBLPTRH,F addwfc TBLPTRU,F stan_next_char_2 tblrd *+ movff TABLAT,temp_wr call d_write ;send character to LCD decfsz ptr_count,F ;move pointer to next char bra stan_next_char_2 movlw "\n" ;move data into TXREG movwf TXREG ;next line btfss TXSTA,TRMT ;wait for data TX goto$-2
movlw    "\r"        ;move data into TXREG
movwf    TXREG        ;carriage return
btfss    TXSTA,TRMT    ;wait for data TX
goto    $-2 return ;---------------------------------------------------------------------- ;------------------ 100ms Delay -------------------------------- delay_100ms movlw 0xFF movwf temp_1 movlw 0x83 movwf temp_2 d100l1 decfsz temp_1,F bra d100l1 decfsz temp_2,F bra d100l1 return ;---------------- 1s Delay ----------------------------------- delay_1s movlw 0xFF movwf temp_1 movwf temp_2 movlw 0x05 movwf temp_3 d1l1 decfsz temp_1,F bra d1l1 decfsz temp_2,F bra d1l1 decfsz temp_3,F bra d1l1 return ;---------------- Binary (8-bit) to BCD ----------------------- ; 255 = highest possible result bin_bcd clrf MSD clrf MsD movwf LSD ;move value to LSD ghundreth movlw .100 ;subtract 100 from LSD subwf LSD,W btfss STATUS,C ;is value greater then 100 bra gtenth ;NO goto tenths movwf LSD ;YES, move subtraction result into LSD incf MSD,F ;increment hundreths bra ghundreth gtenth movlw .10 ;take care of tenths subwf LSD,W btfss STATUS,C bra over ;finished conversion movwf LSD incf MsD,F ;increment tenths position bra gtenth over ;0 - 9, high nibble = 3 for LCD movf MSD,W ;get BCD values ready for LCD display xorlw 0x30 ;convert to LCD digit movwf MSD movf MsD,W xorlw 0x30 ;convert to LCD digit movwf MsD movf LSD,W xorlw 0x30 ;convert to LCD digit movwf LSD retlw 0 ;---------------- Binary (16-bit) to BCD ----------------------- ; xxx = highest possible result bin16_bcd ; Takes number in NumH:NumL ; Returns decimal in ; TenK:Thou:Hund:Tens:Ones swapf NumH,W andlw 0x0F addlw 0xF0 movwf Thou addwf Thou,F addlw 0xE2 movwf Hund addlw 0x32 movwf Ones movf NumH,W andlw 0x0F addwf Hund,F addwf Hund,F addwf Ones,F addlw 0xE9 movwf Tens addwf Tens,F addwf Tens,F swapf NumL,W andlw 0x0F addwf Tens,F addwf Ones,F rlcf Tens,F rlcf Ones,F comf Ones,F rlcf Ones,F movf NumL,W andlw 0x0F addwf Ones,F rlcf Thou,F movlw 0x07 movwf TenK movlw 0x0A ; Ten Lb1: decf Tens,F addwf Ones,F btfss STATUS,C bra Lb1 Lb2: decf Hund,F addwf Tens,F btfss STATUS,C bra Lb2 Lb3: decf Thou,F addwf Hund,F btfss STATUS,C bra Lb3 Lb4: decf TenK,F addwf Thou,F btfss STATUS,C bra Lb4 retlw 0 ;---------------------------- EEPROM WRITE ------------------------------- write_eeprom bsf SSPCON2,SEN ;start bit btfsc SSPCON2,SEN goto$-2
movlw    B'10100000'    ;send control byte (write)
movwf    SSPBUF
ssprw
btfsc    SSPCON2,ACKSTAT
goto    $-2 movlw 0x00 ;send slave address HIGH byte movwf SSPBUF ssprw btfsc SSPCON2,ACKSTAT goto$-2

movlw    0x05    ;send slave address LOW byte(0x0005)
movwf    SSPBUF
ssprw
btfsc    SSPCON2,ACKSTAT
goto    $-2 movf temperature,w ;send slave DATA = temperature movwf SSPBUF ssprw btfsc SSPCON2,ACKSTAT goto$-2

bsf    SSPCON2,PEN        ;stop bit
btfsc    SSPCON2,PEN
goto    \$-2

bcf    PIR1,TMR1IF    ;clear TIMER1 overflow flag
clrf    TMR1L    ;clear registers for next overflow
clrf    TMR1H

return

;*********************************************************************
end

### RE: a.c. 50Hz voltage measurement trouble

Hello there.
First, i think that you should have asked for help in the microchip forums. The reason is that not many people write code in assembly, and furthermore even less write code that will operate a PIC micro.

So, consider the above and the next: (i am in microchip forums too)
> The 18F family has the mcc18 compiler which is C [free]. You can move your existing code as "inline assembly". With that move, you keep your working code, and you have some easy things... like easy to find the square root.

- Timer and 20samples: You can use a timer, say tmr2, write the correct pre and post/scales, maybe use autoreload. Enable the TMR2IF interrupt, so when it overflows, you will be redirected to the low or high interrupt vector. There you set the GO bit of the A/D module , ...etc
Then you store the result in e.g. the PIC's RAM. See the free space in the datasheet. You can save it in an eeprom if you want, but the RAM would be great. This would be if you used assembly for that part. Now in C, you can define a table (array)... When you write a number of values, you sum them (for loop, because you know how many samples you got), find the square root.

Hope this little info helps

#### Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

#### Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Close Box

# Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

• Talk To Other Members
• Notification Of Responses To Questions
• Favorite Forums One Click Access
• Keyword Search Of All Posts, And More...

Register now while it's still free!