Project List

Mail me

Last update: 2012-09-06



I'm using rechargeable lead acid gel batteries in my autonomous mobil robot (12V/24Ah). This circuit monitors the status of the accumulator. Monitoring is achieved by simply measuring the voltage value of the battery. The status of the battery can be queried via the RS-232 interface.

About the Circuit

Digital Part

The digital part is standard ATmega8 circuitry. It includes a RS-232 transceiver and a baud crystal for clocking the AVR. Its frequency of 14.7456 MHz allows for error-free generation of all standard baud rates. Analog reference and supply are buffered according to Atmel's recommendations.

Wiring diagram of battery monitor

Analog Part

The analog part is more application specific thus more interesting. A simple way of determining the status of a led acid battery is to measure its voltage value.

So the voltage values we can measure are ranging from 14.8V when charging, to 13V when fully charged to 0V when discharged. However, we are not interested in voltage values below 11V. At 11V the robots DC/DC converters are still working fine. Power supply for the PC and the microcontrollers is still guaranteed. But the 12V motors are slowing down significantly. Therefore the circuit is supposed to capture the range from 11V to 15V. This also increases the resolution of the ADC for the voltages that are significant to us.

We need to map the measured value to the range from 0V to 2.56V since we are using the AVR's internal bandgap reference (2.56V) for A/D conversion. The left side of the following diagram shows the voltage range from 0V to 15V mapped to 0V to 2.56V. This can easily be achieved using a voltage divider. The right side depicts a situation where we forget everything from 0V to 11V and only map the range 11V-15V to 0V-2.56V. This requires a more complex circuitry. The advantage is that we achieve a higher resolution for the range we are interested in.

Increase ADC resolution for the voltage range of interest
We can see such a mapping of one voltage range to another as a function which maps an input voltage Uin ∈ [11V; 15V] to an output voltage Uout ∈ [0V; 2.56V]. This is depicted in the following diagram. The blue curve is what a voltage divider would deliver. The red curve is the function we want to achieve. The diagram also shows that the problem is a mx+b problem.

A function mapping Uin to Uout
The idea of solving the problem is to use an operational amplifier. First we cut of b volts and second we multiply it by m. Therefore we use a differential amplifier as depicted below.

Basic differential amplifier circuit
The above circuit is a standard op amp circuit which you can read about on the internet. It realizes a function
Uout = (U2 - U1) * RF / RI
This is great for our purpose. First we let U2 be our battery voltage value and U1 be 11V. That means that we already get our offset of 11V cut off. When the battery falls below 11V we will have an output of 0V. Now we need to choose RF and RI so that the output will be 2.56V once the input reaches 15V.

Where do we get a constant value of 11V? We don't. Instead we use the AVR's internal voltage reference of 2.56V! So we can only cut off 2.56V. Therefore we are using a trim potentiometer to divide the battery voltage as depicted in the following wiring diagram. That diagram is a further developed version of the first one.

Differential amplifier circuit modified for the application
The above circuit realizes a function
Uout = (Utrim - Uref) * RF / RI
Utrim = Uin / x, Uref = 2.56V
Now we need to determine x, RF and RI. We are not free to choose any resistor value we want unless we are using further trim potentiometers. Therefore - from the available resistor values - I chose RF=100kΩ and RI=39kΩ. By accident this gives us an amplification of approximately 2.56.

Now what is left is to determine x which basically means adjusting the trim potentiometer Rtrim. We can calculate a value. But we make life easier by just calibrating the trim pot. Therefore we don't use the actual battery but a laboratory power supply instead.

The below diagram depicts the calibration setup I was using.
Calibration setup

You will not achieve exact results (exactly 0-255) but the result will suffice. After having adjusted the trim pot my battery monitor delivers the following values:

Battery [V]ADC Value
ADC values for certain battery voltage values

This gives us a nice linear relation between battery voltage and ADC value.

Voltage to ADC curve

About the Software

Included in this project is a test program for the AVR. It captures analog values from ADC channel #0 in a free running manner. That is, the values are captured automatically and repeatedly. The value from the hardware DAC register is read and stored for later use in a global variable. This happens in the corresponding ISR.

The global variable is returned to a host PC via RS-232. You can use a standard terminal program for receiving output from the AVR.



Circuit board (some capacitors soldered at back side)

Version History

1.0.02012-07-06Initial version.
1.1.02012-07-21Some minor corrections.
1.2.02012-09-06Now using libAvrUtils 1.2.0.

Copyright Statement

mega8battMon Copyright (C) 2012 Holger Zahnleiter

This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. The program and its source code are published under the GNU General Public License (GPL). See http://www.gnu.org/licenses/gpl-3.0.txt for details.


Creating this library would not have been possible without the achievements of the following persons/organisations:


Operationsverstärker Grundschaltungen Article (german) on operational amplifiers on mikrocontroller.net.
http://www.mikrocontroller.net/ A great (german) resource of Atmel AVR tutorials and general microcontroller know how.
RoboterNETZ Another great (german) resource of microcontroller know how.
AVR freaks English speakers should visit this website.
CrossPack CrossPack for AVR Development for Mac OS X.
AVR-GCC-Tutorial German avr-gcc tutorial from mikrocontroller.net.
http://www.nongnu.org/avr-libc/ The AVR C library (for use with avr-gcc).
http://www.nongnu.org/avrdude/ AVRDUDE, a tool for flashing AVRs.
http://www.cadsoft.de/ EAGLE a CAD software for designing circuits. Free version available for Mac OS X, Linux and Windows.
RS-232 product site MAXIM's website featuring their line of RS-232 transceivers. The most current datasheet can be downloaded from there.
LM358 product site Texas Instruments's website featuring the LM358 operational amplifier. The most current datasheet can be downloaded from there.
ATmega8 product site Atmel's website featuring ATmega8. The most current datasheet can be downloaded from there.


Source code for ATmega8 (mega8battMon-1.2.0-src.zip)
ATmega8 test program (test.hex)
Wiring diagram/Eagle 6.2.0 (mega8battMon.sch)
Atmel ATmega8 Datasheet
Texas Instruments LM358 Operational Amplifier Datasheet
MAXIM RS-232 Transceivers Datasheet
Fastron 11P 10µH Inductor Datasheet
Fastron 11P Inductors Product Codes
Panasonic 12V/24Ah Lead Acid Battery Datasheet


The information on this web site and the documents downloadable from here have been carefully reviewed and is believed to be reliable, but I do not assume any liability arising out of the application or use of any documents, programs or circuit described herein.
Furthermore I want to declare that I'm not responsible in any way for the content of other web pages, books and other sources I'm refering to.