Menu

using internal FVR and ADC for VDD estimation (18F15Q40)

Help
Nick
2024-08-28
2024-09-21
  • Nick

    Nick - 2024-08-28

    Hi,
    I've done a fair bit of general I/O coding with GCBASIC, mostly porting PICAXE code. Recently I have gotten the hang of the 18F15Q40 chip, having sorted out how to use some of the "different" capabilities of this advanced chips when it comes to ADC config etc. But I am stuck on coding what was very straight forward with the PICAXE 20M2 and this how to estimate the VDD for a simple monitor on a battery powered application.

    Does anyone have a good reference specific to this chip or chip family? Anything I have found on this forum (links below) seems not to work for me, even the one which claims to be for this chip!

    Would be great if a working examples was available in the standard GCBASIC document :)

    https://sourceforge.net/p/gcbasic/discussion/579126/thread/dc82c1d50e/
    https://sourceforge.net/p/gcbasic/discussion/579126/thread/dc82c1d50e/
    https://sourceforge.net/p/gcbasic/discussion/579126/thread/810b24c927/?page=1

     
  • Anobium

    Anobium - 2024-08-28

    Hell Nick,

    I think you are missing the use of setting the constant AD_REF_SOURCE.

    This should work ( it is untested), this formats a string volts.

    Try, let us know if this resolves.

    Evan

    #chip 18F15Q40 
    #option Explicit
    
        Dim volts as string * 4
        Dim ADval as Byte
    
        // Use VDD as Reference
        #DEFINE AD_REF_SOURCE AD_REF_AVCC
    
        // Read AD
        ADVal = ReadAd(AN0)
    
        // Factorise result
        Dim ADvalWord as Word
        // Now volts is between 0 and 500
        ADvalWord=scale(ADVal, 0, 255, 0, 500)
    
        if ADvalWord<10 then
            volts="0.0"+left(volts,1,1)
        else if ADvalWord<100 then
            volts="0."+mid(volts,1,2)
        else
            volts=left(volts,1,1)+"."+mid(volts,2,2)
        end if
    
     
  • Nick

    Nick - 2024-08-31

    Thanks for response Evan.

    Much of the problem with the 18F15Q40 is how tricky it gets with the analog channels. AN0 is no more, it is probably ANA1 according the datasheet, at least that is what seems to be routed to vref+

    However ANA1 is also connected to pin 12, which in my case has a pull down.

    Its also the normal it seems to read the FVR first and scale the result; at least this seems how the other examples and the PICAXE folk did it.

    I am convinced it is in the AD_REF_SOURCE aspect of the chip; but nothing I seem to try gives me either a constant answer for the FVR or a VDD >0 (probably because of the pin is needed as a general input with pull down).

    When I slot in a PICAXE20M2 to the circuit it all works dandy! (of course the PICAXE is a different PIC core). Been bang my head for months actually before posting... every other requirement ported nicely in the end...

     
  • Anobium

    Anobium - 2024-08-31

    Nick. AN0 is ANA0.

    So, I am confused. Let me try a Q40 here. I will post some code.

     
  • Nick

    Nick - 2024-08-31

    Thanks Evan, its definitely doing my head in - so if you have more familiarity with these newer gen chips it would be appreciated.

     
  • Anobium

    Anobium - 2024-08-31

    Can you let me know what actual PIC the 20M2 is? I need this.

    The 20M2 will tell me what your starting point is.

    Is it a PIC16F1829 ? You can just put the 20M2 in a program and read the chip to determine its type. But, if you MUST select the chip and chip family first.

     
  • Anobium

    Anobium - 2024-08-31

    I assuming it is a 16F1829.

    Check the picture out. The Q40 and the 1829 both have VREF+ on PIN12. And, you have PIN12/RA1 pulled down.

    So, how do this work with the PICAXE? Was some other PIN used?

    I need to understand what worked on the PICAXE.

     
  • Nick

    Nick - 2024-08-31

    Hi Evan, sorry for the delayed reply (we are in different timezones).

    PICAXE say its a 16F1829 and when I read it in a programmer it says the same. Its contents are protected, so that's all I can get.

    The PICAXE code I use looks like this.

    calibadc10 varA
    varA= 52378 / varA * 20
    

    I believe this looks at the FVR and then scales according to expectation. This is why the external pin state is not a problem.

    I dont need super precision, just to warn when battery my need changing - but also for 360 rotational servos to do some crude voltage compensation to stretch on-time as voltage falls.

    I suspected the challenge is in how to switch and read the FVR. So have previously spent time checking the GBC ADC header file, etc. I think the logic is to read the ADC directly (high/low registers) rather than a channel - reading the channel "switches" the ADC away from the FVR to the pin. At a superficial level the header files looked to be doing the right thing, the forum examples also looked on the right track, but for this chip it isnt working out.

    I'm either doing something really simply wrong or ... either way, a calibadc style function in GCB would make the problem go away and help a lot of PICAXE project conversions. Those chips are great for beginners still, especially with their Blockly interface.

    Thanks for the offer to investigate.

     
  • Anobium

    Anobium - 2024-09-01

    OK. Thanks.

    Can you clarify the circuit. What is connected to the FVR+ pin?

    I have a memory of PICAXE caliadc() using 'Sample-and-Hold'. This requires a specific circuit.

    Can you ask a question on the PICAXE forum on the method used by caliadc? We do not the code just the approach. Is this 'Sample-and-Hold' and doss this use multiple samples? Is there any compensation of chip Temperature?

    Once we know the approach then we can resolve.

     
  • Nick

    Nick - 2024-09-01

    Hi Evan,

    I have connected the 20M2 to just the PICAXE programmer circuit. This is just VDD, VSS, the download output on "A.0" (pin 19) and download input circuit pin 2 (which is a10k to VSS and a series resistor to the PC programmer). If you recall this is proprietary serial programming method they use, and the output from A.0 can also be sent to the serial port on the PC for debug.

    With nothing else attached the debug reports 3000, and I measure 3.1v for VDD with a good multimeter; good enough for my purposes.

    I have attached the page from the PICAXE reference manual and they state for the 20M2 it uses the 1.024 voltage reference. This is the FVR and from my reading of the 18F15Q40 datasheets this should be the default also for the FVR on this chip from FVR_buf1. The challenge - how to route it internally with the special config bits and then read straight from the ADC electronics, ideally without resorting to learning assembler!

    When I have hacked some asm code from the forum examples which didnt give me zeros the value was jumping around a bit; as if it was random, so i wasnt convinced this was correct. it wasnt bit toggle it byte level jumping around like i had routed to a floating pin, so didnt feel convinced it was connected to the FVR which should be stable minus some bit noise given the battery supply.

    Hope these extra insights help. Thanks for spending the time to help crack this.

     
  • Anobium

    Anobium - 2024-09-01

    Ah... They are using the VP6EN ( 0v6) reference voltage approach. As documented on the PICAXE page. ( not Sample-And-Hold).

    0v6 is not available. As the new chip has other reference voltages then these should work.

    The VP6EN is not VFR - yet they can yield reference results.

    So, set the ADC up and read ANA1.

    #DEFINE AD_REF_SOURCE AD_REF_4096
    refVoltage = ReadAD ( ANA1 )
    
     
  • Nick

    Nick - 2024-09-01

    Hi Evan, no luck. The readAD(ANA1) just reads the pin connection.

    The ADPCH register gets reset.
    My guess is it needs a command like readAD(FVR) to read the correct internal channel rather than the external. So i tried something like this

    DEFINE FVR = 62 'xx111110, this gets loaded to ADPCH, FVR_buf1
    DEFINE AD_REF_SOURCE AD_REF_1024
    refVolts = ReadAD ( FVR )
    DataByte=RefVolts/10
    call SayNumber

    Repeated 10 times it gives numbers spread between 5-10.
    Vref = 70/255 for the 1.024V which means the VDD is around 3.75V which is probably realistic; but why the instability and it climbs as if saturating... This doesnt seem right to me. The PICAXE code is super stable!

     

    Last edit: Nick 2024-09-01
  • Anobium

    Anobium - 2024-09-01

    Something is not right in your implementation.

    Here is reference code. You may be missing FVRInitialize ( FVR_1x ) or you are leaving your programmer attached to RA1.

    Evan

    I do not have a 15Q40 but the 16Q40 is its big brother.

    #CHIP 18F16Q40
    #OPTION EXPLICIT
    
        'Generated by PIC PPS Tool for GCBASIC
        'PPS Tool version: 0.0.6.2
        'PinManager data: Not available (3)
        'Generated for 18f16q40
        '
        'Template comment at the start of the config file
        '
        #startup InitPPS, 85
        #define PPSToolPart 18f16q40
    
        Sub InitPPS
    
                'Module: UART pin directions
                Dir PORTC.6 Out    ' Make TX1 pin an output
                'Module: UART1
                RC6PPS = 0x10;   //RC6->UART1:TX1;    
                U1RXPPS = 0x0D;   //RB5->UART1:RX1;    
    
        End Sub
        'Template comment at the end of the config file
    
    
    
    '' -------------------PORTA----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    ----------------SW---------------
    ''-----------------------------------------
    ''
    '' ------------------PORTB-----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    ----SCL-----SDA------------------
    ''-----------------------------------------
    ''
    '' -------------------PORTC----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    -----TX-SW-LED--LED-LED LED-ADC--
    ''-----------------------------------------
    ''
    
    
    'Setup Serial port
    #DEFINE USART_BAUD_RATE 9600
    #DEFINE USART_BLOCKING
    #DEFINE USART_DELAY OFF
    
    
    '*****************************************************************************************************
    'Main program commences here.. everything before this is setup for the board.
    
    
    Dim adcval as Word
    Dim volts as String
    
        FVRInitialize ( FVR_1x )
    
        Do    
    
            wait 100 ms
            adcval = ReadAD ( ANA1 )
    
            adcval=adcval*100
            adcval=adcval/51
            volts=str(adcval)
            if adcval<10 then
                volts="0.0"+left(volts,1,1)
                goto volt_format_done
            end if
            if adcval<100 then
                volts="0."+mid(volts,1,2)
            else
                volts=left(volts,1,1)+"."+mid(volts,2,2)
            end if
            volt_format_done:
            HSerPrintStringCRLF volts
    
        Loop
    
    
    /* GCBASIC Optimisation file - this will optimise ADC operations by disabling the ADC operations on the AD channel that is set to FALSE
                                 to enable ADC operations on a specific AD channel set to TRUE
    
                Legacy chip Constants for ADC
     */
                #DEFINE USE_AD0 FALSE
                #DEFINE USE_AD1 FALSE
                #DEFINE USE_AD2 FALSE
                #DEFINE USE_AD2 FALSE
                #DEFINE USE_AD3 FALSE
                #DEFINE USE_AD4 FALSE
                #DEFINE USE_AD5 FALSE
                #DEFINE USE_AD6 FALSE
                #DEFINE USE_AD7 FALSE
                #DEFINE USE_AD8 FALSE
                #DEFINE USE_AD9 FALSE
                #DEFINE USE_AD10 FALSE
                #DEFINE USE_AD11 FALSE
                #DEFINE USE_AD12 FALSE
                #DEFINE USE_AD13 FALSE
                #DEFINE USE_AD14 FALSE
                #DEFINE USE_AD15 FALSE
                #DEFINE USE_AD16 FALSE
                #DEFINE USE_AD17 FALSE
                #DEFINE USE_AD18 FALSE
                #DEFINE USE_AD19 FALSE
                #DEFINE USE_AD20 FALSE
                #DEFINE USE_AD21 FALSE
                #DEFINE USE_AD22 FALSE
                #DEFINE USE_AD23 FALSE
                #DEFINE USE_AD24 FALSE
                #DEFINE USE_AD25 FALSE
                #DEFINE USE_AD26 FALSE
                #DEFINE USE_AD27 FALSE
                #DEFINE USE_AD28 FALSE
                #DEFINE USE_AD29 FALSE
                #DEFINE USE_AD30 FALSE
                #DEFINE USE_AD31 FALSE
                #DEFINE USE_AD32 FALSE
                #DEFINE USE_AD33 FALSE
                #DEFINE USE_AD34 FALSE
    //          Recent chip Constants for ADC 
                #DEFINE USE_ADA0 FALSE
                #DEFINE USE_ADA1 TRUE
                #DEFINE USE_ADA2 FALSE
                #DEFINE USE_ADA3 FALSE
                #DEFINE USE_ADA4 FALSE
                #DEFINE USE_ADA5 FALSE
                #DEFINE USE_ADA6 FALSE
                #DEFINE USE_ADA7 FALSE
                #DEFINE USE_ADB0 FALSE
                #DEFINE USE_ADB1 FALSE
                #DEFINE USE_ADB2 FALSE
                #DEFINE USE_ADB3 FALSE
                #DEFINE USE_ADB4 FALSE
                #DEFINE USE_ADB5 FALSE
                #DEFINE USE_ADB6 FALSE
                #DEFINE USE_ADB7 FALSE
                #DEFINE USE_ADC0 FALSE
                #DEFINE USE_ADC1 FALSE
                #DEFINE USE_ADC2 FALSE
                #DEFINE USE_ADC3 FALSE
                #DEFINE USE_ADC4 FALSE
                #DEFINE USE_ADC5 FALSE
                #DEFINE USE_ADC6 FALSE
                #DEFINE USE_ADC7 FALSE
                #DEFINE USE_ADD0 FALSE
                #DEFINE USE_ADD1 FALSE
                #DEFINE USE_ADD2 FALSE
                #DEFINE USE_ADD3 FALSE
                #DEFINE USE_ADD4 FALSE
                #DEFINE USE_ADD5 FALSE
                #DEFINE USE_ADD6 FALSE
                #DEFINE USE_ADD7 FALSE
                #DEFINE USE_ADE0 FALSE
                #DEFINE USE_ADE1 FALSE
                #DEFINE USE_ADE2 FALSE
    
     
  • Nick

    Nick - 2024-09-07

    Hi Evan,

    Did you say you tested this with the big brother chip? I have this too and have not had any luck with the code.

    I am also finding the result doesnt change with FVR_x1 or FVR_x2 or FVR_x4
    I would have expected the ADC value to scale?

    I'm not convinced reading ANA1 is correct. If the external pin is not connected this may work... but The FVR needs to be switched to be read internally to the ADC - how GCB does this is missing from my knowledge... By default VREF+ if it is routed to the external pin RA1/ANA1. We need to be redirecting this via its internal routing. I think this is the role of the ADPCH register, but not sure how that is done with GCB.

    I have wired up a diode/resistor to form a crude FVR on an external pin and the maths works fine when VDD is changed - I believe its something in the internal ADC channel selection that is not doing it correctly; ReadAD ( ANA1 ) will load the ADPCH with 1 and read from the pin, where as the ADPCh should be loaded with "read from FVR", which is 62 - but that is not giving an answer which scales with which FVR is selected...

    Any other thoughts to try?

     
  • Anobium

    Anobium - 2024-09-07

    Yes, I tested.

    The range reported changed as I changed the FVR. When FVR was _1x the ADC reported the max ADC when the voltage was at or above the 1x reference voltage. The same for the FvR setting.

    ANA1 is correct.

    Did you try the program above? post your ASM file. I will compare to mine to ensure your tool chain is producing the same ASM.

    I can video my tests, if this helps.

     
  • Nick

    Nick - 2024-09-07

    Hi Evan,

    The code you provided is put into a subroutine. Instead of sending via serial I play it back (DataByte sent to a subroutine). Can you see an issue with the below? The GBC help says to turn it off, but doesnt affect the result.

    sub CheckBattery ; check battery VDD
    dim adcval as byte

    FVRInitialize ( FVR_X1 )
    wait 100 ms
    adcval = ReadAD ( ANA1 )
    'FVRInitialize ( FVR_off )
    adcval=adcval*100
    adcval=adcval/51
    DataByte=adcval
    call SayNumber
    

    end sub

    When the chip is "in-circuit" the result is zero - pin 18, since ANA1 has a 10k pulldown. When I bend the pin out of circuit (so its floating) I get values, but they are "floating"... if the chip is left in a programmer its tied to whatever is inside the specific programmer as this pin is also the ICSPCLK; so again a random result?

    As mentioned, a PICAXE 20M2 works fine with the calib code, whether in the circuit, the pin floating or in the programmer. So my expectation is the pulldown should not be seen by the ADC if its configured properly internally to route the FVR to the ADC VREF+. Some how the PICAXE folk worked it out... or their chip can do it and the 18F cannot :(

    The other quirk in the sample code given is it goes against all the ASM and app_notes on using the FVR for VDD calculation. They basically say the FVR ADC result should be inversely proportional to the VDD and so the equation for VDD is something like VDD= constant/FVR_ADC. A higher VDD should give a lower FVR reading.

    adcval is never on the bottom of the above equations?

    Has me stumped :(

     
  • Anobium

    Anobium - 2024-09-08

    Nick I would be guessing.

    Please use the program above. Change only the chip. Why? This can be used a reference program. We both have the same program and you can then explain what works and what does not. I woud be guessing what you have in your existing program, there are manythings that your program could be doing that I cannot guess. The program above enables you to create the ASM, post the ASM and I can compare to what I have here.

    So, please use the program above and post the ASM.


    Re PICAXE. I will try again. The PICAXE uses 0.6v increments for the calibration. The internal microcontroller process is totally different implement ( within the microcontroller ) to that used for FVR. There is no comparison. And, therefore we have to resolve the FVR.


    What ASM are you refering to? Can you share the APPNOTE. Any information you have will help.


    My understanding of the issue is probably totally wrong, and, I need the reference program working at your end so we talk the same and we can resolve. :-)

    Evan

     
  • Nick

    Nick - 2024-09-08

    Hi Evan, it wont be until next weekend when I am back with hardware to retry. I have to build a serial debugger to use your code directly as my programmer doesnt support. I use a PICKIT2 which goes only to the upper 4 pins each side of the DIP as a universal programmer - this means I can program any chip out of circuit. In-circuit programmer on the boards for the project have the routing for either PICAXE or PIC downloads; and have these boards in schools for years... so are a proper PCBA.

    Can I ask when you run your code is the programmer attached, or removed so I can replicate? And which pin is your serial output on so I can route that to the same port for output on the PC? Does the chip needs the PPS configured?

    I can send you the ASM, but if its the same code as your posted why would the ASM be generated differently unless I am using an old version of GCB or its compilers? This confuses me. I only installed this in January 2024, could it be the compiler is out dated?

    As for the PICAXE, its a 20M2 and so this I am pretty certain uses the 1.024 voltage reference. The 0.6V is only for older chips. The datasheet references for the FVR and registers for the 16F1829 look to be the same as the 18F15Q40. I couldnt find reference to a 0.6V FVR in the 16F1829 datasheet like you do in the older chip (eg 16F690) docs. https://picaxe.com/basic-commands/advanced-picaxe-configuration/calibadc/ does give info that suggests its the 1.024 reference including formulas with the read ADC on the bottom of the VDD equation. If more convincing is needed that PICAXE use the 1.024V FVR, they make it clear "Note that the FVR voltage is reset to 1.024V via a calibadc command. " at this link https://picaxe.com/basic-commands/advanced-picaxe-configuration/fvrsetup/

    So even with 10k pulldown on pin18 the code for the 20M2 works fine, but for the PC18F15Q40 it reports zero (when using ANA1 as the ADC channel) and floating when note connected to anything.

    If you can please outline the hardware you have wired to pin 18 that would be handy so I can fully replicate both the software and the hardware when I next try. Leaving the programmer attached will mean its connected to whatever is inside the PICKIT2 since it is one of the programming lines.

    Thanks again for looking into this. I'm sure we will nut it out.
    Nick

     
    • Anobium

      Anobium - 2024-09-08

      :-)

      Next weekend no issue. I will look out for progress.


      I tried with PICKit2 attached and removed.

      PPS is determined in the program already. Dir PORTC.6 Out ' Make TX1 pin an output.

      So, PORTC.6 is the TX.


      Do upload the ASM. This is a to check your configuration is up to date. The intent of GCASTUDIO is to keep your setup up to date. But, ensuring the ASM is the same makes sure the tool chain is in order.


      You are probably right about FVR. I may have looked up the wrong datasheet.


      Re the circuit attached. A chip, 5v0 and 0v0 and one ADC to ANA1. This is it.

       
  • Nick

    Nick - 2024-09-21

    Hi Evan,
    I have not yet been able to find time to build a "vanilla" circuit with a debug terminal port PORTC.6

    However, i have compiled with both the 15Q40 and 16Q40 chips and attached.

    I will try to find time to build the circuit later this weekend. Fingers, crossed.

     

    Last edit: Nick 2024-09-21
  • Anobium

    Anobium - 2024-09-21

    Thank you. No rush.

     
  • Nick

    Nick - 2024-09-21

    Thanks Evan, reattached the 15Q40.ASM

     
    • Anobium

      Anobium - 2024-09-21

      The ASM with GCBASIC source would help me.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.