Hello. I am using an ArduinoMega 328 using the 8MHz internal clock powered by an 18650 lithium battery.
I want to monitor swimming pool temperature and levels and am trying to monitor voltage. I am sending these values to a monitorng station via radio (lora) about every hour.
I am using example codes furnished by Nick Gammon which have been modified for my special application.
The various additional components are;
Distance(A02yyuw)
Temperature (DS18B20)
Transmitter Lora Reyax RYLR896
LDO Adustable MCP1727 regulator:
The Arduno is powered directly by the battery while sleeping. When it wakes up, it turns on a MOSFET to enable the components, measure, transmit the values then disable the components before going back to sleep.
All measured values are correct EXCEPT the battery voltage which, from time to time show 4.4V instead of the normal 4.17V value.
I am not able to explain this value and I would be interested in any suggestions. Below is my code.
Thank you
[sleepTest.ino|attachment](upload://eejBfXrCQddZujpzpLyBoHxMj0F.ino) (8.7 KB)
/*
Simple, in-progress library to allow easy reading of current battery (VCC) voltage
so that a timely warning can be given to user that it's time to get new batteries
before these ones expire!
See https://github.com/RalphBacon/Arduino-Battery-Monitor
See https://www.youtube.com/ralphbacon video #160
*/
#include "Arduino.h"
#include "BatteryVoltageReader.h"
void BatteryVoltageReader::begin() {
this->startInternal1V1VoltageReference();
}
void BatteryVoltageReader::startInternal1V1VoltageReference() {
// Internal 1.1V reference, works instantly (compare to below)
ADMUX = bit (REFS0) | bit(REFS1);
// Above is the equivalent of:
/*
// Request INTERNAL 1v1 reference voltage (for ATMega328P)
analogReference (INTERNAL);
// That request is not honoured until we read the analog pin
// so force voltage reference to be turned on
analogRead (A0);
*/
}
uint16_t BatteryVoltageReader::readVCC() {
//Partly adapted from http://www.gammon.com.au/adc (Nick Gammon)
// Adjust this value to your boards specific internal BandGap voltage x1000
//const long InternalReferenceVoltage = 1095L; // Here I measured 1.095 volts on pin 21
const long InternalReferenceVoltage = 1067L; // Bill I measured 1.067 volts on pin 21
//Taken from https://forum.arduino.cc/index.php?topic=331178.msg2285210#msg2285210
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
// For mega boards
// REFS1 REFS0 --> 0 1, AVcc internal ref. -Selects AVcc reference
// MUX4 MUX3 MUX2 MUX1 MUX0 --> 11110 1.1V (VBG) -Selects channel 30, bandgap voltage, to measure
ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR)| (0<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
#else
// For 168/328 boards
// REFS1 REFS0 --> 0 1, AVcc internal ref. -Selects AVcc external reference
// MUX3 MUX2 MUX1 MUX0 --> 1110 1.1V (VBG) -Selects channel 14, bandgap voltage, to measure
ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
#endif
// Let mux settle a little to get a more stable A/D conversion
delay(50);
// Start a conversion
ADCSRA |= _BV(ADSC);
// Wait for conversion to complete
while (((ADCSRA & (1 << ADSC)) != 0)) {
;
}
// Scale the value - calculates for straight line value. +5L gives us the fractional rounding.
unsigned int results = (((InternalReferenceVoltage * 1024L) / ADC) + 5L) / 10L;
return results;
}#ifndef BatteryVoltageReader_h_
#define BatteryVoltageReader_h_
#include "Arduino.h"
class BatteryVoltageReader {
public:
void begin();
uint16_t readVCC();
private:
void startInternal1V1VoltageReference();
protected:
};
#endif

