Attiny85 battery tester shows wrong reading

I created this attiny85 battery tester but it is showing the wrong voltage on new batteries. It should show 1.5V but it is showing over 2.5V. The battery tester has an OLED and and RGB LED to display the voltages. The main issue is the OLED display showing the wrong voltage. Here is the code

#include <Tiny4kOLED.h>


int redPin = 1;
int greenPin = 3;

int analogValue = 0;
float voltage = 0;
int ledDelay = 1000;
// ============================================================================

void setup() {
   oled.begin();
  oled.clear();
    oled.on();
   oled.switchRenderFrame();
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
}

void loop() {
  oled.clear();
  oled.setFont(FONT8X16);
  oled.setCursor(32, 0);
  oled.print(F("Voltage"));
  oled.setFont(FONT6X8);
  oled.setCursor(13, 2);
  oled.print(F(""));
  oled.setCursor(16, 3);
  oled.print(F(""));
  oled.switchFrame();
  delay(10);
analogValue = analogRead(A2);
  voltage = 0.0048*analogValue;
 oled.println(voltage);
  

  if( voltage >= 1.6 )
    setColor(0, 255, 0);  //green LED color
  else if (voltage > 1.2 && voltage < 1.6)
     setColor(255, 255, 0);  // yellow LED color
  else if( voltage <= 1.2)
    setColor(255, 0, 0);  // red LED color

    oled.clear();
}

void setColor(int red, int green, int blue)
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
    
}

I am pretty sure this part is to blame in the code

voltage = 0.0048*analogValue;

This code below works perfectly on an arduino and it displays the correct voltage of any battery. I am guessing I need to change something in the code going from an arduino nano to attiny 85. Any help would greatly be appreciated. Here is the code for the battery tester on an arduino nano.

#include <Adafruit_SSD1306.h>

#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(OLED_RESET);


int redPin = 3;
int greenPin = 5;

int analogValue = 0;
float voltage = 0;
int ledDelay = 1000;

void setup()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  
   pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  
}

void loop()
{
  analogValue = analogRead(A1);
  voltage = 0.0048*analogValue;
 display.println(voltage);

  if( voltage >= 1.6 )
    setColor(0, 255, 0);
  else if (voltage > 1.2 && voltage < 1.6)
    setColor(255, 255, 0);  // yellow
  else if( voltage <= 1.2)
    setColor(255, 0, 0);  // red
    
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Voltage");
  display.display();
   display.clearDisplay();

}

void setColor(int red, int green, int blue)
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  //analogWrite(bluePin, blue);  
}
  1. Which core are you compiling with?
  2. Which physical pin # are you connecting the battery to on the ATtiny85?

Are the Nano and the Attiny getting the same VCC?

e.g. if you power the Attiny85 from a lower voltage the analogread will show a higher value.

The attiny85 is powered by a 3V battery, pin4 is ground and pin 8 is VCC. The arduino is connected to the computer. Is this the part of the code that needs changing?

voltage = 0.0048*analogValue;
voltage = 0.0048*analogValue;

can also be written as

voltage = 5.0 * analogValue / 1023.0; // (or 1024.0 depending on your POV)

The 5.0 is for 5V operation. For 3.3V operation the equation should be

voltage = 3.3 * analogValue / 1023.0; // (or 1024.0 depending on your POV)

Is the use of Vref a valid way to avoid this?

Yes, as long as you can ensure that the voltage to be measured is below the 2.56 Volt of the internal voltage reference. The internal voltage reference requires a VCC of minimum 3 volts. So your 3Volt battery is the absolute minimum.

O, and you still need to adjust the calculation like @van_der_decken suggested, but then with a 2.56 factor instead of 3.3 or 5.0

1.1volt Aref is a safer option. Then 3volt VCC is not a problem any more.

When using 1.1volt Aref, battery voltage that you measure must then be reduced to ~1volt with a voltage divider. Say 10k from pin to ground and 4k7 between pin and (for a 1.5volt) battery.

That is not a bad thing, because you should never connect a power source directly to an I/O pin.
Leo..

I measured 3.3V of NANO by PC-connected NANO and have found 3.3V on the Serial Monitor.

I have measured the 3.3V of NANO using PC-connected Digispark ATtiny85 Dev Board, and I have found 3.1V -3.2V on the OLED Monitor.

If yo are are operating ATtiny85 by VCC = 3V, then you have to make a two-point calibration as we use the following code to display the acquired voltage; where, VREF voltage of the ADC is: 5V (default).

oled.print((5.0/1023)*analogRead(A2), 1);
oled.on();

Changing the voltage from 3.3V to 2.38V worked!

voltage = 2.38 * analogValue / 1024.0;

This comes to within 0.01-0.04V accuracy in 1.5V batteries. Is there a way to change the code for it to read 3.0V and 9V batteries? This code reads a new 3.0V battery as 2.37V. It also reads a 9V battery as 2.37V.

Voltage dividers on the battery are needed when battery voltage exceeds Aref. If you don't, then the A/D will just peg at it's highest value of 1023, which will display 2.37volt with your current voltage formula.

I hope you didn't connect the 9volt battery directly to the pin, because that would likely kill it.

If you don't use a stable voltage reference, like the internal 1.1volt Aref, then your voltage reading will also depend on supply voltage of the Attiny85.
Leo..

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.