12V Battery State of Charge Indicator




Introduction: 12V Battery State of Charge Indicator

With the use of 12V batteries becoming more popular (typically the 7Ah sealed lead acid), I have been requested several times to build a state of charge (SOC) meter displaying the voltage on LEDs. However, each person wants something a little different. The biggest difference is the required minimum and maximum voltage to be displayed.

If a low level warning is also required, this will then result in three voltage levels to be monitored. Using pots for adjustments, is the normal method used. However, add a second or third warning, this can become a problem.

Lastly, the current drawn by circuits I have tested, ranged between 45mA and 150mA. With a standard LM3914 battery monitor, the battery monitor itself will drain a 7Ah battery in about 46 hours.

The aim was then to design a battery indicator with the following specifications:

- LED Display
- Adjustable maximum voltage level
- Adjustable minimum voltage level
- 3 Adjustable alarms (typically 50%, 30%, 20%)
- Alarms to be non-irritating, and have a mute function
- Minimum buttons
- Low power consumption

For my design, I opted for the AtMega328P micro.

Step 1: LED Display

The LED display was designed to be simple and easy to interpret. There are 6 LEDs, indicating the voltage level in a LED BAR method:

Led 6 - 100%
Led 5 - 80%
Led 4 - 60%
Led 3 - 40%
Led 2 - 20%
Led 1 - 0%

The 0% Led is to be linked to the programmed minimum voltage level
The 100% Led is to be linked to the programmed maximum voltage level.

The scaling between 0% and 100% is linear. For 0%, only Led 1 will be on, and for 100%, all Leds will be on.

For power saving, the LED display does not stay on. To turn on the display, a button needs to be pressed, and the display will turn off after 30 seconds.

Step 2: Voltage and Alarm Levels

To be able to measure the voltage, the battery voltage needs to be down scaled. Using a resistor divider, the voltage is scaled down to 1.1V with a 1M and 82K resistor. With the A/D converter set to the internal 1.1V reference, this means that the maximum measureable voltage will be around 14.45V, high enough for the design.

There are 5 voltage levels that needs to be monitored:

- maximum voltage level
- minimum voltage level
- alarm 1 voltage level
- alarm 2 voltage level
- alarm 3 voltage level

Instead of using trimpots, I decided to go for a more unconventional way. Via a programming procedure, apply the specific voltage levels in turn, and save the various A/D results in EEPROM.

The LEDs are used to indicate the programming sequence, and the same button used for the display, is used for programming.

Step 3: Audible Alarm

A normal piezo buzzer is used for the alarm. as this should be load enough. Provision for three alarms were made, with the following properties:

- Alarm 1, to beep once every few seconds. Should be able to silence this alarm
- Alarm 2, to beep twice every few seconds. Should be able to silence this alarm
- Alarm 3, to beep three times every few seconds. This alarm can not be silenced.

Once an alarm is silenced, I needed an automatic reset function to enable the alarms again if the battery has been charged. I included a reset function that will enable all alarms again if the battery voltage exceeds 60% again.

To silence the alarms, the same button used for the display is used.

I tested these alarm sounds in my house, without any complaints from my wife and son, so I am sure it will not be irritating in the outdoors world.

Step 4: Minimum Buttons

All functions are done using a single button.


To turn on the display, press the button. The LED dislpay will come on, and turn off automatically after 30 seconds.


Alarm 1 and Alarm 2 are silenced by pressing the buttom.


To enter programming mode, press and hold the button while powering up the unit. Keep the button pressed for 5 seconds.

Step 5: Low Power . . .

There are several ways to reduce the overall power used by the circuit. I used the following methods:


By pressing the button, the LED display is turned on, and automatically turns off the LEDs after 30 seconds. This results in a saving of 120mA.

MCU Voltage

Running the AtMega328P at 5V, uses more power than running at 3.3V. I opted for a 3.3V low drop out regulator.

Voltage Regulator

A standard 7805 regulator has a quesent current of around 20mA. Using a 78L05, this is reduced to 3.5mA. But, by using a low drop out regulator like the LP2950 3.3V, this can be dropped to as low as 0.1mA.

If you do not require the power saving, you can use a 78L05

Oscillator speed and selection

From the datasheets, the AtMega328P current can be dropped from around 10mA to 1mA by selecting the internal 8MHz oscillator, as compared to the external 16MHz crystal.

I opted to use the internal oscillator running at 8MHz for the design, as it gives the best speed/power performance. However, the drawback is that the AtMega328P config registers needs to be programmed using AVRDude. I make use of this site (http://www.engbedded.com/cgi-bin/fcx.cgi?P_PREV=&P... to get the correct register configs.

If you do not want to change the config fuses, the MCU must run on an external 16MHz oscillator. Please change any delay() and Millis() values to actual ms values.


By placing the AtMega328P in SLEEP mode, one can further reduce the power. In SLEEP mode, most of the MCU interfaces are turned off. In this mode, the MCU can draw as little as 0.001mA. However, the MCU is no longer running, or in this case, measuring the voltage.

A watchdog time is used to wake the MCU from SLEEP. Setting up the watchdog timer to wake up the MCU every 8 seconds, will ensure that the power used is even less.

More information about the power saving modes can be found at http://www.gammon.com.au/forum/?id=11497.

Results of power saving

By using the above power saving techniques, I was able to reduce the current of the circuit down from 80mA to as low as 0.12mA when the device is in SLEEP mode. Overall, the circuit uses about 0.28mA.

Thus, before power saving the circuit will drain a 7Ah battery in about 2.8 days.

After power saving, it will take around 3.5 years for the circuit to drain the same battery.

Step 6: Building the Circuit

I used the free version of Eagle to design the PCB. All components, except the push button, are mounted onto the PCB. Assembly is easy, with the exception of soldering the LEDs. Ensure all LEDs are the same height. I used 20mm spacer to mount the unit, and used this as reference for the LED height.

Because my design uses a 3.3V regulator, some standard 5V piezo buzzers does not work. The buzzer in the design is connected across 12V, and switched with a transistor. Play around with the value of R6 to get a decent sound out of the buzzer, without destroying it. Apart from this, there is no other tricks in building the circuit.

Step 7: Calibrating the Unit

You will need a variable power supply and a multi meter to calibrate the unit.

Entering Calibration Mode

- Press and hold the button
- Connect unit to power supply
- After 5 seconds, the unit will beep continuously
- Release the button
- Unit will give 6 beeps (setting maximum voltage)
- Top LED will be on
- Uit is now in CALIBRATE mode. To exit this mode, remove power from the unit without pressing the button.
- Adjust power supply output to the maximum voltage to be displayed on the LED display (typical 12.7V)
- Press the button
- Unit will give 5 beeps (setting minimum voltage)
- Bottom LED will be on
- Adjust power supply output to the minimum voltage to be displayed on the LED display (typical 11.8V)
- Press the button
- Unit will give 4 beeps (setting Alarm 1)
- Bottom 4 LEDs will be on
- Adjust power supply output to Alarm 1 voltage level (typical 12.4V)
- Press the button
- Unit will give 3 beeps (setting Alarm 2)
- Bottom 3 LEDs will be on
- Adjust power supply output to Alarm 2 voltage level (typical 12.2V)
- Press the button
- Unit will give 2 beeps (setting Alarm 3)
- Bottom 2 LEDs will be on
- Adjust power supply output to Alarm 3 voltage level (typical 12.0V)
- Press the button
- Unit will give 1 long beep to indicate end of calibration, and LED display will turn on for 30 seconds.

All programming values are stored in EEPROM, so the unit only needs to be calibrated once.

Be the First to Share


    • Digital Fabrication Student Design Challenge

      Digital Fabrication Student Design Challenge
    • Stone Concrete Cement Contest

      Stone Concrete Cement Contest
    • Go Big Challenge

      Go Big Challenge



    1 year ago

    I realise this is an old post but, just in case the original poster is still active - Isnt the code posted just standard arduino IDE ?

    Sayandeep Nayak
    Sayandeep Nayak

    4 years ago

    Can you let me know the value of c3 and c4 in the circuit dia. And is any programming to be done for the ATMEGA?

    Eric Brouwer
    Eric Brouwer

    Reply 4 years ago


    C3 and C4 is 0.1uf.

    Yes, the ATMEGA needs to be programmed with the code found under Step 6.



    Sayandeep Nayak
    Sayandeep Nayak

    Reply 4 years ago

    Thanks. Good project. I will make it.

    Eric Brouwer
    Eric Brouwer

    Reply 6 years ago on Introduction

    Let me know if the build goes without any problems.

    walang hiya
    walang hiya

    Reply 6 years ago

    great! well done!..can someone help me..i need to make it 48VDC ..does the components are the same if i make one?

    walang hiya
    walang hiya

    Reply 6 years ago

    great! well done!..can someone help me..i need to make it 48VDC ..does the components are the same if i make one?

    Eric Brouwer
    Eric Brouwer

    Reply 7 years ago on Introduction

    That is why I love electronics. There are no single correct method. Each project can be custom made for a specific requirement. The design will depend of your own need.


    7 years ago on Introduction

    Nice instructable! It happens I've been working on a similar project for the past few days, but it also involves a battery charging circuit. I'm using ATTiny13A and 74HC595N shift register for handling state-of-charge display. This way I still have a reset interrupt pin and 2 GPIOs left to control the charge cycle. Still working on the firmware(writing from scratch in AVR assembly), but I think it will be ready soon.

    Another thing, which may come in handy: there are very cheap LED battery indicators like these:


    I wanted to use regular 5mm LEDs as well, but this thing is much prettier and is only $1.50 =)


    Well done, your first FEATURED Instructable it looks like. I think the build options you presented were useful to any who wish to customize their project, thanks for sharing your expertise.


    7 years ago on Introduction

    I have read this with interest thanks . I also did an Instructable using an RGB led instead . Perhaps it might be useful also . I have used your paragraph on power saving as an addition to my post thank you.



    7 years ago

    A 12 volt battery is fully charged at 12.7 volt and discharged at 12 volt. Yes empty at 12 volt. Any further discharge below11 volt will distroy the battery.

    Eric Brouwer
    Eric Brouwer

    Reply 7 years ago on Introduction

    I fully agree with you that 12.0V indicate 0% charge. But this is OPEN CIRCUIT voltage. As my batteries are always LOADED when the monitor is on, I am actually measuring the loaded voltage. I have found that discharging my batteries to 11.8V loaded, is still within limits. When the load is disconnected at 11.8V, the battery terminal voltage will rise back to above 12.0V.

    I do not use deep cycle batteries as used in electric gate motors, as I do not require a lot of power. Also, the cost of one deep cycle SLA battery is still higher than that of three standard "alarm system" SLA batteries. The higher voltage drop across the terminals of the cheaper SLA batteries is due to their higher internal resistance. Even with a fully charged battery, the loaded voltage of the battery will fall with about 0.15 to 0.2V compared to their open circuit voltage with a load of 1 amp.

    One of the more challenging parts of the design was actually how to accurately determine the state of charge when the battery is loaded. At first my monitor was set at 12.0V, and I used it until the monitor indicated 12.0V , I then charged the battery with an intelligent charger, but only returned 4500mA back into the 7aH battery. I repeated this test on another battery, with almost the same results. The last test was done with the same battery, but discharged to 11.8V loaded. Leaving the battery open circuit for 30 minutes, the voltage returned to 12.15V. Charging the battery, returned 5200mA.

    This is the main reason I included the programmable display and alarm levels. My unit is currently calibrated as follow:

    - Max displayed voltage: 12.60V

    - Min displayed voltage: 11.80V

    - Alarm level 1: 12.30V

    - Alarm level 2: 12.15V

    - Alarm level 3: 12.00V

    This gives me enough time to react on the first and second alarm, reducing the load, and prevent the battery from being drained too low. But it does leave me with about 25% battery life in case of an emergency.


    7 years ago

    Awesome project! :) thanks for shearinga