Hi,
i built an energy power meter. It works fine, but I would also like to measure the battery voltage (the plus is wired to A3) in order to know when to charge it. The problem is that the analogRead returns wrong values. I even used A2 wired to the negative of the battery (which of course is the same as GND of the Arduino) to compute a difference, but I still get values like 4716mV when the real value (measured with a multimeter) is 3.95V. Below is a piece of the code.
[...]
display.print("Battery: ");
battery_voltage = map(analogRead(A3) - analogRead(A2), 0, 1023, 0, 5000);
display.print(battery_voltage);
display.println(" mV");
display.print("Reference: ");
ref_voltage = map(analogRead(A2), 0, 1023, 0, 5000);
display.print(ref_voltage);
display.println(" mV");
[...]
I tried changing to A7, doing multiple samples, etc. Nothing worked. Maybe the problem could be the reference voltage? The LiPo battery 3.7V gets stepped up to 5V and then goes to the Arduino NANO.
The schematic is pretty straightforward, as I wired the plus of the battery directly to A3 and the GND is in common with everything.
Here it is the full code.
// Sketch for Arduino NANO
#include <Wire.h>
#include <Adafruit_INA219.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include "SdFat.h"
SdFat SD;
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
Adafruit_INA219 ina219;
unsigned long previousMillis = 0;
byte interval = 10;
bool sd_status = 1;
float max_curr;
float max_load;
float max_pow;
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float energy = 0;
float power_mW = 0;
float res = 0;
int battery_voltage = 0;
int ref_voltage = 0;
File AllFile;
void setup() {
pinMode(A3, INPUT);
pinMode(A2, INPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Accendo il display
ina219.begin(); //Inizio con la calibrazione più sicura
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.println(" POWER METER by JS");
display.println("Calibration: OK!");
display.print("Battery: ");
battery_voltage = map(analogRead(A3) - analogRead(A2), 0, 1023, 0, 5000);
display.print(battery_voltage);
display.println(" mV");
display.print("Reference: ");
ref_voltage = map(analogRead(A2), 0, 1023, 0, 5000);
display.print(ref_voltage);
display.println(" mV");
display.display();
delay(10000);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ina219values();
if (SD.begin(10)) {
sd_status = 1;
AllFile = SD.open("ALL.txt", FILE_WRITE);
if (AllFile) {
AllFile.print(millis());
AllFile.print(",");
AllFile.print(loadvoltage);
AllFile.print(",");
AllFile.println(current_mA);
AllFile.close();
}
} else sd_status = 0;
displaydata();
}
}
void displaydata() { //Stampo tutto sul display 128x64
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print(loadvoltage);
display.print(" V ");
if (current_mA > 1000) {
display.print(current_mA/1000);
display.println(" A");
} else {
display.print(current_mA);
display.println(" mA");
}
if (power_mW > 1000) {
display.print(power_mW/1000);
display.print(" W ");
} else {
display.print(power_mW);
display.print(" mW ");
}
if (res > 1000) { //Stampo la resistenza e la converto così da non occupare troppo schermo
display.print(res/1000);
display.println(" kohm");
} else {
display.print(res);
display.println(" ohm");
}
if (energy > 1000) { //Stampo l'energia e la converto così da non occupare troppo schermo
display.print(energy/1000);
display.print(" Wh ");
} else {
display.print(energy);
display.print(" mWh ");
}
display.print("t: ");
display.print(millis()/1000);
display.println(" s");
display.print(max_curr/1000); //Stampo la massima corrente e potenza
display.print(" A ");
display.print(max_pow/1000);
display.print(" W");
if (sd_status == 0) display.print(" SD!");
else display.print(" SD OK");
display.display();
}
void ina219values() {
if ((current_mA < 500) && (current_mA != 0)) { //Calibrazione costante
if (current_mA < 200) ina219.setCalibration_16V_400mA();
else ina219.setCalibration_32V_1A();
}
else ina219.begin();
shuntvoltage = ina219.getShuntVoltage_mV(); //Ottengo i vari dati da INA219
busvoltage = ina219.getBusVoltage_V();
current_mA = ina219.getCurrent_mA();
loadvoltage = busvoltage + (shuntvoltage / 1000);
res = abs(loadvoltage*1000/current_mA);
power_mW = loadvoltage*current_mA;
energy = energy + loadvoltage * current_mA / 3600;
if (max_curr < current_mA) max_curr = current_mA; //Calcolo massima corrente, tensione e potenza
if (max_load < loadvoltage) max_load = loadvoltage;
if (max_pow < power_mW) max_pow = power_mW;
}