Skip to content

Instantly share code, notes, and snippets.

@dwhacks
Last active December 4, 2020 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dwhacks/8055309 to your computer and use it in GitHub Desktop.
Save dwhacks/8055309 to your computer and use it in GitHub Desktop.
Attiny 85 blinking RGB LED strip + battery monitor
/*
Attiny85_batteryMonitor
Ideas borrowed from: https://github.com/unixbigot/Flat-Mate
modified for arduino tiny core by DWhacks
Added control of RGB LED strip or possibly just an RGB LED for use as a rear Bicycle light
*@@ Voltage trigger levels.
*
* Battery voltage is read through a voltage divider and compared to the internal voltage reference.
*
* If
* Vin ----+
* R1
* +----- Vout (BATI)
* R2
* |
* =
* . (gnd)
*
* Then Vout = Vin * ( R2 / (R1 + R2) )
*
*
* eg. R1=12k R2=1k => Vout = Vin * (1000 / (1000 + 12000))
* Vin * 0.0769
*
* R1=20k R2=10k => Vout = Vin * 0.3333 Ileak = 0.4mA @ 12v
* R1=2k2 R2=1k => Vout = Vin * 0.3125
* R1=3k3 R2=1k => Vout = Vin * 0.232
* R1=3k9 R2=1k => Vout = Vin * 0.204 Ileak = 2.4mA @ 12v
* R1=39k R2=10k => Vout = Vin * 0.204 Ileak = 0.24mA @ 12v
* R1=4k7 R2=1k => Vout = Vin * 0.175
* R1=10k R2=1k => Vout = Vin * 0.0909 Ileak = 1mA @ 12v
* R1=12k R2=1k => Vout = Vin * 0.0769 Ileak = 0.92mA @ 12v
*
* Fully charged LiPo is 4.23v/cell, discharged is 2.7v/cell (nominal voltage 3.7v/cell)
* For battery endurance, do not discharge below 3.0v/cell (aircraft users commonly use 2.9v/cell as limit)
*
* A 2-cell battery (nominally 7.46v) varies from 8.46v to 5.40v, with low-volt alert at 6.00v
* A 3-cell battery (nominally 11.1v) thus varies from 12.9v to 8.10v, with low-volt alert at 9.00v
* A 4-cell battery (nominally 14.8v) thus varies from 16.9v to 10.8v, with low-volt alert 12 12.0v
* NOTE: a 4-cell battery requires a different voltage divider than 2-and-3 cells (use 15:1 not 12:1)
*
*
*@@ Analog read values for defined voltage levels
*
* In AVR-worldview, we use 12:1 voltage divider and read 10-bit ADC comparisons versus AREF (1.1v)
*
* So 12v becomes ~1.00V when divided.
* Compared to 1.1v reference this gives an ADC result of 1024*(1.0/1.1) == 859
*
* An alternative approach is to use a smaller voltage divisor and compare
* against Vcc (5.0v), but in practice a 12:1 divisor is easier to achieve
* due to the standard first preference resistor value series.
*
* You can use these Emacs lisp defuns to calculate threshold analog values for your voltage levels
*
* for 4-cell, use a 15:1 divider
*
*
/* Use a 12:1 voltage divider */
/* Use a 12:1 voltage divider */
#define VL_FULL 859
#define VL_GOOD 715 //10
#define VL_LOW 687 //9.6
#define VL_CRIT 644
const int batteryPin = 3; //V+ from battery connected to analog1 physical pin 2
// Define the number of samples to keep track of. The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input. Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.
const int numReadings = 3;
int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
int redPin = 1;
int greenPin = 4;
int bluePin = 0;
long randr = 0;
long randg = 0;
long randb = 0;
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time
void setup()
{
analogReference(INTERNAL);
pinMode(batteryPin, INPUT);
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0; // initialize all the readings to 0
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
randomSeed (analogRead (3));
}
void loop()
{
averageVoltage(); //get average voltage from function
int voltage = average;
randOn = random (5, 100); // generate ON time between 0.1 and 1.2 seconds
randOff = random (10, 200); // generate OFF time between 0.2 and 0.9 seconds
randr = random (0, 255);
randg = random (0, 255);
randb = random (0, 255);
if (voltage >= VL_GOOD){ //if the battery voltage is above GOOD then slow fade
setColor(255, 0, 0); // red
delay(randOn + 20);
setColor(randr, randg, randb); // random colour
}
else if (voltage >= VL_LOW){ //If the battery voltage is above LOW and below GOOD then fast fade
/*Fade Up*/
for(byte i=1; i<50; i++) {
byte on = i;
byte off = 50-on;
for( byte a=0; a<100; a++ ) {
digitalWrite(redPin, HIGH);
delayMicroseconds(on);
digitalWrite(redPin, LOW);
delayMicroseconds(off);
}
}
/*Fade Down*/
for(byte i=1; i<50; i++) {
byte on = 50-i;
byte off = i;
for( byte a=0; a<100; a++ ) {
digitalWrite(redPin, HIGH);
delayMicroseconds(on);
digitalWrite(redPin, LOW);
delayMicroseconds(off);
}
}
}
else if (voltage < VL_LOW){ //If the battery voltage is below LOW then cut of power and fast blink!
digitalWrite(redPin, HIGH);
delay(100);
digitalWrite(redPin, LOW);
delay(100);
}
}
void averageVoltage() {
// subtract the last reading:
total= total - readings[index];
// read from the sensor:
readings[index] = analogRead(batteryPin);
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;
// if we're at the end of the array...
if (index >= numReadings)
// ...wrap around to the beginning:
index = 0;
// calculate the average:
average = total / numReadings;
delay(1); // delay in between reads for stability
}
void setColor(int red, int green, int blue)
{
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
delay(randOn);
analogWrite(redPin, 0);
analogWrite(greenPin, 0);
analogWrite(bluePin, 0);
delay(randOff);
}
//end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment