Automatic Voltage Sensing Cigarette Lighter Adaptor | |||||||||||||
October 2014
ConstructionPrinted Circuit BoardThese photos show, on the left, an enlarged layout of the PCB and, on the right, the actual-size artwork.
This photo shows the PCB almost completed. It's just missing the 5.1v zener diode and the ATtiny85.
Some Components
Programming the ATtiny85The ATtiny85 is programmed using the Arduino environment with either an Arduino Uno or a dedicated programmer.It's necessary to define the ATtiny85 core so the Arduino IDE knows about its pins. Be aware there are a couple of different libraries for the ATtiny85 that treat the ATting85's internal registers differently. The library I used is arduino-tiny. The 'README' included in the downloaded zip package contains full instructions for installing it into the Arduino IDE. There are dozens of websites detailing how to use the Arduino Uno as a programmer - particularly for the ATtiny85 - so I won't repeat them in detail here. In brief, the steps are:
The Arduino Sketch/* Car battery voltage monitor - vwlowen.co.uk/arduino/car-voltage-monitor */ /* Uses ATtiny 85 with arduino-tiny core: https://code.google.com/p/arduino-tiny/ */ #include <avr/sleep.h> #include <avr/wdt.h> #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif const float Vref = 5.00; // Actual voltage and resistor values can be set here. const float R1 = 99900.0; // R1 is nominally 100000.0 const float R2 = 21850.0; // R2 is nominally 22000.0 const float resDiv = (R2/(R1 + R2)); // Resistor divider factor applied to measured voltage. const float vLow = 13.50; // Set low voltage threshold (engine off). const float vHigh = 13.75; // Set high voltage threshold (engine running). int LEDpin = 4; // LED flashes at power-down. Full on at power up. int MOSFETpin = 0; // MOSFET power switch gate signal int BATTpin = A3; // Analogue input from the 100K/22K divider. int tim = 10; // Delay between low voltage checks float getVolts() { // Function returns the actual battery volts. int raw = analogRead(BATTpin); float volts = (raw / 1024.0) * Vref; volts = (volts / resDiv); return volts; } void setup() { pinMode(LEDpin, OUTPUT); // Set LED and MOSFET I/O as outputs. digitalWrite(LEDpin, LOW); pinMode(MOSFETpin, OUTPUT); digitalWrite(MOSFETpin, LOW); for (int i=0; i<4; i++) { digitalWrite(LEDpin, HIGH); // Blink LED a few times to show some activity. delay(50); digitalWrite(LEDpin, LOW); delay(50); } setup_watchdog(7); // approximately 2 seconds sleep } void loop() { if (getVolts() <= vLow) { // If battery voltage is low, delay(tim); // delay and check again, but only the if (getVolts() <= vLow) { // first time around. tim = 10; digitalWrite(MOSFETpin, LOW); // If still low, turn off MOSFET. } } if (getVolts() >= vHigh) { // If battery voltage is high, digitalWrite(MOSFETpin, HIGH); // turn on MOSFET and LED. digitalWrite(LEDpin, HIGH); tim = 5000; // Reset low-volts delay timer so it } // will do the delayed double-check next time. if (tim == 10 ) system_sleep(); // If confirmed battery low, enter sleep mode. } // Put system into the sleep state void system_sleep() { cbi(ADCSRA,ADEN); // switch ADC OFF to save power set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here sleep_enable(); sleep_mode(); // System sleeps here sleep_disable(); // System continues execution here when watchdog times out sbi(ADCSRA,ADEN); // switch ADC back ON digitalWrite(LEDpin, HIGH); // Blink LED to show some activity. delay(50); digitalWrite(LEDpin, LOW); if (getVolts() < 12.4) { delay(50); digitalWrite(LEDpin, HIGH); // Blink again to show low battery. delay(50); digitalWrite(LEDpin, LOW); } } // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms // 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec void setup_watchdog(int ii) { // set the required register bits to // set up the watcdog timer. byte bb; if (ii > 9 ) ii=9; bb = ii & 7; if (ii > 7) bb |= (1<<5); bb |= (1<<WDCE); MCUSR &= ~(1<<WDRF); WDTCR |= (1<<WDCE) | (1<<WDE); WDTCR = bb; WDTCR |= _BV(WDIE); } // Watchdog Interrupt Service / is executed when watchdog times out ISR(WDT_vect) { // Include this routine even if it doesn't do anything. }
|