Just topped off my build with a battery monitor. I had a couple of 'free' Analog pins. Since I'm 'minimalist'-ing this BitX, it has only 16 characters
on the LCD, so, every character counts. I 'preciate those who are driving a 20x2 or 16x2 LCD - you have real estate to show '12.5' or even '12.5V'.
I chose to use a single character and rely on 'Custom Characters', 8 of which can be added using the LiquidCrystal library.
My 'voltage divider' starts with 560K / 180K resistors, with an additional 0.01uf (10nf) across the 180K, just to increase consistency and slow any temporary changes.
This gives some headroom for the ADC, which shouldn't be run > 5V. This divider translates to an input voltage of around 20.5V MAX, which shouldn't happen (at
least on the board - this would, necessarily, measure only the 'whole board', not the PA - if that's driven with 25V).
For Gel Battery Values 'above 13.0V' - the very FIRST Icon is 'plugged in'. I've not seen many gel batteries above 13.0V unless they've JUST come off charge.
So, that Icon can also be used to show 'eh, you're on a power supply, 13.8V'...
For the custom characters - I rely on a tool on my website:?
What I came up with is (and you can design your own):
int ?batterySense[8] = {647,632,622,612,602,597,592,587}; ? ? // ADC values which correspond to a voltage divider: ? V+ - 560K - (ADC Pin) 180K - GND
// ?These correspond to: ?13.0, 12.7, 12.5, 12.3, 12.1, 12.0, 11.9, 11.8 - but last number is not used; if we're not 'above the other 7 numbers' - empty!
// Note that ADC Values (Analog Pin read) are based upon the 560k/180k ratio, but 'your mileage may vary' (if, for instance, your 560k is 560,100 or 559,050, etc...)
// So, for testing for 'full battery', ehhhh, you might have 12.73 or 12.68 as your 'test for greater than' result. Experimentation can make this accurate for a particular?
// divider resistor pair, but... it's just meant to be an approximation anyway. It's sufficient that the general RANGE of values is consistent.
byte battery[][8] = {
? ? ?{ B01010, B01010, B11111, B10001, B10001, B10001, B01110, B00100 } // Plugged In ? ?> 13.0 - usually only shows when 'charging' or on a bench power supply.
? ? ,{ B01110, B11111, B11111, B11111, B11111, B11111, B11111, B11111 } // Full Battery ?> 12.7 - (values are approximate, based upon the divider accuracy.)
? ? ,{ B01110, B11011, B11111, B11111, B11111, B11111, B11111, B11111 } // ? ? ? ? ? ? ? > 12.5
? ? ,{ B01110, B11011, B10001, B11111, B11111, B11111, B11111, B11111 } // ? ? ? ? ? ? ? > 12.3
? ? ,{ B01110, B11011, B10001, B10001, B11111, B11111, B11111, B11111 } // ? ? ? ? ? ? ? > 12.1
? ? ,{ B01110, B11011, B10001, B10001, B10001, B11111, B11111, B11111 } // ? ? ? ? ? ? ? > 12.0
? ? ,{ B01110, B11011, B10001, B10001, B10001, B10001, B11111, B11111 } // ? ? ? ? ? ? ? > 11.9 - (you're runnin' on vapors here...)
? ? ,{ B01110, B11011, B10001, B10001, B10001, B10001, B10001, B11111 } // EMPTY BATTERY - recharge or risk damaging your battery. References I've seen put this at about 11.9V.
};
#define ?BatteryCheckSeconds 5 * 1000L ? ? ? ? ? ? ? ? ?// Check the battery every 'n' Seconds. Here 'n' is every 5 seconds.
unsigned long lastBatteryCheck = 0L;????????????????????? ? // Time (in millis()) of the LAST battery check... this (and millis()) is a LONG.
In the INIT:
? // Setup the Battery Monitor...
? for (int i=0; i < 8; i++){
? ? lcd.createChar(i, battery[i]); ? ?// Create the Custom Icons.
? }
? display_battery();
? lastBatteryCheck = millis(); ? ? ? ?// Mark the time, so we don't swamp CPU or cause unnecessary RF noise doing this constantly
In the LOOP:
? // You don't look too busy... Check the Battery... at least every (n) seconds.
? if (millis() - lastBatteryCheck > BatteryCheckSeconds)
? ? display_battery();
Finally, the battery checkin' itself (I used A0, but - whatever Analog pin you might have available):
void display_battery() {
? // Read Battery Sense Pin
? int sensorValue = analogRead(A0);
? // Find a suitable Icon...
? lcd.setCursor(0, 0); ? ? ? ? ? ? ? ? ? ? ? ? ?// *** Mine's on the far left; put it where'd you like, or however you'd show it..
? boolean notfound = true;
? for (int i=0; i < 7; i++){
? ? ? if (sensorValue >= batterySense[i]) {
? ? ? ? ? lcd.write(i);
? ? ? ? ? notfound = false;
? ? ? ? ? i = 7;
? ? ? }
? }
? if (notfound) ????? ? // We never found a 'sensevalue' above approximately 11.9...
? ? lcd.write(7); ? ? ? // ...so, we must be below < 11.9V; use our Last Icon 'Empty Battery'
? // mark our most recent Battery Check Time
? lastBatteryCheck = millis();
}
Thought I'd share this; I enjoyed writing the code & putting together the custom LCD Icons. Hope someone finds it useful.
I'll update my 'album' with an updated LCD photo.
Mike Yancey, KM5Z
Dallas, Texas