Measuring battery level with a voltage divider and no regulator

I am trying to measure the battery level voltage as maniacbug did but I always get value = 324 for 2.58V measured with a multimeter. Can someone help ?

The equation is vout = (value * 3.44) / 1024.0; and vin = vout / (R2/(R1+R2)); but vin appears to be around 2.98V. The voltages measured in the voltage divider are 1.75/0.81.

I am creating a wireless node with an nRF24L01+ and a battery level meter, using 2AA batteries (2.4-3.0Volts). I am also testing it with two cables from an arduino Uno board connected on 3V3 pin (3.3Volts). The chip doesn't have an external oscillator - I am using the 8Mhz bootloader provided by official arduino website.

I am also measuring the AREF pin which is not connected to anything, with a multimeter by hand and it shows 3.3 when connected to the 3V3 source and analog Reference set to DEFAULT and 2.7Volts when connected to INTERNAL. I've also used 5 different ATMega328s, some of them brand new (in case I burnt something). Shouldn't it be 1.1 ?

I am using the exact same schematic except for the R's which are 1KOhm and 470Ohm.

please help!

The voltage on analogue pin should be 470/1470 (~1/3) of the battery voltage.

And if the code has analogReference(INTERNAL) in the setup, then the voltage on the Aref pin should be ~1.1volt.

Seems your code has a bug.
Please post it inside code tags.
Leo..

it's a bit long and I thought I may confuse people.

I am reading the analog value with

payload.batt = analogRead(A2);

and printing it on an OLED. Please consider everything working 100% except the "batt." reading.

Client

#include <dht11.h>
#include "RF24Network.h"
#include "RF24.h"
#include <SPI.h>
#include "printf.h"
#include <JeeLib.h>

//////////////////////////////////////
// Create the structures for data
//////////////////////////////////////
struct data_to_send {
  unsigned node;
  unsigned temp;
  unsigned humi;
  unsigned batt;
  unsigned door;
  unsigned pir;
  unsigned long hkey;
};

struct data_received {
  unsigned long hkey = 0;
};

//////////////////////////////////////
// Setup nRF24L01+ module
//////////////////////////////////////
RF24 radio(8,7);
RF24Network rf24Net(radio);
const uint64_t this_node =  02; // node A
const uint64_t other_node = 00; // base

//////////////////////////////////////
// Setup the rest of it
//////////////////////////////////////

const int led_A_Pin = 6;

unsigned long currentTime = 0;
unsigned long startTime   = 0;
bool runOnce = true;

ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup the watchdog

//////////////////////////////////////
// setup
//////////////////////////////////////
void setup(void) {

  // Initialize interfaces
  printf_begin();
  Serial.begin(9600);
  Serial.print(F("Starting interfaces..."));
  SPI.begin();
  radio.begin();
  Serial.print(F("complete]\n"));
  rf24Net.begin(90, this_node);
  radio.setDataRate(RF24_250KBPS);
  radio.printDetails();
  analogReference(INTERNAL);

  // initialize pins
  pinMode(led_A_Pin, OUTPUT);

}

//////////////////////////////////////
// loop
//////////////////////////////////////
uint32_t txTimer = 0;

void loop(void)
{
    digitalWrite(led_A_Pin, HIGH);
    delay(200);
    digitalWrite(led_A_Pin, LOW);
    delay(200);
    digitalWrite(led_A_Pin, HIGH);
    
    currentTime = millis();

    if (currentTime - startTime <= 1000) {
      Serial.println(currentTime - startTime);
    }
    else {
       digitalWrite(led_A_Pin, LOW);
    }
  
  rf24Net.update();

  if (millis() - txTimer > 1000) {
    data_to_send payload;
    payload.node  = 02;
    payload.temp  = 11;
    payload.humi  = 11;
    
    payload.batt = analogRead(A2);
    payload.door  = 0;
    payload.pir   = 0;
    payload.hkey  = random(10000000, 99999999);


    // starts counting
    unsigned long elapsed = 0;
    unsigned long start = millis();
    Serial.println(payload.hkey);

    digitalWrite(led_A_Pin, HIGH);
    delay(100);
    digitalWrite(led_A_Pin, LOW);
    delay(100);
    digitalWrite(led_A_Pin, HIGH);
    delay(100);
    digitalWrite(led_A_Pin, LOW);
    delay(100);

    // sends packet
    RF24NetworkHeader header(other_node);

    Serial.println("Sending data to base every 30 sec.");
    txTimer = millis();
    bool ok = rf24Net.write( header, &payload, sizeof(payload) );
    if (ok) {
      unsigned long finish = millis();
      elapsed = finish - start;
      Serial.println("ok.");
      Serial.print(elapsed);
      Serial.print("ms\n");
      rf24Net.update();
    }
    else {
      Serial.println("failed.");
    }
  }

  while ( rf24Net.available() )
  {
    Serial.println("Received packet");
    RF24NetworkHeader header2;
    data_received confirm;
    rf24Net.read(header2, &confirm, sizeof(confirm));
    Serial.println(confirm.hkey);
    Serial.println("------------------------------");
    
    Serial.println(F("Going to sleep..."));
    delay(100);
    radio.powerDown();
    Sleepy::loseSomeTime(2000);
    radio.powerUp();
    Serial.println(F("Woke up!"));
  }
}

Base

#include "U8glib.h"
#include "RF24Network.h"
#include "RF24.h"
#include <SPI.h>
#include "printf.h"

//////////////////////////////////////
// Create the structures for data
//////////////////////////////////////
struct data_received {
  unsigned node;
  unsigned temp;
  unsigned humi;
  unsigned batt;
  unsigned door;
  unsigned pir;
  unsigned long hkey;
};

struct data_to_send {
  unsigned long hkey = 0;
}confirm;

unsigned long finish = 0;
unsigned long elapsed = 0;

//////////////////////////////////////
// Setup nRF24L01+ module & Oled
//////////////////////////////////////
RF24 radio(7,8);
RF24Network rf24Net(radio);
const uint64_t this_node  = 00; // base
const uint64_t other_node = 01; // node A
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);

void clearDisplay(void){
  u8g.firstPage();
  do {
   // do nothing
  } while( u8g.nextPage() );
}

//////////////////////////////////////
// Setup the rest of it
//////////////////////////////////////
const int ledPin = 2;

//////////////////////////////////////
// setup
//////////////////////////////////////
void setup(void) {

  // Initialize interfaces
  printf_begin();
  Serial.begin(9600);
  Serial.print(F("Starting interfaces..."));
  SPI.begin();
  radio.begin();
  Serial.print(F("complete]\n"));
  rf24Net.begin(90, this_node);
  radio.setDataRate(RF24_250KBPS);
  radio.printDetails();

  pinMode(ledPin, OUTPUT);
}


//////////////////////////////////////
// float map
//////////////////////////////////////

float fmap (float sensorValue, float sensorMin, float sensorMax, float outMin, float outMax){
  return (sensorValue - sensorMin) * (outMax - outMin) / (sensorMax - sensorMin) + outMin;
}

//////////////////////////////////////
// loop
//////////////////////////////////////
void loop() {

  rf24Net.update();
  data_received payload;

  // listen for incoming clients
  while ( rf24Net.available() )
    {
      RF24NetworkHeader header;
      confirm.hkey = 0;

      // read the next available header
      //rf24Net.peek(header);

      // print NRF24 header data
      String rf24header = "\n[header info => id: "
                        + String(header.id) + " type: "
                        + header.type + " from_node: "
                        + header.from_node +"]";
      Serial.println(rf24header);

      // read data
      rf24Net.read( header, &payload, sizeof(payload) );

      // send back data to confirm integrity
      confirm.hkey = payload.hkey;
      RF24NetworkHeader header2(header.from_node);

      // starts counting just before sending
      elapsed = 0;
      unsigned long start = millis();

      bool sent_back = rf24Net.write( header2, &confirm, sizeof(confirm));

      if (sent_back == true){
        finish = millis();
        elapsed = finish - start;
      }
      else{
      }
      rf24Net.update();
    }

    u8g.firstPage();
    do {
         u8g.setColorIndex(1);
         u8g.setFont(u8g_font_fixed_v0r);
         u8g.setPrintPos(1,10);
         u8g.print(F("HYPERNET"));
         u8g.setPrintPos(95,10);
         if (elapsed > 0 && elapsed <= 10){
           u8g.print("<<<<<");
         }
         else if (elapsed > 10 && elapsed <= 20){
           u8g.print(" <<<<");
         }
         else if (elapsed > 20 &&elapsed  <= 30){
           u8g.print("  <<<");
         }
         else if (elapsed > 30 && elapsed <= 40){
           u8g.print("   <<");
         }
         else if (elapsed == 0){
           u8g.print("xxxxx");
         }
         else {
           u8g.print("    <");
         }
         // --------------------------------
         String node_str;
         if (payload.door || payload.pir){
           digitalWrite(ledPin, HIGH);
           node_str = String("NODE #")+payload.node+String("     REED ALARM!");
         }
         else if (payload.pir){
           digitalWrite(ledPin, HIGH);
           node_str = String("NODE #")+payload.node+String("     PIR ALARM!");
         }
         else{
           digitalWrite(ledPin, LOW);
           node_str = String("NODE #")+payload.node;
         }

         u8g.setPrintPos(1,23);
         u8g.print(node_str);

         // --------------------------------
             Testing some things for batt level

         float vout = 2.25;
         float vin = 0.0;
         float R1 = 993.0; 
         float R2 = 463.0; 
         int value = 0;

         value = payload.batt;
         vout = (value * 2.25) / 1024.0; 
         vin = vout / (R2/(R1+R2)); 

         // ---------------------------------
         
         String read_str1;
         read_str1 =
            String("T:")
            +payload.temp
            +String("\'C  ")
            +String("H:")
            +payload.humi
            +String("%  ")
            +String("P:")
            +payload.batt
            +String("V  ");

         u8g.setPrintPos(1,36);
         u8g.print(read_str1);
         // --------------------------------
         String read_str2;
         read_str2 =
            String("Time elapsed:")
            +elapsed
            +String("ms");

         u8g.setPrintPos(1,48);
         u8g.print(read_str2);
         // --------------------------------
         u8g.setPrintPos(1,62);
         u8g.print(F("Hash key:"));
         u8g.setPrintPos(76,62);
         u8g.print(payload.hkey);
         u8g.setPrintPos(102,62);
         u8g.print("");

    } while( u8g.nextPage() );

    Serial.println("Listening for nodes..");

}

hyp3rkyd:
I am also measuring the AREF pin which is not connected to anything, with a multimeter by hand and it shows 3.3 when connected to the 3V3 source and analog Reference set to DEFAULT and 2.7Volts when connected to INTERNAL.

Shouldn't it be 1.1 ?

On the client that reads the battery voltage and changes it into a value..
Yes!
1.xxx volt (~1.000 to 1.200).
Did you read the digital value directly on the client.
It should be ~800 there.

Base: (value * 2.25), not sure were you get 2.25 from.
Two variables are the battery A/D value and the ~1.1volt Aref of the client.
Fixed is 1024 and 470/1470.
Leo..

it's not 800, it always display 323. I tried with 5 ATMega328P chips and two boards. The only difference with the arduino Uno is that the boards have no oscillators and they work with the 8Mhz arduino bootloader. Could that have to do anything with that (any kind of bug?) ?

I am measuring the voltage directly with the Red needle on the AREF pin and the BLACK on the GND one. INTERNAL gives 2.7V, DEFAULT gives 3.3V.

Any ideas where to search at ?

Don't know if other libraries are interfering with 1.1volt Aref.
Try to load something else.
With this sketch and my UNO r3, I measure 1.063volt on Aref.
Leo..

/*
0 - ~17volt voltmeter
works with 3.3volt and 5volt Arduinos
uses the internal 1.1volt reference
10k resistor from A1 to ground, and 150k resistor from A1 to +batt
(1k8:27k or 2k2:33k are also valid 1:15 ratios)
100n capacitor from A1 to ground for stable readings
*/
float Aref = 1.075; // change this to the actual Aref voltage of ---YOUR--- Arduino (1.000 - 1.200), or adjust to get accurate voltage reading
unsigned int total; // A/D output
float voltage; // converted to volt
//
void setup() {
  analogReference(INTERNAL); // use the internal ~1.1volt reference, change (INTERNAL) to (INTERNAL1V1) for a Mega
  Serial.begin(9600); // ---set serial monitor to this value---
}
//
void loop() {
  analogRead(1); // one unused reading to clear old sh#t
  for (int x = 0; x < 16; x++) { // 16 analogue readings and 1/16 voltage divider = no additional maths
    total = total + analogRead(1); // add each value
  }
  voltage = total * Aref / 1024; // convert readings to volt
  // print to serial monitor
  Serial.print("The battery is ");
  Serial.print(voltage);
  Serial.println(" volt");
  total = 0; // reset value
  delay(1000); // readout delay
}

I also measure something like that on my arduino Uno but not in the external board.

Is this a home-made Arduino board.
If so, did you use proper decoupling.
Leo..

Yes it is and I use the same configuration as maniacbug, it's nothing complicated.

All the arrows are pointing at the software not switching to 1.1volt Aref.
I would start another topic in "Programming Questions" with e.g. "1.1v Aref not working" as header.
And refer to this post. List micro, bootloader, etc.
Leo..