Electronic – arduino – Detect Arduino power failure and save data

arduinopowervoltage divider

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.

Best Answer

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.