Close

The code

A project log for Blinking 6W of LEDs

Blinking (2x3W) LEDs with an ATTiny45 and a 240mAh battery

non-iceNon-ICE 10/01/2015 at 18:430 Comments

/*
Dronestrober with BMS and charger

when running on 4.4 volt or less it will strobe leds
when run on more it will charge the battery to (approx.) 4.2 volt, let it drop to 4.0 before recharge
will cut off operation at cell voltage about 3 volts

dji phantom pro 3 lower leg 9x7mm



flashing status readout

battery mode:
Vcc x.x volts
2 sec delay
battery pin read, nonsense
2 sec delay
flashing operation starts.


USB power mode:
Vcc x.x volts, ususally 5 blinks then 3 sec delay (5 volts)
at least 2 sec delay
battery x.x volts, 1 sec delay is the decimal separator
2 sec delay
charging mode starts:
flash every second: CHARGING
flash every 5 seconds: CHARGING DONE

*/




//sleep stuff
#include <avr/sleep.h>
#include <avr/wdt.h>
//#include <avr/power.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



//for sleep mode watchdog timer
volatile boolean f_wdt = 1;


const int batpin = 3; // D3 and A3 for charging ans sensing battery voltage.
const int ledpin = 4; // LED pin -> mosfet -> LED
const int potpin = 1; // analogue input 1 (pin 2) for strobe setting, read only first 60 secs. or something.

//battery data
const int batmax = 4080; //max battery charge voltage mV
const int batrecharge = 3950; //restart charge coltage mV
const int batmin = 3100; //min battery charge voltage mV
const int chargethreshold = 4400; //charge vs operation threshold

int voltage; //battery measured
int sensorValue; //temp readvalue
int debug; //debug



//variables will change:
int runmode=1;
int wdduration=5;
int blinks;

int ond=20; //on delay for LED
int itv; //interval 1 for LED sleepdelay
int sitv; //interval 2 for LED sleepdelay

void setup() {
//internal voltage reference
//analogReference( INTERNAL2V56_NO_CAP );
//indicate on state
digitalWrite(ledpin,HIGH);
delay(10);
digitalWrite(ledpin,LOW);
//sleep before sensing input voltage.
setup_watchdog(8); // approximately 4 seconds sleep before starting operation.
system_sleep();

delay(10);
//show Vcc
int bdebug=readVcc()/1000;
int adebug=(readVcc()/100)-(bdebug*10);
while (bdebug>0) {
digitalWrite(ledpin, HIGH);
delay(1);
digitalWrite(ledpin, LOW);
delay(400);
bdebug--;
}
delay(1000);
while (adebug>0) {
digitalWrite(ledpin, HIGH);
delay(1);
digitalWrite(ledpin, LOW);
delay(400);
adebug--;
}

delay(2000);

//read input voltage
if (readVcc() > chargethreshold) {
runmode=1; //runmode for charging.
}
else {
runmode=2; //runmode for strobing
}



pinMode(batpin, INPUT);
pinMode(ledpin, OUTPUT);
pinMode(potpin, INPUT);

}



void loop(){

if (f_wdt==1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
f_wdt=0; // reset flag
}



//check runmode
//pinMode(batpin,INPUT);
sensorValue = analogRead(batpin);
voltage = (1000 * (sensorValue * (5.0 / 1023)));

if (debug!= true) {
int bdebug=voltage/1000;
int adebug=(voltage/100)-(bdebug*10);
while (bdebug>0) {
digitalWrite(ledpin, HIGH);
delay(1);
digitalWrite(ledpin, LOW);
delay(400);
bdebug--;
}
delay(1000);
while (adebug>0) {
digitalWrite(ledpin, HIGH);
delay(1);
digitalWrite(ledpin, LOW);
delay(400);
adebug--;
}

delay(2000);
debug=true;
}


if (runmode==1) { //charging

if (voltage <= batmax) { // charge
pinMode(batpin,OUTPUT);
digitalWrite(batpin,HIGH);
delay(1000);
digitalWrite(ledpin,HIGH);
delayMicroseconds(50);
digitalWrite(ledpin,LOW);
digitalWrite(batpin,LOW);
pinMode(batpin,INPUT);
delay(2);
} else {
runmode=3;
}
}

if (runmode==2) { //flashing
if (readVcc() > batmin) { // strobe

if (blinks<250) { //stop measuring pot if over 250 blinks to lock blinkrate
//read pot for sleeptimers
blinks++;
int pot = analogRead(potpin); //pot read value
if (pot < 100) {itv=2;; sitv=0;}
if (pot >= 100 && pot <=199) {itv=2;sitv=1;}
if (pot >= 200 && pot <=299) {itv=2;sitv=2;}
if (pot >= 300 && pot <=399) {itv=2;sitv=3;}
if (pot >= 400 && pot <=499) {itv=3;sitv=1;}
if (pot >= 500 && pot <=599) {itv=3;sitv=2;}
if (pot >= 600 && pot <=699) {itv=3;sitv=3;}
if (pot >= 700 && pot <=799) {itv=4;sitv=1;}
if (pot >= 800 && pot <=899) {itv=4;sitv=2;}
if (pot >= 900 && pot <=1024) {itv=4;sitv=3;}
}
//sleep
if (wdduration==itv) {
wdduration=itv+sitv;
}
else
{
wdduration=itv;
}

//blink
digitalWrite(ledpin,HIGH);
delay(ond);
digitalWrite(ledpin,LOW);

setup_watchdog(wdduration);
system_sleep();
}
else { // else battery is dead
setup_watchdog(9);
system_sleep();
}
}
if (runmode==3) {
if (voltage <= batrecharge) { // charge
runmode=1;
}
digitalWrite(ledpin,HIGH);
delayMicroseconds(50);
digitalWrite(ledpin,LOW);
delay(5000);
}
}



// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF

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 timed out
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}

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

byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;

MCUSR &= ~(1<<WDRF);
// start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}

// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
f_wdt=1; // set global flag
}



long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring

uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both

long result = (high<<8) | low;

result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
//result = 1100000L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}

Discussions