In my HVAC project, I am trying to find a way to store ever changing values without ruining my persistent memory...
anytime a setting is changed I want to store it, so in the event of an electrical power failure the controller recovers to its previous settings...
obviously i can use persistent bytes... however it will eventually ruin the non volatile memory if i write to it each time a setting changes.. I realize a million writes is a lot.. is there an external chip I can use?
also how many bytes of persistent memory exist on a ZX-328n and a ZX-1281n that I can use? maybe I can rotate writing different bytes so that I dont ruin the memory as fast?
-Christopher
what to do with ever changing values?
Re: what to do with ever changing values?
An FRAM device like the FM25256B may be useful. It has an SPI interface and claims 10^14 cycles lifetime.cadillackid wrote:is there an external chip I can use?
Check the ZX Device Parameter web page. It is also available as an Excel spreadsheet.cadillackid wrote:how many bytes of persistent memory exist on a ZX-328n and a ZX-1281n that I can use?
Wear leveling is a well-known procedure. I believe that Atmel and Microchip both have application notes on the topic.cadillackid wrote:maybe I can rotate writing different bytes so that I dont ruin the memory as fast?
- Don Kinzer
I used wear leveling in order to extend the life of a hour meter project. Using an array of 200 persistent variables I was able to extend the lifespan of the product from the advertised 100,000 writes, to 20,000,000 writes. It's been running for 2 years nonstop so far, writing once per minute, without any problems. I gather it will run for another 36 years before I see a failure.
The other method worth mentioning is power failure detection. Monitor the incoming power supply for a loss of power. Provide enough backup power (usually in the form of capacitance) to write the current value to persistent memory, but only do it when the power fails.
Neither of the above techniques require additional components, which is a plus.
-Don Kirby
The other method worth mentioning is power failure detection. Monitor the incoming power supply for a loss of power. Provide enough backup power (usually in the form of capacitance) to write the current value to persistent memory, but only do it when the power fails.
Neither of the above techniques require additional components, which is a plus.
-Don Kirby
http://www.atmel.com/dyn/resources/prod ... oc2526.pdf
Here's an example I wrote some time ago, from the BX-24 Yahoo list. Note that lTwoDaysInTicks applies a trick to the BX-24 RTC that probably does not work in ZBasic machines. Adjust accordingly.
Like Don, I have one of these running without a failure for several years.
Here's an example I wrote some time ago, from the BX-24 Yahoo list. Note that lTwoDaysInTicks applies a trick to the BX-24 RTC that probably does not work in ZBasic machines. Adjust accordingly.
Code: Select all
' Hobbs-like Running Time Meter on BX-24
' 0.001 hour resolution (or 0.01)
' Resettable ~1165 hour maximum count (11650)
' 12000 hour minimum endurance (120000)
' 2006-03-28 Tom Becker GTBecker@RighTime.com
const Pin_Input_Reset_Count_Not as byte = 10
const ilenCircularBuffer as integer = 120
dim laCircularBuffer(1 to ilenCircularBuffer) as New PersistentLong
dim iXMax as integer
const lThousandthHourInTicks as Long = 1843 '0.001hr = 3.6seconds * 512ticks = ~1843 (0.01% error)
const lTwoDaysInTicks as long = 88473600 'RTC T0, well beyond 24 hours; won't reset at midnight
sub Main()
call PutPin (Pin_Input_Reset_Count_Not, bxInputPullup) 'reset switch pin
if FirstTime then
call Reset
end if
iXMax = iGetLargestRunningTimeIndex 'find index of largest in ring, resume
call SetRTCTicks(laCircularBuffer(iXMax) * lThousandthHourInTicks) 'start timer from there
call ShowRunningTime 'show start time
do 'endless
if (lGetRTCTicks \ lThousandthHourInTicks) <> (laCircularBuffer(iXMax)) then
iXMax = iXMax mod ilenCircularBuffer + 1 'next in ring
laCircularBuffer(iXMax) = lGetRTCTicks \ lThousandthHourInTicks 'store each 0.001 hour
call ShowRunningTime
end if
if GetPin(Pin_Input_Reset_Count_Not) <> 1 then
call Reset
call ShowRunningTime
end if
loop
end sub
function lGetRTCTicks() as long
lGetRTCTicks = register.RTCTick - lTwoDaysInTicks 'RTC count is offset to avoid midnight
end function
sub SetRTCTicks(byval lTicks as long)
register.RTCTick = lTicks + lTwoDaysInTicks
end sub
sub ShowRunningTime()
debug.print strRunningTimeInHours(laCircularBuffer(iXMax))
end sub
function strRunningTimeInHours(byval lT as long) as string '1165.210hr max; (2^31-1/512/3600)-48hrs
dim strH as string*5, strF as string*4
strF = cStr(lT mod 1000 + 1000) 'hour fraction
lT = lT \ 1000 'discard fraction
strH = cStr(lT + 10000) 'hours
strRunningTimeInHours = mid(strH, 2, 4) &"."& mid(strF, 2, 3)
end function
sub Reset()
call ResetRunningTime 'zero ring
call SetRTCTicks(0) 'zero RTC
end sub
sub ResetRunningTime()
dim iX as integer
debug.print " Reset"
for iX = 1 to ilenCircularBuffer 'this takes about four seconds on BX-24
laCircularBuffer(iX) = 0
next
end sub
function iGetLargestRunningTimeIndex () as integer
dim iX as integer
debug.print " Resume"
iGetLargestRunningTimeIndex = 1
for iX = 1 to ilenCircularBuffer 'get index of largest value
if laCircularBuffer(iGetLargestRunningTimeIndex) < laCircularBuffer(iX) then
iGetLargestRunningTimeIndex = iX
end if
next
end function
Tom
-
- Posts: 35
- Joined: 22 August 2009, 16:34 PM
I think im going to go the route of rotating data in the persistent areas... I realized that even if the thermostat settings changed 1000 times per day(which is an awful lot of adjusting...roughly once every 1.4 minutes).. I would hit close to the 1 million mark little less than once a year... im only using about 10 bytes of persistent memory.. so if I rotate in 100 bytes It should last about 10 years.... but then who is going to adjust their settings 1000 times / day...
I dont want the controller to stay active during a power failure as in HVAC its not a good idea to "bang" equipment... however the controller is powered by the A/C unit which is 5 volts so I could just read a pin and have a capacitor as suggested earlier to hold power up long enough for me to start the time delay and save the settings....
-Christopher
I dont want the controller to stay active during a power failure as in HVAC its not a good idea to "bang" equipment... however the controller is powered by the A/C unit which is 5 volts so I could just read a pin and have a capacitor as suggested earlier to hold power up long enough for me to start the time delay and save the settings....
-Christopher
I have also had good results with FRAM (from Ramtron), though now some other products incorporate this type of memory. For instance the Dallas DS32X35 incorporates a VERY accurate RTC and FRAM in the same package. The two currently available have 2K and 8K of FRAM. Fram wil not wear out, so you do not have to worry about wear levelling. I beleive you already have an I2C bus on your device, and these are I2C devices, though Ramtron also offers SPI FRAM devices.
If you are going to need an RTC, then the Dallas chip might make sense.
-Tony
If you are going to need an RTC, then the Dallas chip might make sense.
-Tony
I have a ZX that uses the rotating fixed length data record approach. Each record is numbered (ascending). So at startup, the code looks for the highest numbered record. The writing code uses circular buffer and overwrites the lowest numbered record.
THis has been running here for 2 years or so - with 4 or so records added per day. Using onboard EEPROM
THis has been running here for 2 years or so - with 4 or so records added per day. Using onboard EEPROM