Download - Led Voltage Monitor
![Page 1: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/1.jpg)
/*
This unit was designed to be used on 12V battery systems only.
FEATURES
========
6 LEDs to display voltage level (< 20%, >20%, >40%, >60%, >80%, 100% and above)
Programmable maximum LED displayed voltage
Programmable minimum LED displayed voltage
3 Independant programmable undervoltage alarms (independant of LED display)
SPECIFICATIONS
==============
Supply 8 to 18V
Max measureable voltage 14.5V
Min measureable voltage 8.0V
Average current drain 0.25mA with display off @ 12.8V
A/D Converter 10 bit
A/D Resolution about 15.0mV
Sample method Average of 100 samples taken every 8 seconds
Prevered alarm settings >100mV between alarms
BUTTON
======
Pressing the button will display voltage level for 30 seconds
![Page 2: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/2.jpg)
if Alarm 1 or Alarm 2 is active, pressing the button will silence the alarms
Pressing button while powering up device, will enter CALIBRATION mode (see CALIBRATION)
While display is on, pressing the button has no effect
BUZZER
======
Beep 1 time every 8 seconds - voltage lower than ALARM 1 level. Press button to silence alarm
Beep 2 times every 8 seconds - voltage lower than ALARM 2 level. Press button to silence alarm
Beep 3 times every 8 seconds - voltage lower than ALARM 3 level. Alarm can not be silenced
Alarms that was silenced, will be reset once voltage exceeds 60% of display voltage for longer than 10 seconds
DISPLAY
=======
While display is on, no alarms will sound
Display will turn off automatically after 30 seconds to conserve battery
CALIBRATION
===========
Before applying power, press button and keep pressed for longer than 5 seconds
Device will beep constant
Release button
6 Beeps - program max display voltage
Top LED on
Device is now in CALIBRATE mode
To exit CALIBRATE mode, remove power from device before preesing the button again
![Page 3: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/3.jpg)
Adjust to max display voltage and press button to save
5 Beeps - program min display voltage
Display will show lowest LED
Adjust to min display voltage and press button to save
4 Beeps - program alarm 1 voltage
Display will show lowest 4 LED
Adjust to alarm 1 voltage and press button to save
3 Beeps - program alarm 2 voltage
Display will show lowest 3 LED
Adjust to alarm 2 voltage and press button to save
2 Beeps - program alarm 3 voltage
Display will show lowest 2 LED
Adjust to alarm 3 voltage and press button to save
Device will give a long beep
Actual voltage is now displayed for 30 seconds
Calibration complete
! ! ! ! ! SPECIAL NOTE ON THE PROJECT ! ! ! ! ! !
To make use of the power saving options available on the AtMega328P, this
program was written with the clock speed at 8MHz, instead of 16MHz. I also
programmed the chip to use the internal 8MHz oscillator for maximum energy
saving.
This means all delays and millis() routines will run at half the speed.
*/
![Page 4: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/4.jpg)
// Include this 3 files for the low power setups
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <EEPROM.h>
// define constants
const byte BTN = 2; // test button
const byte LED1 = 8; // 0%
const byte LED2 = 7; // 20%
const byte LED3 = 6; // 40%
const byte LED4 = 5; // 60%
const byte LED5 = 4; // 80%
const byte LED6 = 3; // 100%
const byte Buzzer = A4; // buzzer
const byte BatIn = A5; // battery monitor pin
// define variables
byte oldADCSRA = 0;
boolean BtnDwn = 0;
byte Range = 0;
// define battery settings
![Page 5: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/5.jpg)
unsigned int Vmin = 0; // minimum displayed battery voltage
unsigned int Vmax = 0; // maximum displayed battery voltage
unsigned int Alm1 = 0; // alarm 1
unsigned int Alm2 = 0; // alarm 1
unsigned int Alm3 = 0; // alarm 1
unsigned int Batt = 0; // calculated voltage reading
long Told = 0; // ms timers
long Tnew = 0; // /
boolean Mute1 = 0; // 1st alarm buzzer mute flag
boolean Mute2 = 0; // 2nd alarm buzzer mute flag
boolean Beep1 = 0; // 1st alarm beep status
boolean Beep2 = 0; // 2nd alarm beep status
//------------------------------------------------------------------------------------------------------------------------------------
// Setup
//------------------------------------------------------------------------------------------------------------------------------------
void setup () {
// setup hardware
pinMode(BTN, INPUT_PULLUP); // enable pull-up
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(LED5,OUTPUT);
pinMode(LED6,OUTPUT);
![Page 6: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/6.jpg)
pinMode(Buzzer,OUTPUT);
// turn off LEDS
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED6,LOW);
digitalWrite(Buzzer,LOW);
//load calibration from EEPROM
if (EEPROM.read(11) == 123) {
//EEPROM contains valid data
// min voltage
Vmin = EEPROM.read(1);
Vmin = Vmin << 8;
Vmin = Vmin + EEPROM.read(2);
// max voltage
Vmax = EEPROM.read(3);
Vmax = Vmax << 8;
Vmax = Vmax + EEPROM.read(4);
// alarm 1 voltage
Alm1 = EEPROM.read(5);
Alm1 = Alm1 << 8;
Alm1 = Alm1 + EEPROM.read(6);
// alarm 2 voltage
![Page 7: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/7.jpg)
Alm2 = EEPROM.read(7);
Alm2 = Alm2 << 8;
Alm2 = Alm2 + EEPROM.read(8);
// alarm 3 voltage
Alm3 = EEPROM.read(9);
Alm3 = Alm3 << 8;
Alm3 = Alm3 + EEPROM.read(10);
}
else {
// no calibration data. Enter calibration mode
Do_Calibrate();
}
// Button pressed during power up - start calibration mode
if (digitalRead(BTN) == 0) {
Told = millis();
while (digitalRead(BTN) == 0) {
if ( (millis() - Told) > 2500) {
digitalWrite(Buzzer,HIGH);
while (digitalRead(BTN) == 0) {
delay(20);
}
digitalWrite(Buzzer,LOW);
delay(250);
Do_Calibrate();
}
![Page 8: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/8.jpg)
}
}
analogReference(INTERNAL);
oldADCSRA = ADCSRA;
delay(10); // delay for A/D to set
//wakeup();/
BtnDwn = 1;
// start-up test
digitalWrite(Buzzer,HIGH);
delay(500);
digitalWrite(Buzzer,LOW);
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED6,LOW);
Told = millis();
}
//------------------------------------------------------------------------------------------------------------------------------------
// Main Loop
//------------------------------------------------------------------------------------------------------------------------------------
void loop () {
BattLoop:
![Page 9: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/9.jpg)
Do_Batt();
// if button is pressed, show voltage for 30 seconds
if (BtnDwn == 1) {
Do_LEDs();
delay(25);
if ( (millis() - Told) < 15000) goto BattLoop;
// Mute any alarms
if (Beep1 == 1) Mute1 = 1;
if (Beep2 == 1) Mute2 = 1;
BtnDwn = 0;
}
Do_Buzzer();
sleep();
sleep_disable();
wakeup();
}
//------------------------------------------------------------------------------------------------------------------------------------
// Calibration routine
//------------------------------------------------------------------------------------------------------------------------------------
void Do_Calibrate() {
// calibrate max voltage
digitalWrite(LED6,HIGH);
// beep 6 times
for (byte i = 1; i <= 6; i++) {
![Page 10: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/10.jpg)
digitalWrite(Buzzer,HIGH);
delay(50);
digitalWrite(Buzzer,LOW);
delay(100);
}
while (digitalRead(BTN) == 0) {
delay(20);
}
calMax:
Do_Batt();
delay(50);
if (digitalRead(BTN) == 1) goto calMax;
// Done, save value
EEPROM.write(3,Batt >> 8);
EEPROM.write(4,Batt & 255);
// reset calibrated flag;
EEPROM.write(11,0);
digitalWrite(LED6,LOW);
while (digitalRead(BTN) == 0) {
delay(20);
}
// calibrate min voltage
digitalWrite(LED1,HIGH);
// beep 5 times
for (byte i = 1; i <= 5; i++) {
![Page 11: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/11.jpg)
digitalWrite(Buzzer,HIGH);
delay(50);
digitalWrite(Buzzer,LOW);
delay(100);
}
calMin:
Do_Batt();
delay(50);
if (digitalRead(BTN) == 1) goto calMin;
// Done, save value
EEPROM.write(1,Batt >> 8);
EEPROM.write(2,Batt & 255);
digitalWrite(LED1,LOW);
while (digitalRead(BTN) == 0) {
delay(20);
}
// calibrate alarm 1 voltage
digitalWrite(LED4,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
// beep 4 times
for (byte i = 1; i <= 4; i++) {
digitalWrite(Buzzer,HIGH);
delay(50);
![Page 12: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/12.jpg)
digitalWrite(Buzzer,LOW);
delay(100);
}
calAlm1:
Do_Batt();
delay(50);
if (digitalRead(BTN) == 1) goto calAlm1;
// Done, save value
EEPROM.write(5,Batt >> 8);
EEPROM.write(6,Batt & 255);
digitalWrite(LED4,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED1,LOW);
while (digitalRead(BTN) == 0) {
delay(20);
}
// calibrate alarm 2 voltage
digitalWrite(LED3,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
// beep 3 times
for (byte i = 1; i <= 3; i++) {
digitalWrite(Buzzer,HIGH);
delay(50);
![Page 13: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/13.jpg)
digitalWrite(Buzzer,LOW);
delay(100);
}
calAlm2:
Do_Batt();
delay(50);
if (digitalRead(BTN) == 1) goto calAlm2;
// Done, save value
EEPROM.write(7,Batt >> 8);
EEPROM.write(8,Batt & 255);
digitalWrite(LED3,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED1,LOW);
while (digitalRead(BTN) == 0) {
delay(20);
}
// calibrate alarm 3 voltage
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
// beep 2 times
for (byte i = 1; i <= 2; i++) {
digitalWrite(Buzzer,HIGH);
delay(50);
digitalWrite(Buzzer,LOW);
delay(100);
![Page 14: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/14.jpg)
}
calAlm3:
Do_Batt();
delay(50);
if (digitalRead(BTN) == 1) goto calAlm3;
// Done, save value
EEPROM.write(9,Batt >> 8);
EEPROM.write(10,Batt & 255);
digitalWrite(LED2,LOW);
digitalWrite(LED1,LOW);
while (digitalRead(BTN) == 0) {
delay(20);
}
// read EEPROM data
// min voltage
Vmin = EEPROM.read(1);
Vmin = Vmin << 8;
Vmin = Vmin + EEPROM.read(2);
// max voltage
Vmax = EEPROM.read(3);
Vmax = Vmax << 8;
Vmax = Vmax + EEPROM.read(4);
// alarm 1 voltage
Alm1 = EEPROM.read(5);
Alm1 = Alm1 << 8;
![Page 15: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/15.jpg)
Alm1 = Alm1 + EEPROM.read(6);
// alarm 2 voltage
Alm2 = EEPROM.read(7);
Alm2 = Alm2 << 8;
Alm2 = Alm2 + EEPROM.read(8);
// alarm 3 voltage
Alm3 = EEPROM.read(9);
Alm3 = Alm3 << 8;
Alm3 = Alm3 + EEPROM.read(10);
// set calibrate flag
EEPROM.write(11,123);
}
//------------------------------------------------------------------------------------------------------------------------------------
// Read A/D and convert reading
//------------------------------------------------------------------------------------------------------------------------------------
void Do_Batt() {
analogReference(INTERNAL);
delay(10); // delay for A/D to set
// read batt voltage (take average of 100 readings)
long TempBatt = 0;
for (byte i = 1; i <=100; i++) {
TempBatt = TempBatt + analogRead(BatIn);
}
TempBatt = TempBatt/100;
![Page 16: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/16.jpg)
TempBatt = TempBatt;
Batt = TempBatt;
unsigned int DisplayBat = Batt;
DisplayBat = constrain(DisplayBat, Vmin, Vmax);
Range = map(DisplayBat, Vmin, Vmax, 1, 6);
oldADCSRA = ADCSRA;
}
//------------------------------------------------------------------------------------------------------------------------------------
// Display on LEDs
//------------------------------------------------------------------------------------------------------------------------------------
void Do_LEDs() {
// Full
if (Range == 6) {
digitalWrite(LED6,HIGH);
digitalWrite(LED5,HIGH);
digitalWrite(LED4,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
}
// > 80%
if (Range == 5){
digitalWrite(LED6,LOW);
digitalWrite(LED5,HIGH);
![Page 17: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/17.jpg)
digitalWrite(LED4,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
}
// > 60%
if (Range == 4){
digitalWrite(LED6,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED4,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
}
// > 40%
if (Range == 3) {
digitalWrite(LED6,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED3,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
}
// > 20%
![Page 18: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/18.jpg)
if (Range == 2) {
digitalWrite(LED6,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED2,HIGH);
digitalWrite(LED1,HIGH);
}
// < 20%
if (Range == 1) {
digitalWrite(LED6,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED1,HIGH);
}
}
//------------------------------------------------------------------------------------------------------------------------------------
// Sound buzzer
//------------------------------------------------------------------------------------------------------------------------------------
void Do_Buzzer() {
// Reset Mutes
if (Range == 4) {
![Page 19: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/19.jpg)
Mute1 = 0;
Mute2 = 0;
}
// REset beep flags
if (Batt > Alm1) {
Beep1 = 0;
Beep2 = 0;
}
// Alarm 1
if ( (Batt > Alm2) and (Batt <= Alm1) ) {
Beep1 = 1;
if (Mute1 == 0) {
digitalWrite(Buzzer,HIGH);
delay(50);
digitalWrite(Buzzer,LOW);
}
}
// Alarm 2
if ( (Batt > Alm3) and (Batt <= Alm2) ) {
Beep2 = 1;
if (Mute2 == 0) {
for (byte i = 1; i <=2; i++) {
digitalWrite(Buzzer,HIGH);
delay(50);
digitalWrite(Buzzer,LOW);
![Page 20: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/20.jpg)
delay(100);
}
}
}
// Alarm 3
if (Batt <= Alm3) {
for (byte i = 1; i <=3; i++) {
digitalWrite(Buzzer,HIGH);
delay(50);
digitalWrite(Buzzer,LOW);
delay(100);
}
}
}
//------------------------------------------------------------------------------------------------------------------------------------
// Put device into sleep
//------------------------------------------------------------------------------------------------------------------------------------
void sleep() {
pinMode(LED1,INPUT);
pinMode(LED2,INPUT);
pinMode(LED3,INPUT);
pinMode(LED4,INPUT);
pinMode(LED5,INPUT);
![Page 21: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/21.jpg)
pinMode(LED6,INPUT);
pinMode(Buzzer,INPUT);
MCUSR = 0; // clear various "reset" flags
WDTCSR = bit (WDCE) | bit (WDE); // allow changes, disable reset, enable Watchdog interrupt
// set interval (see datasheet p55)
//WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); // 128K cycles = approximativly 1 second
WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay
wdt_reset(); // start watchdog timer
set_sleep_mode (SLEEP_MODE_PWR_DOWN); // prepare for powerdown
sleep_enable();
// Do not interrupt before we go to sleep, or the
// ISR will detach interrupts and we won't wake.
noInterrupts ();
// will be called when pin D2 goes low
attachInterrupt (0, Btn_ISR, LOW);
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE);
MCUCR = bit (BODS);
oldADCSRA = ADCSRA;
ADCSRA &= ~(1<<ADEN); //Disable ADC
ACSR = (1<<ACD); //Disable the analog comparator
DIDR0 = 0x3F; //Disable digital input buffers on all ADC0-ADC5 pins
![Page 22: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/22.jpg)
DIDR1 = (1<<AIN1D)|(1<<AIN0D); //Disable digital input buffer on AIN1/0
power_twi_disable();
power_spi_disable();
power_usart0_disable(); //Needed for serial.print
power_timer0_disable(); //Needed for delay and millis()
power_timer1_disable();
power_timer2_disable(); //Needed for asynchronous 32kHz operation
// We are guaranteed that the sleep_cpu call will be done
// as the processor executes the next instruction after
// interrupts are turned on.
interrupts (); // one cycle
sleep_cpu (); // power down !
}
//------------------------------------------------------------------------------------------------------------------------------------
// Wake-up device and set up
//------------------------------------------------------------------------------------------------------------------------------------
void wakeup() {
//power_twi_enable();
//power_spi_enable();
//power_usart0_enable();
power_timer0_enable();
//power_timer1_enable();
![Page 23: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/23.jpg)
//power_timer2_enable();
power_adc_enable();
ADCSRA = oldADCSRA;
// re-enable output pins
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(LED5,OUTPUT);
pinMode(LED6,OUTPUT);
pinMode(Buzzer,OUTPUT);
Told = millis();
}
//------------------------------------------------------------------------------------------------------------------------------------
// watchdog interrupt
//------------------------------------------------------------------------------------------------------------------------------------
ISR (WDT_vect)
{
wdt_disable(); // disable watchdog
}
//------------------------------------------------------------------------------------------------------------------------------------
// Button interrupt
//------------------------------------------------------------------------------------------------------------------------------------
void Btn_ISR () { // button interrupt
![Page 24: Led Voltage Monitor](https://reader036.vdocuments.site/reader036/viewer/2022062313/563db82f550346aa9a91552f/html5/thumbnails/24.jpg)
// cancel sleep as a precaution
sleep_disable();
BtnDwn = 1;
// must do this as the pin will probably stay low for a while
detachInterrupt (0);
}