5
\$\begingroup\$

Prologue

On an Arduino Mega, I need to save data into the EEPROM (about 40 bytes) in case of power failure. The data is constantly changing (steppers position, speed, etc), but since the EEPROM has limited write cycles, the data needs to be written only when a power drop is detected, so periodic writes in the main loop or on a timer are out of the question.

The setup

Arduino inputs:

  • A lot of buttons / microswitches (each with 10K pulldown resistors)
  • IR receiver

Arduino outputs:

  • 2 stepper driver outputs
  • 3 LEDs
  • serial connection to graphic LCD (powered externally)

Other components powered from the same 12V PSU rail (besides the Arduino board):

  • 6V (~220mA max) graphic LCD (fed through a L7806 regulator)
  • 12V (0.65A) 120mm fan

Possible solution

I don't know too much about electronics, I've just learned about what a voltage divider is, so please bare with what I'm about to say.

Normally, a supercapacitor would be needed as a backup for when the power goes down, but I'm thinking it's not needed as the PSU already has them and it takes 1-2 seconds to discharge when swithed off, even with a 12V fan running off of the PSU. We'll assume the maximum 2 seconds scenario, implying the PSU being switched on for at least a few minutes for the caps to be fully charged.

As a voltage drop detection mechanism, I thought of a voltage divider with 2 resistors, in parallel with the Arduino VIN supply (meaning totally separate, non-dependent circuit), with the divider output going to an Arduino analog pin. The input from the PSU being Vin=12V, I would choose the 2 resistors values R1=10K and R2=5K. That would mean a max 0.4mA for the pin and would be well below the recommended 20mA sinking current an Arduino pin supports. A 1:2 ratio for the resistors would then give a Vin/Vout=1/3 ratio, and that means a Vout=4V maximum going to the analog pin. Reading the pin value, with the Arduino voltage reference to the default 5V, the "normal" value would be around 819 (on the 0-1023 analog scale).

The accepted voltage for the VIN pin on the Arduino Mega is 7-12V as recommended in the specs, but, as reading on the forums, the actual minimum voltage for the Mega VIN is around 6V. The Mega has a lower dropout 5V voltage regulator than other boards, with the dropout of around 1V. In case of power failure, the voltage from the PSU would drop slowly (in 1-2 seconds) from 12V to 6V when the Arduino wouldn't be supplied and it would shutdown. Divider Vout = 6V / 3 = 2V, so I should save the data when the analog value read would be somewhere between 819 and 410, but enough above 410 so that there would be plenty time for saving about 40 bytes of data (EEPROM writes are slow - I should look into the exact timings, but I think the full write wouldn't take more than 100ms).

[UPDATE] It takes 3.3ms/write. But to increase EEPROM life-span, I don't write the full chunk at once but do byte-by-byte updates and write only if the byte value differs, so it would be max ~130ms for writing 40 bytes (if all 40 actually changed), plus whatever time is needed for reading them.

Also, to make things by the book and fast enough, instead of constantly polling the analog pin (as analog readings are slow and an overhead), the analog read should be interrupt driven, on a CHANGE trigger.

Questions

  1. Are the above solution and statements correct? Are the resistor values for the divider chosen correctly? Do you have any suggestions?
  2. Would powering the Arduino by USB a) along with VIN b) alone (USB only) interfere with the voltage dropout reading on the analog pin?
  3. An even better solution would be a FALLING triggered interrupt (HIGH to LOW), but the external hardware should include something more besides a voltage divider. A diode maybe? What kind / parameters?

.

Note: I know I should have powered the Arduino through the power connector and not the VIN pin, as the connector features reverse current protection diodes, but for this project I built a shield holding external connectors and it made sense to also feed the board using the VIN pin. I took care not to reverse the input while testing and the power connector is one way only so as to avoid eventual mistakes.

UPDATE

Thank you for all the suggestions, but I would still like to go the voltage divider way. I particularly like this approach because it's non-intrusive - basically it's just another sensor on the Arduino, powered from the same supply, but not interfering / getting between the Arduino and power supply.

\$\endgroup\$
  • \$\begingroup\$ Have you considered using an external regulator with a "PGOOD" output so that you can know when the power has failed? \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 20 '14 at 0:50
  • \$\begingroup\$ @IgnacioVazquez-Abrams I'm not sure I understand, what should the regulator be powered from? Can you detail? \$\endgroup\$ – binar Mar 20 '14 at 0:56
  • \$\begingroup\$ It would be powered from your 12V PSU and feed into the 5V connection on the Arduino. \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 20 '14 at 0:58
  • \$\begingroup\$ You mean power the board from 2 different connectors (5V pin and what I use now, the VIN 12V) ? Or use it on an input pin to "sense" the voltage? I was thinking a voltage divider is proper in this case because I expect the input power to be fairly constant (12V), the Arduino only needs 5V, so when the 12V drops to a lower value, the Arduino would still be working, but the Vout of the divider will drop and I can sense that. In contrast, a regulator provides a steady 5V no matter its input as long as it's above ~6v, so I couldn't sense that until it would be too late. \$\endgroup\$ – binar Mar 20 '14 at 1:08
  • \$\begingroup\$ @IgnacioVazquez-Abrams A suitable regulator would be one with a big voltage drop, say at over 11V input it would output 5V (and feed that to an analog input), and below 11V to decrease the output, but does such a regulator even exist? \$\endgroup\$ – binar Mar 20 '14 at 9:46
4
\$\begingroup\$

A simple battery backup IC will do what you want.

enter image description here

Essentially, a comparator samples two voltage inputs, the main power, and a backup power supply (Batteries). Based on that, two cascading inverters paired with two p-channel fets power the circuit at Vo, while two n-channel fets are used as open-drain outputs. Pull them up with a resistor, and they are the perfect interrupt source for your arduino.

The specific one shown is the ICL7673, but it's maximum current is 38mA. It's designed for rtc and ram with a coincell, but an extra pair of P-channels can be used to increase the current.

There are other battery backup or power switches which will do higher current builtin.

\$\endgroup\$
  • \$\begingroup\$ If I wasn't on dialup, er I mean crappy tmobile slow internet, I would have found a better one. \$\endgroup\$ – Passerby Mar 20 '14 at 3:19
  • \$\begingroup\$ Thanks, I'll look more into battery backup ICs. Should the IC be connected in parallel with the mains power for the Arduino or should it be the only power input to the board? Because I don't mind the 38mA limit as long as it's just for saving data while on backup battery power. It might also be enough for normal usage at this moment, but don't want to limit future addons to the project. \$\endgroup\$ – binar Mar 20 '14 at 7:50
  • \$\begingroup\$ Also, how do these types of ICs work? I suspect that because it's called a "battery backup", in case of power failure the Arduino will run off the battery until it completely drains? If that's the case, because I expect the system to be switched off while not used, I'll have to put a cutoff switch for the backup IC output (maybe change the DPST microswitch that currently powers on the PSU to a DPDT). \$\endgroup\$ – binar Mar 20 '14 at 7:55
  • \$\begingroup\$ And it would also mean that after detecting a switch to battery power, save the data and put the Arduino in a low-power mode / infinite loop in order to conserve the backup battery. \$\endgroup\$ – binar Mar 20 '14 at 8:34
  • 1
    \$\begingroup\$ You can probably get away with using a large capacitor instead of a battery with this, and just busy wait after writing until it runs out. \$\endgroup\$ – Ignacio Vazquez-Abrams Mar 20 '14 at 8:36
1
\$\begingroup\$

adding two diodes couple resistors and a electrolytic cap is all takes. Assume a wall-wart power cube. Take Positive to the input VCC (9v input) on the board through a diode (typ a 1n4002) Place a cap across the input connector at the board. This should be 1000-2000uF / 16V. Then from the positive of the wall-wart attach another diode (1n4002). This diode feeds a voltage divider made of two resistors such that the divide provides 3-4 volts max to a analog input. The voltage at the analog input will drop well before the voltage at the input to the board.

  int PowerGood = Digital.read(Ax);  // select analog input
  if (PowerGood = 0){ ShutdownStore();}

void ShutdownStore() // routine to store data and stay put for (x == 0; x

You get the idea.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.