Shop OBEX P1 Docs P2 Docs Learn Events
Help with power down save value to EEPROM — Parallax Forums

Help with power down save value to EEPROM

Don MDon M Posts: 1,653
edited 2011-07-10 15:09 in Propeller 1
In my project I have successfully been able to save a value to the EEPROM after the Propeller detects a power down. I would like to share with everyone here my example but also have a question about a small glitch.

I am using the Propeller Proto board (non USB version). This board comes with a 1000 uF capacitor that is un-connected. I connected it to the 3.3 volt bus. I also added 2 resistors as a voltage divider from the 5 volt supply bus. I tie the center of the divider network to P20 on the Propeller. See attached schematic.

Power supply example 2.png


My Logic Analyzer connections are: I2C CLK, I2C DATA, P20 Input from divider, 3.3 volt supply.

Here I'll show you a Logic trace taken during the power down sequence. In this trace I have shown 2 green markers that indicate the start and stop of the I2C routine writing to the EEPROM. I have placed a red box around the time showing that it takes approx 2.84 mS to write a long to the EEPROM.

Powerdown save 1.jpg


Next is a wider view of the Logic trace showing the time relationship between when P20 goes to logic low and when the 3.3 volt bus goes to a logic low value. Note that the time it takes is approx 17.64 mS.

Powerdown save 3.jpg


Now here is where my glitch question comes in. In this trace you will notice that the I2C object is trying to write again to the EEPROM. I think this has to do with the way I have my loop logic written but I don't know how to correct it. I added "repeat 1" to the loop to try and make it only write 1 time but that didn't help. Here is the Logic trace showing what I am talking about. I have circled in red where it starts to try and write but you can see that it does not finish. Maybe the EEPROM Vcc is to low by then? I don't know. All I know is that I want it to only write the one time and quit.

Powerdown save 2.jpg


And here is an even wider Logic trace showing the timing relationships when all the pins go low after the detection of power down. You can see that the overall time is approx 39.4 mS.

Powerdown save 4.jpg


Here is my code:
con

  _clkmode = xtal1 + pll16x
' _xinfreq =  5_000_000
  _clkfreq = 80_000_000

  MS_001   = _clkfreq / 1_000

  RS = 9       ' 1                   
  RW = 10      ' 2                    
  E  = 11      ' 3

  DBLow  = 12   ' 0
  DBHigh = 15

  PWR = 20

  EE_DEVICE_ADDR                = $A0
  EE_BASE_ADDR                  = $9000

con

  #1, HOME, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR, #16, CLS      ' PST formmatting control

'  0.003515185598214                                            ' multiplier for inches / pulse

obj

  term  : "fullduplexserialdp"                                  ' for terminal output
  level : "jm_grayenc2"                                         ' 2-bit, graycode encoder 
  kp    : "Keypad_encoder"                                      ' keypad driver object P0 - P7
  vfd   : "LCD_Nx2"                                             ' VFD driver
  simp  : "Simple_Numbers_plus"
  i2c   : "Basic_I2C_Driver_1"

var


pub main | newlevel, oldlevel, Pressed_Key

  term.start(31, 30, %0000, 115_200)                            ' start terminal for test
  pause(2000)
  term.tx(CLS)

  dira[PWR] := 0

  i2c.initialize(28)
  level.init(16, true, 0, 1707, i2c.ReadLong(i2c#BOOTPIN, EE_DEVICE_ADDR, constant(EE_BASE_ADDR + $0)))                             ' detented encoder on p16/p17
 
  vfd.Init( E, RS, RW, DBHigh, DBLow )
  kp.start(4, 4, 0, 4, @table)                                   ' start keypad driver

  pause(1)
    
  vfd.clear                                                    ' clear vfd screen
  term.str(string("Table Controller", 13))
  term.str(string("Version 0.07"))
  vfd.PrintStr(string("Table Controller")) 
  vfd.SetRowCol(2, 0)
  vfd.PrintStr(string("Version 0.07"))
  pause(4000)
  vfd.clear
  term.tx(CLS)
  term.tx(LF)
  term.str(string("Press PROG for Menu"))
  vfd.SetRowCol(2, 0)
  vfd.PrintStr(string("Press PROG for Menu"))
  pause(500)

  
  repeat
  
    oldlevel := newlevel                                        ' setup to detect change 
    term.tx(HOME)                                               ' display it
    vfd.SetRowCol(0, 0)
    vfd.PrintStr(string("Position: "))
    term.str(string("Position: "))
    vfd.SetPos(16)
    vfd.PrintChr($22)
    newlevel *= 3515                                            
    newlevel /= 100
    term.decdp(newlevel, 4)
    vfd.SetPos(10)
    vfd.PrintStr(simp.decf(newlevel, 4))

     repeat
       if ina[PWR] == 0

          repeat 1

            i2c.WriteLong(i2c#BOOTPIN, EE_DEVICE_ADDR, constant(EE_BASE_ADDR + $0), newlevel) 
          
       newlevel := level.read                                    ' poll encoder
                                       
     until (newlevel <> oldlevel)                                '  until it changes  

 
pub pause(ms) | t

  t := cnt
  repeat ms
    waitcnt(t += MS_001)
    

dat     ' keypad translation table

table   byte  "1", "2", "3", "S"
        byte  "4", "5", "6", "R"
        byte  "7", "8", "9", "E"
        byte  "N", "0", "P", "X"

' Keypad layout
'
' 1  2  3  Start
' 4  5  6  Prog
' 7  8  9  Set
' -  0  +  Stop 

935 x 562 - 15K
1024 x 172 - 34K
1024 x 176 - 27K
1024 x 172 - 33K
1024 x 176 - 30K

Comments

  • Don MDon M Posts: 1,653
    edited 2011-06-28 13:46
    Well I tried inserting "abort" right after the EEPROM write and that seemed to do the trick.
        repeat
           if ina[PWR] == 0
    
              repeat 1
    
                i2c.WriteLong(i2c#BOOTPIN, EE_DEVICE_ADDR, constant(EE_BASE_ADDR + $0), newlevel) 
                abort
           newlevel := level.read                                    ' poll encoder
                                           
         until (newlevel <> oldlevel)                                '  until it changes  
    
    

    Is that the proper use of that command?
  • Mike GreenMike Green Posts: 23,101
    edited 2011-06-28 15:37
    The REPEAT 1 really doesn't do anything useful for you. You might as well leave it out and the extra indenting on the i2c.writelong. What you want is for the Propeller to stop doing anything once the power failure has occurred and the data has been saved to EEPROM. An ABORT will do that for the current cog as long as you're not using the "\" operator to catch aborts (which you're not doing). Better is to do "COGSTOP(COGID)" which ends up doing the same thing as an ABORT. You could also do:
    REPEAT
       WAITCNT( CLKFREQ + CNT )
    
    The REPEAT repeats the indented stuff forever and that consists of just a low power wait for 1 second. You could leave out the WAITCNT and just use the REPEAT. Without a count, it will repeat forever.
  • Don MDon M Posts: 1,653
    edited 2011-06-28 20:23
    Thanks Mike. I'll make some of your suggested changes and just leave the abort command in as long as it works.
  • ddstarkeyddstarkey Posts: 6
    edited 2011-07-08 11:01
    Same problem, my solution.

    I posted a PASM object (http://obex.parallax.com/objects/765/) that monitors a 60-Hz signal from a power transformer and clears a variable to 0 when the power fails.
    It does this within 1/120 of a second and combined with a large filter capacitor on the Propeller's power supply, gives plenty of time to save variables to EEPROM.

    Good Luck,
    Don
  • EmptyBitEmptyBit Posts: 72
    edited 2011-07-10 15:09
    Don M,

    Excellent and timely post with real world visual time base of power loss vs. eeprom writes times.

    From my initial testing and discovering feedback through the PPB regulators, I am somewhat surprised to see your divider sense line at P20 drop to 0v with no blocking diode to the left node at the 1000uF cap.

    In the near future I will be testing circuits using supercaps, backup battery and/or auto powerdown with latching mosfet methods.

    I just purchased a Tektronix 2022C to R&D my options with save on detected power loss.

    One question as to your regulator circuit and my findings I never did get a response on in my thread.

    Will feedback through the PPB regulators, once power drops - eventually compromise these regulators?


    Possible solution: Schottky diodes to block feedback.

    Without schottky diodes to block feedback, I have read it may shorten both regulators usable life. I also question how much of the cap stored 3.3v these regulators would consume in reverse feedback; thereby reducing the efficiency of last gasp reserve. There are many threads here that discuss cap storage in R/C hold up time verses load current. Just not many proven circuit examples used long term.

    This blocking solution brings in another issue with a schottky diodes voltage drop eating .3v (50%) of the potential headroom.
    One option here is to swap out the regulators for an LM317(adjustable) in order to compensate the diode drop and return the Vdd back to 3.3-3.6v in the storage cap for more save time.
    I have also read suggestions to lift the reg’s ground legs and insert another diode there to cancel out the diode drop on the output. I just do not look forward to removing the proto board reg’s or cutting traces on the board.

    I have a Newark order coming next week with supercaps, mosfets and schottky’s. This is my last hurdle for this prototype project.



    I hope to prove my circuit with my own data like what you have posted here. That sure takes the mystery out of the unknowns.


    Much appreciated!

    $0
Sign In or Register to comment.