/* 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>