// WORK IN PROGRESS ONLY - PROBABLY WON'T WORK
// Very first attempt at a backup system that "does the job"
// Peter Scargill 2017 - https://tech.scargill.net
-// So this powers up with an SSD1306 display, showing the
+// So this powers up with an SSD1306 display, showing the
// battery voltage (needs dividers - I used 10k and 2k2) to an
// analog in - voltage calc routine needs tweaking
// averages voltage to avoid spikes and save hardware filtering
// Starts up - if voltage above upper threshhold for a while turns
-// output bit on - that controls a P-channel mosfet on output
+// output bit on - that controls a P-channel mosfet on output
// of booster - power board from booster - OR power board from battery
// and control booster chip directly
// There is a warning bit, normally low - to warn micro of impending
// Then turns back on when battery is up to it. BIG hysteresis between
// shutdown voltage and wakeup voltage
+ uint8_t warningTimeout;
// Device address for the SSD1306 display
//------------------------------------------------------------------------------
analogReference(INTERNAL);
- if (myVars.check != 0x52d2)
+ if (eeSave.check != 0x52d2)
- myVars.highV = SWITCHON;
- myVars.lowV = SWITCHOFF;
+ eeSave.highV = SWITCHON;
+ eeSave.lowV = SWITCHOFF;
+ eeSave.startTimeout = 5;
+ eeSave.goodTimeout = 10;
+ eeSave.warningTimeout = 20;
+ eeSave.offTimeout = 20;
oled.begin(&Adafruit128x64, I2C_ADDRESS);
my100millis = millis() + 1000;
+ stateCounter = eeSave.startTimeout;
//------------------------------------------------------------------------------
if (my100millis <= millis()) // 100ms for key check
+ case 1 : if (eeSave.highV < 4.3) eeSave.highV += 0.1; break;
+ case 2 : if (eeSave.lowV < 4.2) eeSave.lowV += 0.1; break;
+ case 3 : eeSave.startTimeout++; break;
+ case 4 : eeSave.goodTimeout++; break;
+ case 5 : eeSave.warningTimeout++; break;
+ case 6 : eeSave.offTimeout++; break;
+ case 1 : if (eeSave.highV > 2.3) eeSave.highV -= 0.1; break;
+ case 2 : if (eeSave.lowV > 2.2) eeSave.lowV -= 0.1; break;
+ case 3 : eeSave.startTimeout--; break;
+ case 4 : eeSave.goodTimeout--; break;
+ case 5 : eeSave.warningTimeout--; break;
+ case 6 : eeSave.offTimeout--; break;
- if (myVars.lowV < 2.0) myVars.lowV = 2.0;
- if (myVars.highV > 4.2) myVars.highV = 4.2;
- if (myVars.highV <= myVars.lowV) myVars.highV = myVars.lowV + 0.1;
- if (myVars.lowV >= myVars.highV) myVars.lowV = myVars.highV - 0.1;
+ if (eeSave.highV <= eeSave.lowV) eeSave.highV = eeSave.lowV + 0.1;
+ if (eeSave.lowV >= eeSave.highV) eeSave.lowV = eeSave.highV - 0.1;
case 0: if (updated == 0)
case 1: if (updated == 0)
- LcdP("SET: High V=%d.%d ", int(myVars.highV), ((int(myVars.highV * 100)) % 100) / 10); oled.clearToEOL();
+ LcdP("SET: High V=%d.%d ", int(eeSave.highV), ((int(eeSave.highV * 100)) % 100) / 10); oled.clearToEOL();
case 2: if (updated == 0)
- LcdP("SET: Low V=%d.%d ", int(myVars.lowV), ((int(myVars.lowV * 100)) % 100) / 10); oled.clearToEOL();
+ LcdP("SET: Low V=%d.%d ", int(eeSave.lowV), ((int(eeSave.lowV * 100)) % 100) / 10); oled.clearToEOL();
case 3: if (updated == 0)
- LcdP("Version 1.01"); oled.clearToEOL();
+ LcdP("SET: Start %d secs",eeSave.startTimeout); oled.clearToEOL();
+ case 4: if (updated == 0)
+ LcdP("SET: Good %d secs",eeSave.goodTimeout); oled.clearToEOL();
+ case 5: if (updated == 0)
+ LcdP("SET: Warn %d secs",eeSave.warningTimeout); oled.clearToEOL();
+ case 6: if (updated == 0)
+ LcdP("SET: Off %d secs",eeSave.offTimeout); oled.clearToEOL();
+ case 7: if (updated == 0)
+ LcdP(VER); oled.clearToEOL();
- case 4: updated = 0; instate = 0; break;
+ case 8: updated = 0; instate = 0; break;
case POWERUP_STATE : // powered up everything off
- gotoXY(0, 0); LcdP("Starting up"); oled.clearToEOL();
+ if (stateCounter == eeSave.startTimeout) { gotoXY(0, 0); LcdP("Starting up"); oled.clearToEOL(); }
gotoXY(0, 2); LcdP("Battery: "); showBattery();
+ gotoXY(0, 3); LcdP("Count: %03d",stateCounter); oled.clearToEOL();
digitalWrite(WARNING, WARNINGOFF); // no warning
digitalWrite(POWER, POWEROFF);
- if (vol > myVars.highV)
+ if (vol > eeSave.highV)
- if (++stateCounter > 3) {
+ if (stateCounter == 0) {
+ stateCounter = eeSave.goodTimeout;
- if (++startCounter > 10) state = OFF_STATE;
+ stateCounter = eeSave.offTimeout;
case GOOD_STATE : // battery is above upper threshold
- if (stateCounter == 0) {
- LcdP("** Pi Power v0.1 **");
+ if (stateCounter == eeSave.goodTimeout) { gotoXY(0, 0); LcdP("** Pi Power %s **",VER); oled.clearToEOL(); }
gotoXY(0, 1); LcdP("Ok. Battery: "); showBattery();
- gotoXY(0, 2); LcdP("High: %d.%dv Low: %d.%dv", int(myVars.highV), ((int(myVars.highV * 100)) % 100) / 10, int(myVars.lowV), ((int(myVars.lowV * 100)) % 100) / 10); oled.clearToEOL();
+ gotoXY(0, 2); LcdP("High: %d.%dv Low: %d.%dv", int(eeSave.highV), ((int(eeSave.highV * 100)) % 100) / 10, int(eeSave.lowV), ((int(eeSave.lowV * 100)) % 100) / 10); oled.clearToEOL();
LcdP("On: %04ldd %02ld:%02ld:%02ld", upSecs / 86400, (upSecs / 3600) % 24, (upSecs % 3600) / 60, upSecs % 60); oled.clearToEOL();
LcdP("Off: %04ldd %02ld:%02ld:%02ld", downSecs / 86400, (downSecs / 3600) % 24 , (downSecs % 3600) / 60, downSecs % 60); oled.clearToEOL();
digitalWrite(WARNING, WARNINGOFF); // no warning
digitalWrite(POWER, POWERON);
- if (++stateCounter > 2) {
+ gotoXY(0, 3); LcdP("Count: %03d",stateCounter); oled.clearToEOL();
+ if (stateCounter == 0) {
+ stateCounter = eeSave.warningTimeout;
- } else stateCounter = 1;
+ } else stateCounter = eeSave.goodTimeout;
case TIMEOUT_STATE : // battery has dropped below upper threshold - ALWAYS timeout to OFF_STATE
- gotoXY(0, 1); LcdP("Timing out. B: "); showBattery();
+ gotoXY(0, 2); LcdP("Timing out. B: "); showBattery();
+ gotoXY(0, 3); LcdP("Count: %03d",stateCounter); oled.clearToEOL();
digitalWrite(WARNING, WARNINGON); // no warning
digitalWrite(POWER, POWERON);
- if (++stateCounter > 10) {
+ if (stateCounter == 0 ) {
+ stateCounter=eeSave.offTimeout;
case OFF_STATE : // everything off
- if (stateCounter == 0) oled.clear();
- gotoXY(0, 1); LcdP("Off: "); showBattery();
+ if (stateCounter == eeSave.offTimeout) oled.clear();
+ gotoXY(0, 2); LcdP("Off: "); showBattery();
digitalWrite(WARNING, WARNINGOFF); // no warning
digitalWrite(POWER, POWEROFF);
- if (vol > myVars.highV)
+ if (vol > eeSave.highV)
- if (++stateCounter > 5) {
+ gotoXY(0, 3); LcdP("Count: %03d",stateCounter); oled.clearToEOL();
+ if (stateCounter == 0) {
+ stateCounter = eeSave.goodTimeout;
- } else stateCounter = 1; // avoid clearscreen
+ stateCounter = eeSave.offTimeout; // avoid clearscreen
+ gotoXY(0, 3); oled.clearToEOL();