led voltage monitor

Post on 04-Dec-2015

220 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Arduino sketch

TRANSCRIPT

/*

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

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

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.

*/

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

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);

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

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();

}

}

}

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:

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++) {

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++) {

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);

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);

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);

}

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;

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;

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);

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%

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) {

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);

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);

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

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();

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

// cancel sleep as a precaution

sleep_disable();

BtnDwn = 1;

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

detachInterrupt (0);

}

top related