News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

How many write cycles to PIC EEPROM?

Started by Frizie, Mar 13, 2021, 03:51 PM

Previous topic - Next topic

Frizie

For a project I have to keep track of how often a press has already pressed something (a total counter for service maintenance).
However, every day the press is switched off and the count (RAM) is gone.
It is an existing PIC control (with Proton and PIC16F1829). :)

The only option I have now is in my opinion the EEPROM in the PIC.
After each press, I increase the count in the EEPROM.
The count will then be remembered when switching off the power from the press.
However, after just one year, the count can exceed 100,000. :o

In the datasheet of PICs with an EEPROM I read under Electrical Specifications under the heading Data EEPROM Memory:
Byte Endurance: 100K (= 100.000)

But a little further:
Number of Total Erase / Write Cycles before Refresh: Min. 1M | Typ. 10M

How should I interpret this?
I mean, how many times can I write to the same EEPROM address before the data becomes unreliable?
And what exactly do they mean with "Byte Endurance"?  ???
Ohm sweet Ohm | www.picbasic.nl

tumbleweed

The Byte Endurance (100K) is the min number of times they guarantee you can write to a single location and have it "work".

The other number (total E/W cycles before refresh) has to do with total EEPROM writes. Every time you write to one location it bleeds off charge from others, so eventually you can end up "erasing" locations you're not even writing to. When you hit the refresh number (1M in this case), you should read and re-write the entire EEPROM to refresh the data.

From the datasheet section 11.2 Using the Data EEPROM:
QuoteWhen variables in one section change frequently, while variables in another section do not change,
it is possible  to exceed the total number of write cycles to the EEPROM without exceeding the total number of write cycles to a single byte.

If this is the case, then a refresh of the array must be performed

Gamboa

Frizie,

To avoid endurance problems you can use an external FRAM memory. You also have another possibility with EERAM memories.
But if the PCB is already done you can only wire with wires. 

Regards,
Gamboa
Long live for you

tumbleweed

I just reserve space for multiple counters and cycle through them on each write. If you had space for 10 counters then you'd have a min of 10 x 100000 = 1000000 write operations before worrying about the endurance issue.

At that point you could also refresh the EEPROM. No additional hdw required.

TimB

I had the same kind of issue with a mileage logger I built. I had to update the last location in sram that the data was stored. The update was every 5 seconds.

What I ended up doing was keeping a count and only writing to eeprom every 100 (approx) counts.

The next thing was I had a little supercap and was able to detect a power outage and used the supercap to give me time to save the current location to eeprom in a controlled way.

Tim

Frizie

Thanks for the clarification and ideas Tumbleweed, now it's all clear for me. :)

Tim, the idea with the supercap also crossed my mind.

Gamboa, I know that FRAM and EERAM memory's exist, I haven't work with them yet, maybe for future projects I will take a look to these devices, but the mentioned solutions here are good for now and it's already baken in the PIC controller. ;)
This way I don't have to change the hardware.

Many thanks for thinking along guys.
Frizie.
Ohm sweet Ohm | www.picbasic.nl

paulc

#6
Have enough capacitance in the power supply (44uF is more than enough in my case). Detect powerfailure on an input using an interrupt. Switch off all powerusers immediately, then write to eeprom in this routine. You could also use the HLVDCON, if available, to detect low voltage in time. I use this a lot and it works perfectly.

top204

I use the HLVD peripheral whenever the final unit is being powered by batteries, because it gives an excellent indication of low voltage, and uses no extra pins. I always set the threshold just above what is critical, so the unit has time to take actions and warn the user. It can also be used to trigger an interrupt when the voltage falls, and this can be used to over-ride all other actions in the firmware and save and shut down etc...

Below is a simple demo showing the HLVD operating on a PIC18F26K40 device. Note that, as always, some devices have different SFR setups and different values for the trip thresholds, so always read the datasheet if using a device other than the PIC18F26K40 or PIC18F46K40.

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Setup the HLVD peripheral on a PIC18F26K40 device to detect low voltage
' For some other devices, the Voltage Trip values may be different, so always read the datasheet.
'
' Written by Les Johnson for the Proton8 BASIC compiler.
' https://sites.google.com/view/rosetta-tech/home
'
    Device = 18F26K40                   ' Tell the compiler what device is being used
    Declare Xtal = 16                   ' Tell the compiler what speed the device is operating at
   
    Declare Hserial_Baud = 9600         ' Set the Baud rate for USART1
    Declare HRSOut1_Pin = PORTC.6       ' Set the TX pin to use for USART1
'
' The voltages to set a trip for the HLVD peripheral on a PIC18F26K40 device
'
$define cHLVD_TRIP_POINT_1_85V 0        ' Trip at 1.85 Volts
$define cHLVD_TRIP_POINT_2_06V 1        ' Trip at 2_06 Volts
$define cHLVD_TRIP_POINT_2_26V 2        ' Trip at 2_26 Volts
$define cHLVD_TRIP_POINT_2_47V 3        ' Trip at 2_47 Volts
$define cHLVD_TRIP_POINT_2_57V 4        ' Trip at 2_57 Volts
$define cHLVD_TRIP_POINT_2_78V 5        ' Trip at 2_78 Volts
$define cHLVD_TRIP_POINT_2_88V 6        ' Trip at 2_88 Volts
$define cHLVD_TRIP_POINT_3_09V 7        ' Trip at 3_09 Volts
$define cHLVD_TRIP_POINT_3_40V 8        ' Trip at 3_40 Volts
$define cHLVD_TRIP_POINT_3_60V 9        ' Trip at 3_60 Volts
$define cHLVD_TRIP_POINT_3_71V 10       ' Trip at 3_71 Volts
$define cHLVD_TRIP_POINT_3_91V 11       ' Trip at 3_91 Volts
$define cHLVD_TRIP_POINT_4_12V 12       ' Trip at 4_12 Volts
$define cHLVD_TRIP_POINT_4_32V 13       ' Trip at 4_32 Volts
$define cHLVD_TRIP_POINT_4_63V 14       ' Trip at 4_63 Volts

$ifndef True
    $define True 1
$endif
$ifndef False
    $define False 0
$endif

'------------------------------------------------------------------------------
' The main program starts here
' Detects a low voltage on the PIC18F26K40 device
' Sends a message to a serial terminal about the state of the device's voltage
'
    HLVD_TripSet(cHLVD_TRIP_POINT_4_12V)                ' Set the HLVD's trip voltage to 4.12V
    HLVD_Enable()                                       ' Enable the HLVD peripheral
   
    Do                                                  ' Create a loop
        If HLVD_Tripped() = True Then                   ' Has the HLVP peripheral triggered because of low voltage?
            HRSOutLn "Voltage Tripped"                  ' Yes. So transmit to the serial terminal
        Else                                            ' Otherwise...
            HRSOutLn "Voltage OK"                       ' Send an OK message to the serial terminal
        EndIf
        DelayMS 512                                     ' Add a delay so we do not have a flood of serial texts
    Loop
   
'------------------------------------------------------------------------------
' Setup the HLVD peripheral for a default trip voltage
' Input     : None
' Output    : None
' Notes     : Sets the default trip voltage to 4.12V
'
Proc HLVD_Default()
    HLVDCON1 = cHLVD_TRIP_POINT_4_12V   ' Set the default trip voltage to 4.12V
    HLVDCON0 = %10000000                ' HLVDEN enabled
    PIR2bits_HLVDIF = 0
EndProc

'------------------------------------------------------------------------------
' Enable the HLVD module
' Input     : None
' Output    : None
' Notes     : None
'
Proc HLVD_Enable()
    HLVDCON0bits_HLVDEN = 1
    PIR2bits_HLVDIF = 0
EndProc

'------------------------------------------------------------------------------
' Disable the HLVD module
' Input     : None
' Output    : None
' Notes     : None
'
Proc HLVD_Disable()
    HLVDCON0bits_HLVDEN = 0
EndProc

'------------------------------------------------------------------------------
' Set the trip point parameter for the HLVD peripheral
' Input     : pTrip holds the trip voltage value
' Output    : None
' Notes     : None
'
Proc HLVD_TripSet(pTrip As Byte)
   HLVDCON1 = pTrip                     ' Set the trip point value
EndProc

'------------------------------------------------------------------------------
' Return the band gap voltage status
'
Proc HLVD_BandGapVoltageStable(), Bit
    Result = HLVDCON0bits_HLVDRDY
EndProc

'------------------------------------------------------------------------------
' Set the trip point parameters for the HLVD peripheral
' Input     : pNegTrip
'           : pPosTrip
'           : pTrip holds the trip voltage value
' Output    : None
' Notes     : None
'
Proc HLVD_TripPointsSetup(pNegTrip As Bit, pPosTrip As Bit, pTrip As Byte)
   HLVDCON0bits_HLVDINTL = pNegTrip     ' Set the Negative trip
   HLVDCON0bits_HLVDINTH = pPosTrip     ' Set the Positive trip
   HLVDCON1 = pTrip                     ' Set the trip point value
EndProc

'------------------------------------------------------------------------------
' Return the HLVD voltage status
' Input     : None
' Output    : Returns 1 if the voltage level has tripped
' Notes     : None
'
Proc HLVD_Tripped(), Bit
    Result = HLVDCON0bits_HLVDOUT
EndProc


trastikata

QuoteHowever, after just one year, the count can exceed 100,000.

1. I would reserve an address in the EEPROM to point to the current counter's address. Also I would back it up on a second address with a marker to make sure it was updated correctly (in case of shutdown while updating it) so no information can be lost.

2. In your subroutine, when you approach 100 000 on the current address, change the EEPROM counter's address and write the address in the pointer and its back-up. 

3. At the beginning of every power cycle, read the pointer, the pointer's back-up and make sure they match, if they don't - use the last valid pointer and repair the information.

4. Use that pointer to determine where to write the counter.

If your application requires around 100 000 updates per year, the EEPROM gives you enough space for many years to come.