Menu

18LF18313 - LPBOREN Not working as expected ! Well it is but not quite !

2024-07-24
2024-08-13
  • Andrew Jameson

    Andrew Jameson - 2024-07-24

    Good afternoon,
    I'm working on, what will be a solar powered application where the supply voltage will be subject to slow rise times and it seemed wise to try to minimize the risk of the PIC ending up in an invalid state. So LPBOREN looked like the ideal solution and I set BORV low, thereby enabling a threshold of 1.9V.
    All seemed to work as expected, the chip stopped at anything lower than 1.9V and restarted normally at anything over than 1.9V.
    Now, I just tested it with a solar panel attached, that charges a 1000mfd as a small reservoir and it no longer works ! During startup, the first thing that happens is an LED pulses for 5mS as an indicator that the program is initializing. However, what is happening is that the LED stays on causing enough drain to stop the supply voltage rising any further indeed it freezes at just over 1.9V.
    It does look as though it might be oscillating, not 'scoped it yet but is it possible that the LPBOREN is cycling the reset ? It's held in reset until the supply is OK but then the supply dips and it's then back in reset - ad infinitum !
    Removing LPBOREN and it all works and the supply voltage slowly rises up to the design limit of 2.7V (the final version will use a supercapacitor and that is the voltage limit).
    Am I missing something ?
    I'd have expected some hysteresis to be associated with the chip's 1.9V detection but there's no mention but ... I've just noticed the PWRTE config bit for a 64mS startup delay and that seems to have it working as expected - so I could just give it long delay running into seconds or minutes.
    Nevertheless, I've never had the chip lockup without LPBOREN and I can now see the risk associated with LPBOREN - an increase current demand at the threshold of 1.9V can result in a never ending reset / run cycle.
    Any advice ? - I don't want to have manual intervention such as a reset button ... just want the chip to run when / if it can.

     
  • Anobium

    Anobium - 2024-07-24

    A great question but no experience here. I thought I would say this rather then stay silent.

     
  • Angel Mier

    Angel Mier - 2024-07-24

    Hi, just some thoughts that may help your project.

    I believe based on what I read on the microchip datasheets, that LPBORDEN was designed for “momentary” ramp up voltage’s with time frames of milliseconds, usually the time it takes to a power supply or a dc-dc converter to stabilize or charge the decoupling and bulk capacitors. But in your application, it seems that it will be subjected to seconds or even minutes of ramp up, depending on the available solar intensity.
    In this case you may need a voltage supervisor circuitry to cover your MCU, there are different approach to do this, from a simple reverse Zener drived transistor or mosfet, to an of the shelf voltage monitor like the TPS3839 (just an example, there are a lot of other parts of different manufacturers) I prefer this last method.

    Datasheet:
    https://www.ti.com/lit/ds/symlink/tps3839.pdf

    There is a simple explanation of how this system works and it also uses the same part I suggested as example, maybe you don't like his English accent, but I assure you it's better than mine. 😊
    https://www.youtube.com/watch?v=BqwUNOHiZ9k

    Hope it helps.

    Angel

     

    Last edit: Angel Mier 2024-07-24
  • Angel Mier

    Angel Mier - 2024-07-24

    Another thing you can do, taking in to account that your selected PIC has an internal voltage reference; is to program it to measure the Vdd voltage of the chip (the ADC can be programmed to compare Vdd to Vref internally without losing an analog pin) and don’t turn on the led or any other power-hungry device until enough voltage is present. this should prevent a reset loop.

    On this block diagram of a 18f45k50 ADC you can see that the adc mux have "vdd" and "vss" switches, and taking into account that the GCB ReadAD10 library just converts port numbers (anX) to a bit register number; in this case you can simply use:

    ReadAD10(an31)
    

    To reverse measure Vdd in respect to internal Vref.

    Note: refer to your specific datasheet to determine port number needed on your part.

    This code should work as an example:

    //This program will measure Vdd voltage and show it on an LCD with other registers.
    
    #chip 18F45k50, 48
    #option Explicit
    
    #define HI2C_BAUD_RATE 400
    #define HI2C_DATA PORTB.0
    #define HI2C_CLOCK PORTB.1
    Dir HI2C_DATA in
    Dir HI2C_CLOCK in
    HI2CMode Master
    
    #define LCD_IO 10
    #define LCD_I2C_Address_1 0x4E
    #define LCD_SPEED OPTIMAL
    #define LCD_WIDTH 16
    #define LCD_Backlight_On_State  1
    #define LCD_Backlight_Off_State 0
    
    LCDBacklight (Off)
    
    PVCFG0 = 0
    PVCFG1 = 0
    
    fvren = 1
    
    #define ADSPEEd LowSpeed
    
    Do
    
        cls
        locate 0,0
        print ReadAD10(an31)
        //an31 measures internal VRef
        Locate 1,0
        print fvrs0
        print fvrs1
        print PVCFG0
        print PVCFG1
        print fvren
        print fvrst
        wait 250 ms
    
    Loop
    
    End
    

    Angel

     

    Last edit: Angel Mier 2024-07-24
    • Angel Mier

      Angel Mier - 2024-07-24

      I just reviewed your part datasheet, and indeed it uses "An31" for internal Vref, you just need to change the PVCFG register in the code to ADPREF that is used in your part, same numbers apply for vdd (00).

      Also remember that the output value of "readad" will be inverted (more is less voltage)

       

      Last edit: Angel Mier 2024-07-24
  • Andrew Jameson

    Andrew Jameson - 2024-07-25

    Hi Angel,

    Many thanks for your input.

    I'd had thoughts like yours a while back and bought a few TC54s - 2.7V. The TC54 is a MicroChip voltage detector with extremely low power consumption. I had the idea of simply waiting for the supercapacitor to reach full charge using the TC54 to hold the PIC in reset and then ignore the TC54 supply good when the PIC was up and running.

    Just have this nagging doubt that whatever implementation, the chip will unexpectedly lock up due to another oversight !

    The odd thing is that the chip has never locked up if I don't use brown-out no matter how slowly Vdd rises - but again the risk.

    I'd have thought by now that MicroChip would have come up with a bullet proof solution and a chip that won't freeze. The fact that the TC54 exists at all indicates the awareness of the problem. I'd even considered an external watchdog but the complexity grows !
    I'll try using the A/D - not something that I've played with - it's a good idea but if the chip freezes then it won't be able to do much at all !

    I recollect secure CPU designs in the past where they collectively analysed one another's actions, if one stepped out of line, the others would kill it; that was if the rogue one hadn't already committed suicide ! Much akin to the old VAX Clusters - shared task loading ... a good idea but if you got it wrong, they'd spend all the time passing tasks around to even the load but never found the time to actually run the task.

    I've read other threads with great interest but often there's no conclusion - bit like a whodunnit where the last page is missing ... so I'll try to come back and share my chosen "solution".

    Thanks

    Andrew

     
  • Andrew Jameson

    Andrew Jameson - 2024-07-25

    Oops ... just noticed a typo in the title - the PIC is actually a 16LF18313.

    Yes, the LPBOREN was causing it to reset / start / reset ... an oscillation of about 1kHz !

     
    • Angel Mier

      Angel Mier - 2024-07-25

      revised the datasheet, the 16LF1813 also have an internal Vref. I adapted the code to your part, I don't have that part in stock to test but it should work.

      //This program will measure Vdd voltage from 1.4v to 3.6 on LF parts.
      
      #chip 16lf18313, 32
      #option Explicit
      
      Dim volts as Integer
      
      //configure internal Vref buffers to 1.024V.
      CDAFVR1 = 0
      CDAFVR0 = 1
      
      ADFVR1 = 0
      ADFVR0 = 1
      
      //enable intenal Vref
      FVREN = 1
      
      #define ADSPEEd LowSpeed
      
      Do
          volts = ReadAD10(an31)
          //an31 measures internal VRef
      
          wait 250 ms
      Loop
      
      End
      

      I used this clever method to know the battery level of battery powered devices.

       

      Last edit: Angel Mier 2024-07-25
  • Andrew Jameson

    Andrew Jameson - 2024-08-13

    Hi Angel,
    One of those days trying to find why my serial comms keeps producing a couple of random characters following a PIC restart. So I thought I'd build a test program around your code.
    Failed on both counts ;o( ...
    Serial comms proved to be perfect and I failed to comprehend the numbers coming back from your code. Current test bed is using a 3V battery supply and your example was returning values around 1005 - 1011. What I can not do is actually understand how I might derive a real voltage value - something like 3V would be good.
    Gave ChatGPT a good try but, not unexpectedly, it came up with garbage and even invented a couple of non-existent registers. Sometimes, with a bit of effort, it comes up with acceptable code but the best I got was the suggestion that I read the datasheet !
    Actually there's very little on the internet about reading battery voltage - a lot of threads without solutions - those that exist rely on resistor voltage dividers or timers seeing how long to charge a capacitor.

    Thanks for your time,

    Andrew

     
  • Andrew Jameson

    Andrew Jameson - 2024-08-13

    I forgot - the LPBOREN solution !

    I stopped the fast restart cycle by detecting the fact that it was a brown out reset and basically did nothing for 8 seconds or more after which a watchdog timer triggers and the program is allowed to run - that seemed to be a good solution.

    However, I have found that the PIC has never locked up and there's an advantage in that the PIC can run, dare I say happily, down to around 1.4 volts, so the LPBOREN settings are commented out for the time being.

    Andrew

     
  • Ccin E Crout

    Ccin E Crout - 2024-08-13

    I use this to give an approximate battery level.
    It uses (for this demo) an LCD to display the battery voltage.
    Hopefully this will give you an idea.

    'LCD connection settings
    #Define LCD_IO 4
    #Define LCD_SPEED FAST
    #Define LCD_NO_RW
    
    'Port assignments
    #Define LCD_RS        PortA.0
    #Define LCD_Enable    PortA.1
    
    #Define LCD_DB4       PortA.2
    #Define LCD_DB5       PortC.0
    #Define LCD_DB6       PortC.1
    #Define LCD_DB7       PortC.2
    
    'set up fixed voltage reference model
     FVRCON = b'10000010'    ' Set FVREN On and ADC Vref to 2.048V
     ADCON1 = b'01010000'    'Left justified, FOSC/16, Vref+ to VDD
    
    #Define AN1 = 1
    #Define FVR = 62 'was 31 for 16F1829
    
    Dim ADFetch    As Word
    Dim RefVolts   As Word
    Dim BatVolts   As Word
    
    Get_Battery
    
    Sub Get_Battery
    
        '1) Enable and set the FVR (fixed voltage reference) register for 2.048V setting.
        '2) Enable and read the A-D FVR ;This is an internal register
        '3) You now know what the battery voltage is at that time according to:
        '
        '2.048V / BatVolts = A-D FVR / 255 ;(8 bits is close enough)
        ';Promote values by 100
        'BatVolts = 52224 / A-D FVR ;A-D FVR reading should be around 175 at 3V
    
        Dim Vu  As Byte
        Dim Vf  As Byte
        Do
            RefVolts = ADFetch(FVR)   'internal a-d of FVR
            BatVolts = 52224 / RefVolts
    
            Locate 0,0
            Print "Voltage "
            Let Vu = BatVolts / 100
            Print Vu
            Print "."
            Let Vu = Vu * 100
            Let Vf = BatVolts - Vu
            Print Vf
            Print              "V       "
            Locate 1,0
            Print "Raw "
            Print RefVolts
            Print "                "
            Wait 750 mS
        Loop
    End Sub    
    

    It separates the decimals from the fractions for display purposes.

    I claim no originality for the code, it was pretty much a direct copy from somewhere else in this forum.

     
  • Andrew Jameson

    Andrew Jameson - 2024-08-13

    Thanks for that - I'll give it a try.

    Andrew

     

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.