Indicating Low battery using and piezo speaker

Hello everyone,

I am wanting to use Piezo speaker to simply beep when a battery has 10% of charge left. Any ideas on where to start (reference material/ examples)?

Start by measuring the battery with an analogue pin. Then you can set a threshold voltage in code. Depending on battery chemistry you might or might not be able to detect 10% charge. Turning a buzzer on/off with an output port is the easy part. Post hardware and code of you want detailed help. Leo..

Currently I am using a 9V battery and two 10k ohm resistors as a voltage divider to reduce it to 4.5V (I would have preferred to divide it to 5V but I don’t have the correct value of resistors.) I also want the same battery to power the Arduino. Before I begin programming, is this wiring correct?

Just tried to attach an .JPG but it didn't work. Best way to insert an image?

a 9V battery and two 10k ohm resistors as a voltage divider

That will work, but a 9V battery won't last long.

Thanks for the replies. Here is the image file I tried to upload earlier. Is the wiring correct if I am to power the Arduino with a 9V battery and measure the voltage?

Yes, wiring is correct. That will work if the battery is between 6 and 10 volt. Read A0, and convert the A/D value to a voltage. Leo..

This gives me 5.00 on the serial monitor. How would I then relate this to the voltage on the battery? Do I need to calculate a ratio of Vin and Vout?

int sensorValue;
float voltage;

void setup()



void loop()

  sensorValue = analogRead(0); //read the A0 pin value

  voltage = sensorValue * (5.0 / 1023); //convert the value to a true voltage.

  Serial.println (voltage);


The two 10k resistors form a 2:1 voltage divider (give or take a few percent for the resistor tolerances ... ) so if you had 9v from the battery, you would have 4.5 volts from the divider. Knowing that and the value you are reading from the A/D, you can calculate a scale factor to convert the reading to actual volts. If you are seeing 5.000, I am suspicious the perhaps you are not reading something right although a fresh 9v battery may be that high (10v) - I don't have any handy to check.

Formula must have the resistor divider included.

voltage = sensorValue * 2.0 * (5.0 / 1023);
or shorter
voltage = sensorValue * 0.009775;
Change the last digit(s) to calibrate.

Hello everyone,

I am wanting to use Piezo speaker to simply beep when a battery has 10% of charge left. Any ideas on where to start (reference material/ examples)?

10% of 9 volts is .9 volts, this way below the operating voltage of the Arduino, depending on Chip chosen I think 3v3 is the lowest operating voltage? At 5VDC operating voltage, 5.4VDC would your 90% discharged cut off point.
I would look at something like this code (but I am very new at this)

void loop()
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 1000); 
if val<545 do something;
//the 1000 figure allows for 2 decimal places without needing floating integer maths.

Kiwi_Bloke: 10% of 9 volts is .9 volts, this way below the operating voltage of the Arduino

He said 10% of charge, not voltage. Probably he really means 10% of usable charge. It's hard to calculate that directly but he could decide on a threshold voltage.

It looks like he's using an Uno. They draw about 50mA which means his 9V alkaline battery will drop to 6V after roughly 10 hours of use. After that Vcc on the board goes below 5V. An Uno will keep working until Vcc goes to about 3V or so, or whatever the brownout is set to. But probably he'd want his piezo to sound at a higher voltage.

Post#5. Below ~6volt on Vin, the onboard regulator is not able to produce a stable 5volt anymore.

The 5volt rail drops, and so does default Aref.

When input voltage drops, and Aref drops, the returned A/D value will stay the same.

So below 6volt (with default Aref), you can't measure the battery anymore. Leo..

voltage = sensorValue * 2.0 * (5.0 / 1023);

When I use this, the analog reading becomes 10.00. It is a new battery but I didn't expect a value to as high as 10.00. I would have thought it would have displayed the same value when measuring the battery with a multimeter. When I measure across the two resistors I get a value of 8.24. How do I get that value? Do I calibrate the 0.009775 until I do?

Are you using a 5volt Arduino (there is an UNO on your Fritzing diagram).

Are you sure both resistors are 10k. Measure the voltage on A0. It should be half of the battery voltage.

Post a picture of the setup. Leo..

Here is the set up.

Also I am now using an LCD screen do display the real time volt of the battery.

//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27 , 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

int sensorValue;
float voltage;

const int analogInPin = A0;

void setup() {


  lcd.init();                      // initialize the lcd
  lcd.init();                      // initialize the lcd

  // Print ''Time'' to the LCD.
  lcd.setCursor(0, 0);


void loop()

  sensorValue = analogRead(analogInPin); //read the A0 pin value

  voltage = sensorValue * 2.0 * (5.0 / 1023); //convert the value to a true voltage.

  Serial.println (voltage);

  lcd.print(voltage); //print the voltage to LCD


Setup seems ok.

Still waiting for the voltage on A0. Double-check the resistor values. Leo..

The resistors are definitely 10k ohm. I am assuming to measure the voltage of an anolog pin I just use this code without the multiple of 2 when everything is plugged in? If so I get 4.02.

  Reads an analog input on pin 0, converts it to voltage, and prints the result to the serial monitor.
  Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
  Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

  This example code is in the public domain.

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0);
  // print out the value you read:

If you get 4.02volt with the code, then it's working.

Because you have divided the voltage of the 9volt battery by 2 with the resistors, you have to multiply the calculated voltage value by 2 to get the right voltage readout. 8.04volt. Leo..

Great! However the next problem is when I disconnect the USB power source from the laptop and power the Arduino only using the battery the battery (By using a wire from the battery, before the first resistor to Vin, the value become strange and doesn’t look as if its in real time. Demonstrated in the image below.

The value has dropped drastically from 8.04 - 5.68. And when I voltage across the two resistors it is 7.23 dropping 0.01 quit frequently. This isn’t in sync at all with 5.68?

Also when the Arduino is powered by the USB, the LCD value increases and to verify this is related to the battery, when measured using a multimeter, the batteries voltage increases too. Can anyone explain why this happens?

jremington already said in post#3 that a 9volt smoke alarm battery won't last long. The Arduino and the display (backlight) might add up to 100mA. Most 9volt batteries can't keep up with that current. Unexpected things happen below 6volt. Leo..