led voltage monitor

26
/* 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

Upload: eduard-toma

Post on 04-Dec-2015

220 views

Category:

Documents


0 download

DESCRIPTION

Arduino sketch

TRANSCRIPT

Page 1: Led Voltage Monitor

/*

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

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

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

// 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

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

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

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

}

}

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

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

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

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

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

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

}

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

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

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

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

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

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

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

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

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

//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

// cancel sleep as a precaution

sleep_disable();

BtnDwn = 1;

// must do this as the pin will probably stay low for a while

detachInterrupt (0);

}