Hello,
I am working with an SSD1306 screen that uses the U8Glib library. My goal is to have it show battery level as shown in the picture.
To measure voltage, I am using the internal voltage reference A.K.A "Arduino's Secret Voltage Meter."
Can somebody give me an advice to merge this two parts of my code together, in order to display battery life using the bars. I know that I have to use a conditional statement to set a value for each voltage range, then a switch case to set the display. But, I don't quite know where to begin to do so and could really use a hint.
I plan on using four AA batteries. Two pairs connected in parallel and then in series to get 3.0V. Then a boost converter will squeeze the life out of them.
My Arduino Uno is currently running at 5V and 16MHz, but I plan on lowering it to 3.0V @ 8MHz to save power and build a PCB.
Any advice is welcomed!
Thanks,
Angel
Screen Code:
#include "U8glib.h"
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK); // Display which does not send ACK
void draw(void) {
// graphic commands to redraw the complete screen should be placed here
u8g.setFont(u8g_font_unifont);
//u8g.setFont(u8g_font_osb21);
//This Part Dsiplays Battery Indicator
u8g.drawFrame(14, 5, 22, 10); //Frame for battery sign
u8g.drawFrame(17, 1, 5, 5); //Terminal for battery
u8g.drawFrame(28, 1, 5, 5); //Terminal for battery
u8g.drawFrame(10, 16, 30, 46); //Frame for battery indicator
u8g.drawLine(19, 7, 19, 11); //Vertical line for positive battery sign
u8g.drawLine(17, 9, 21, 9); //Horizontal line for positive battery sign
u8g.drawLine(27, 9, 31, 9);
u8g.drawBox(14, 20, 22, 8);
u8g.drawBox(14, 30, 22, 8);
u8g.drawBox(14, 40, 22, 8);
u8g.drawBox(14, 50, 22, 8);
//This Part Displays Dispensing Level
u8g.drawFrame(46, 16, 30, 46);
//This Part Displays Chalk Storage Level
u8g.drawFrame(82, 16, 30, 46);
}
void setup(void) {
u8g.getMode() == U8G_MODE_BW;
u8g.setColorIndex(1); // pixel on
}
void loop(void) {
// picture loop
u8g.firstPage();
do {
draw();
} while ( u8g.nextPage() );
// rebuild the picture after some delay
delay(50);
}
Measuring Voltage Using Internal Reference:
float iREF = 1.24; //internal reference cal factor
void setup() {
// put your setup code here, to run once:
analogReference(EXTERNAL);
//burn some ADC readings after reference change
for (int i = 0; i < 8; i++) analogRead(A0);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
delay(3000);
Serial.print("Measured battery voltage is: ");
Serial.println(fReadVcc());
Serial.println();
}
//This function uses the known internal reference value of the 328p (~1.1V) to calculate the VCC value which comes from a battery
//This was leveraged from a great tutorial found at https://code.google.com/p/tinkerit/wiki/SecretVoltmeter?pageId=110412607001051797704
float fReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(3); //delay for 3 milliseconds
ADCSRA |= _BV(ADSC); // Start ADC conversion
while (bit_is_set(ADCSRA, ADSC)); //wait until conversion is complete
int result = ADCL; //get first half of result
result |= ADCH << 8; //get rest of the result
float batVolt = (iREF / result) * 1024; //Use the known iRef to calculate battery voltage
return batVolt;
}