/* voltage meter sampling and average calculation
(based https://www.instructables.com/Arduino-Precise-Accurate-Volt-Meter-0-90V-DC/)
mod Steve Barth 2022
*/
#include <Arduino.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);// (rotation, [reset])
float voltage = 0; // used to store voltage value
float Radjust = 0.043459459; //Voltage divider factor ( R2 / R1+R2 )
float vbat = 0; //final voltage after calcs- voltage of the battery
float Vref = 4.346; //Voltage reference - real value measured. Nominal value 4.096v
const int numReadings = 5; // number of reading samples - increase for more smoothing. Decrease for faster reading.
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
unsigned long total = 0; // the running total
int average = 0;
//variables for refreshing the screen without using delay
unsigned long previousMillis = 0; // will store last time the screen was updated
// constants won't change:
const long interval = 100; // interval at which to refresh the screen (milliseconds)
void setup(void) {
analogReference(EXTERNAL); // use AREF for reference voltage 4.096. My reference real voltage is 4.113v
u8g2.begin();
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}
void loop(void) {
unsigned long currentMillis = millis();
//voltage calculations with smoothing average
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(A0);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
// calculate the average:
average = (total / numReadings);
voltage = average * (Vref / 1023.0); //4.113 is the Vref
vbat = voltage / Radjust;
// Setting the delay for the screen refresh using Millis
if (currentMillis - previousMillis >= interval) {
// save the last time the screen was updated
previousMillis = currentMillis;
u8g2.clearBuffer(); // clear the internal menory
//Pack Voltage display
u8g2.setFont(u8g2_font_fub20_tr); // 20px font
u8g2.setCursor (0, 20);
u8g2.print(vbat, 2);
u8g2.setFont(u8g2_font_8x13B_mr); // 10 px font
u8g2.setCursor (88, 20);
u8g2.print("Volts");
//u8g2.setCursor (1, 40);
//u8g2.print("CanadianWinters'");
u8g2.setCursor (1, 60);
u8g2.print("Precise Voltage");
}
u8g2.sendBuffer(); // transfer internal memory to the display
delay(1);
}//<br>