1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Measuring Vdd in Pic

Discussion in 'Microcontrollers' started by Pommie, Aug 16, 2017.

  1. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    I am using the Fixed Voltage Reference (FVR) of a 16F18325 to measure Vdd using the ADC using the following code.
    Code (text):

    uint16 Measure_Vdd(){
        uint32 result;
        FVRCON=0b10000101;      //FVR set to 1.024V
        ADCON0=0b11111101;      //adc on and select FVR
        ADCON1=0b10010000;      //Right Justify, Tosc/8, Vss - Vdd as reference
        __delay_us(50);         //delay for settling time of FVR and ADC acquisition time
        GO=1;                   //Start ADC
        while(GO);              //Wait for conversion to complete
        ADCON0=0;               //Turn ADC off
        FVRCON=0b00000101;      //Turn FVR off
        result = 1048576L/ADRES;
        return((uint16)result);
    }
     
    For anyone interested how this works,
    I set the FVR to 1.024V and feed it to the ADC module. The ADC is set to use Vdd and Vss as the reference.
    The result should be ADCresult = (1.024/Vdd)*1024. Switching this around gives Vdd = ADCresult/(1.024*1024).
    As I want this as millivolts I end up with the equation Vdd=1048576/ADCresult.

    Now, all was working as expected and I was storing Vdd every 15 minutes (running on single Lipo battery).
    Then, yesterday I starting getting readings around 1038 mV without any change to the code.
    I am monitoring the results in Tera term via a USB to RS232 converter and it seems this is the culprit.
    With the converter connected I get stupidly low readings, disconnect it and I get the correct readings.

    Anyone got any theory why this is so?
    I only have Gnd, RX & TX connected but it is still capable of powering the circuit on it's own!
    I'm wondering if using current limiting resistors (22k) on RX and TX might fix this.

    However, I'm still at a loss as to how this is possible. I can't see and change in Vdd using a multimeter and no noise with a scope. It's just completely baffling.

    Edit, The resistors (22k) stopped the serial working completely. The USB - RS232 module is a Prolific PL2303.

    Thanks for reading and for any suggestions.

    Mike.
     
    Last edited: Aug 16, 2017
  2. be80be

    be80be Well-Known Member

    Joined:
    Aug 23, 2008
    Messages:
    4,807
    Likes:
    135
    Location:
    morristown,tn
    I've had this same problem not doing what your doing but the pic powering my usb to serial adapter or the Usb to serial powering the pic and I was only using 2 pin TX to RX and the ground.

    It was giving me a time programming with the pickit 3 I would get a powered target but it wouldn't program only if I really powered it but the pic would run from the rx and the ground.
    I was trying to read the data I was missing so I powered the serial first but as soon as I did the pic word try to run and did. I powered the pic then the serial Id miss the start. It didn't power with a homemade ch340 I made. But I have a old cp2102 it causes all kinds of self powering.
     
    Last edited: Aug 16, 2017
  3. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    What is the LiPo battery voltage, Mike? What are the voltages on the USB-to-Serial Adapter Rx & Tx pins?
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,165
    Likes:
    910
    Location:
    Rochdale UK
    ONLINE

    Just looked at the datasheet!!!!!!!!!!!!!!!!!! WTF! There's only 14 pins and 31..YES 31 banks of SFR's.

    Sorry Mike! You are on your own!
     
  6. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    That's 32 banks, Ian...
     
    Last edited: Aug 17, 2017
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,165
    Likes:
    910
    Location:
    Rochdale UK
    ONLINE
    The problem here is the amount of peripheral to output / input pins... I use the pic16f1825 regularly and its nowhere near as complex as this little chip! You are correct.. It also has 32 banks for SFR's but many are sparce and half are duplicated!! In theory there are only 8 pages of SFR's.. I think the little pic16f18235 is a bit too tightly packed..
     
  8. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    I admit that the setup for these "feature rich" 15000 & 18000 devices can be a pain but the outcome is worth the extra effort. Take a peek at the source for a little 8-pin ClockGen chip for a retro 65C02 computer for instance (below). Using PPS (Peripheral Pin Select) to map peripheral inputs and/or outputs to individual pins gets easier with practice.

    Cheerful regards, Mike

    Code (text):

    ;******************************************************************
    ;                                                                 *
    ;    Project: ClockGen v1.0                                       *
    ;       File: 16F18313_Clock.asm                                  *
    ;     Author: Mike McLaren, K8LH                                  *
    ;    (C)2016: Micro Application Consultants                       *
    ;           : All Rights Reserved                                 *
    ;       Date: 04-Apr-2016                                         *
    ;                                                                 *
    ;    16F18313 Clock-Gen + Econo-Reset for 65C02 (8-MHz crystal)   *
    ;    produces a 1, 2, 4, or 8 MHz CPU clock and an ACIA clock.    *
    ;                                                                 *
    ;        IDE: MPLABX v3.05                                        *
    ;       Lang: MPASM v5.62 (absolute addressing mode)              *
    ;                                                                 *
    ;******************************************************************

            #include <p16F18313.INC>
            errorlevel -302,-311    ; suppress bank warnings
            list st=off             ; symbol table off
            radix dec

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  config settings                                                ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

     __CONFIG _CONFIG1, _FEXTOSC_HS & _FCMEN_OFF
     ;
     ; CLKOUTEN_OFF default
     ; CSWEN_ON     default
     ;
     __CONFIG _CONFIG2, _WDTE_OFF & _PPS1WAY_OFF
     ;
     ; MCLRE_ON     default
     ; PWRTE_OFF    default
     ; LPBOREN_OFF  default
     ; BOREN_ON     default
     ; BOREN_LOW    default
     ; STVREN_ON    default
     ; DEBUG_OFF    default
     ;
     __CONFIG _CONFIG3, _LVP_OFF
     ;
     ; WRT_OFF      default
     ;
     __CONFIG _CONFIG4, _CP_OFF & _CPD_OFF

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  variables                                                      ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            cblock  0x70            ; common RAM available any bank
    delayhi                         ; DelayCy() subsystem variable
            endc

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  constants                                                      ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;
    ;  assign clock and reset pins (RA0..RA2 inclusive).
    ;
    PHI0_clk equ    RA0             ; bit index for RA0 (0)
    ACIA_clk equ    RA1             ; bit index for RA1 (1)
    RESB_out equ    RA2             ; bit index for RA2 (2)
    ;
    ;  associate to "Peripheral Pin Select" output registers.
    ;
    PHI0_PPS equ    RA0PPS+PHI0_clk ; equ RA0PPS
    ACIA_PPS equ    RA0PPS+ACIA_clk ; equ RA1PPS
    RESB_PPS equ    RA0PPS+RESB_out ; equ RA2PPS
    ;
    ;  set 'CLKR_div' constant for desired 65C02 clock frequency.
    ;
    ;               6 ->  0.5-MHz (Fosc / 64)
    ;               5 ->  1.0-MHz (Fosc / 32)
    ;               4 ->  2.0-MHz (Fosc / 16)
    ;               3 ->  4.0-MHz (Fosc / 8)
    ;               2 ->  8.0-MHz (Fosc / 4)
    ;
    CLKR_div equ    4               ; 2.0-MHz PHI0 CPU clock
    ;
    ;  set 'NCO1_inc' constant for desired ACIA clock output.
    ;
    ;          2517 ->    38400-Hz (  2400 * 16) @ 0.01659%
    ;          5033 ->    76800-Hz (  4800 * 16) @ 0.00327%
    ;         10066 ->   153600-Hz (  9600 * 16) @ 0.00327%
    ;         20133 ->   307200-Hz ( 19200 * 16) @ 0.00169%
    ;         40265 ->   614400-Hz ( 38400 * 16) @ 0.00079%
    ;         60398 ->   921600-Hz ( 57600 * 16) @ 0.00004%
    ;        120796 ->  1843200-Hz (115200 * 16) @ 0.00004%
    ;        241592 ->  3686400-Hz (230400 * 16) @ 0.00004%
    ;
    NCO1_inc equ    120796          ; 1.8432-MHz (115200 * 16)

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  K8LH DelayCy() subsystem macro generates four instructions     ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            radix dec
    clock   equ     32              ; 4, 8, 12, 16, 20 (MHz), etc.
    usecs   equ     clock/4         ; cycles/microsecond multiplier
    msecs   equ     usecs*1000      ; cycles/millisecond multiplier
    dloop   equ     5               ; loop size, 5 to ??? cycles
    ;
    ;  -- loop --  -- delay range --  -- memory overhead ----------
    ;  5-cyc loop, 11..327690 cycles,  9 words (+4 each macro call)
    ;  6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
    ;  7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
    ;  8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
    ;  9-cyc loop, 11..589834 cycles, 13 words (+4 each macro call)
    ;
    DelayCy macro   cycles          ; range, see above
        if (cycles<11)|(cycles>(dloop*65536+10))
            error " DelayCy range error "
        else
            movlw   high((cycles-11)/dloop)+1
            movwf   delayhi
            movlw   low ((cycles-11)/dloop)
            call    uLoop-((cycles-11)%dloop)
        endif
            endm

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  reset vector                                                   ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            org     0x0000
    v_reset
            bra     setup           ;                                 |00

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  interrupt vector                                               ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            org     0x0004
    v_int
            retfie                  ;                                 |??

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  main setup                                                     ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    setup
    ;
    ;  turn off analog functions (all I/O will be digital).
    ;
            banksel ANSELA          ; bank 03                         |03
            clrf    ANSELA          ; analog off, digital I/O         |03
    ;
    ;  setup data direction for 'output' pins (default 'input').
    ;
            banksel TRISA           ; bank 01                         |01
            bcf     TRISA,PHI0_clk  ; set phi0 clock pin as output    |01
            bcf     TRISA,ACIA_clk  ; set acia clock pin as output    |01
            bcf     TRISA,RESB_out  ; set resb reset pin as output    |01
    ;
    ;  clear RESB pin output latch (hold the 65C02 in reset).
    ;
            banksel LATA            ; bank 02                         |02
            bcf     LATA,RESB_out   ; RESB_out = '0'                  |02
    ;
    ;  setup Fosc for 32-MHz (external 8-MHz crystal and 4xPLL).
    ;
            banksel OSCCON1         ; bank 18                         |18
            movlw   b'00010000'     ; -001---- NOSC[2:0], Ext 4xPLL   |18
                                    ; ----0000 NDIV[3:0], Clk Div 1   |18
            movwf   OSCCON1         ; 8-MHz Xtal & 4xPLL -> 32-MHz    |18
    stable
            btfss   OSCCON3,ORDY    ; OSC stable? yes, skip, else     |18
            bra     stable          ; loop (wait until OSC stable)    |18
    ;
    ;  assign PHI0_clk pin (RA0) and ACIA_clk pin (RA1) resources
    ;  via 'Peripheral Pin Select'.
    ;
            banksel PPSLOCK         ; bank 28                         |28
            movlw   0x55            ; PPS unlock sequence             |28
            movwf   PPSLOCK         ;  "                              |28
            movlw   0xAA            ;  "                              |28
            movwf   PPSLOCK         ;  "                              |28
            bcf   PPSLOCK,PPSLOCKED ;  "                              |28
            banksel PHI0_PPS        ; bank 29                         |29
            movlw   b'00011110'     ; assign CLKR (Ref Clock) output  |29
            movwf   PHI0_PPS        ; to the PHI0 clock pin (RA0)     |29
            movlw   b'00011101'     ; assign NCO module output to     |29
            movwf   ACIA_PPS        ; the ACIA clock pin (RA1)        |29
            banksel PPSLOCK         ; bank 28                         |28
            bsf   PPSLOCK,PPSLOCKED ; all done, lock it up            |28
    ;
    ;  setup CLKR (Reference Clock) module for PHI0 CPU Clock.
    ;
            banksel CLKRCON         ; bank 07                         |07
            movlw   0x10|CLKR_div   ; 50% duty cycle & divider bits   |07
            movwf   CLKRCON         ; prep 1, 2, 4, or 8-MHz output   |07
            bsf     CLKRCON,CLKREN  ; enable Reference Clock output   |07
    ;
    ;  setup NCO to generate the ACIA clock.
    ;
            banksel NCO1CON         ; bank 08                         |08
    ;       bcf     NCO1CON,N1PFM   ; fixed duty cycle mode (default) |08
            movlw   b'00000001'     ; N1CKS<1:0> = '01' = Fosc        |08
            movwf   NCO1CLK         ; set NCO clock source            |08
            clrf    NCO1ACCL        ; clear 20-bit phase accumulator  |08
            clrf    NCO1ACCH        ;  "                              |08
            clrf    NCO1ACCU        ;  "                              |08
            movlw   low(NCO1_inc)   ; setup 20-bit phase increment    |08
            movwf   NCO1INCL        ;  "                              |08
            movlw   high(NCO1_inc)  ;  "                              |08
            movwf   NCO1INCH        ;  "                              |08
            movlw   upper(NCO1_inc) ;  "                              |08
            movwf   NCO1INCU        ;  "                              |08
            bsf     NCO1CON,N1EN    ; enable NCO module output        |08
    ;
    ;  complete the 65C02 reset cycle.
    ;
            DelayCy(20*msecs)       ; wait ~20-msecs                  |08
            banksel LATA            ; bank 02                         |02
            bsf     LATA,RESB_out   ; release 65C02 from reset        |02

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  main loop                                                      ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    loop
            bra     loop            ; loop forever (until reset)      |02

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;  K8LH DelayCy() subsystem 16-bit 'uLoop' timing subroutine      ~
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    a = dloop-1
        while a > 0
            nop                     ; (cycles-11)%dloop entry points  |??
    a -= 1
        endw
    uLoop   addlw   -1              ; subtract 'dloop' loop time      |??
            skpc                    ; borrow? no, skip, else          |??
            decfsz  delayhi,F       ; done?  yes, skip, else          |??
            bra     uLoop-dloop+5   ; do another loop                 |??
            return                  ;                                 |??

    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            end
     
    • Like Like x 2
  9. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,165
    Likes:
    910
    Location:
    Rochdale UK
    ONLINE
    I have always admired your coding... I moved away from ASM specifically as the new extended mid range became C friendly..
    I still use ASM on the Hitachi H8 and H8s... But it's really nice to see well presented code like yours..
     
    • Like Like x 2
  10. be80be

    be80be Well-Known Member

    Joined:
    Aug 23, 2008
    Messages:
    4,807
    Likes:
    135
    Location:
    morristown,tn
    I just looked at my setup ground to RX is 3.3 volts ground to TX is 5 volts on the five volt setting on the 3.3 there both 3.3 volts to ground
     
  11. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    The battery is a single cell Lipo (link) so 3.75(my cutoff voltage) to 4.2V. I measured the RS232 pins and they are at 4.6V which means that, assuming 0.7V on protection diode, it will drive Vdd towards 3.9V and partially charge the battery. However, this does not explain the low readings. Having left it overnight storing the value every 5 minutes I get the following chart which suggests all is well and it shut off at the desired 3.75V. But I'm still curious about the RS232 causing low readings.

    Edit Arrgg, The readings stop before 3.75V which means I have a bug which crashed it after 20 hours running. That's not going to be easy to find.
    Edit 2, Seems the glitch in the middle of the chart is it going into standby mode(<3.75V). I thought I only stored the voltage when not in standby. Looks like I have a battery life of just 10 hours but no bug.

    Mike.
    Discharge.png
     
    Last edited: Aug 17, 2017
  12. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Is there a chance the higher voltage from the USB adapter is somehow affecting the VDD VREF even though it doesn't appear to affect VDD?

    Have you got a USB adapter with 3.3v output levels you can try?
     
  13. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    Tomorrow, I'll try adding a 2k resistor with 5 diodes to gnd to fix the voltage at 3.5V or just two diodes in series to fix around 3.2V. See if that fixes things. Actually, that'll be Monday as girlfriend will be upset otherwise.

    Mike.
     
    • Funny Funny x 1

Share This Page