×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*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.

Students Click Here

a.c. 50Hz voltage measurement trouble

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
menu

;------------------ 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




;-------------------------------------------------------------------
    bra    menu            ;begining of menu
    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    menu_current    ;YES
    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




;------------------------
        ;adjust Duty Cycle
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.

* Note that i did not read your code.

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.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

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:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close