I'm working on some code for an ATTiny85 that uses the V-USB bootloader. As such I've only got about 5.3kb of usable flash memory.
I'm currently at 98% of that but really would like to add more functionality. I've run over my code a few times but not really sure where else I could optimize it. But then I started thinking about 2 libraries I'm using, the NeoPixel library, and also a OneButton library.
But I'm wondering, would I save program space by basically copying the library functionality directly into my sketch, rather than including them? Or is the contents of the .h file not actually included in the compiled code, just the C/CPP file itself?
Or, if anyone is curious, can you see something I can optimize in my code?
// avrdude -c usbasp -p attiny85 -b 19200 -U lfuse:w:0xF1:m -U hfuse:w:0xD5:m -U efuse:w:0xFE:m
// avrdude -c usbasp -p attiny85 -b 19200 -U flash:w:flash_me_lv.hex:i
// Use slow clock!
#include <Adafruit_NeoPixel.h>
#include <avr/power.h> // Include for 16Mhz mode
#include <OneButton.h>
#include <EEPROM.h>
#define PIN 0 // LED Pin
Adafruit_NeoPixel strip = Adafruit_NeoPixel(50, PIN, NEO_GRB + NEO_KHZ800);
OneButton button(1, false); // Button on pin 1, active high
uint16_t k, j = 0;
long previousMillis = 0;
long prevMillis = 0;
int voltage;
boolean iterated = false;
byte colwipe = 1;
boolean isFlat = false;
byte wheelcol = 0;
int bright = EEPROM.read(0);
byte dispmode = EEPROM.read(1);
byte wheelcolv[4] = {EEPROM.read(2), EEPROM.read(3), EEPROM.read(4), EEPROM.read(5)};
void setup() {
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
if (F_CPU == 16000000) clock_prescale_set(clock_div_1); // Run at 16Mhz
strip.begin();
strip.show(); // Initialize pixels
strip.setBrightness(bright);
button.attachClick(changeMode);
button.attachDuringLongPress(changeVars);
button.attachLongPressStop(saveVars);
button.attachDoubleClick(turnOff);
// Stuff to write initial EEPROM config
/*EEPROM.write(0, 32);
EEPROM.write(1, 1); // dispmode
EEPROM.write(2, 20); // First colour
EEPROM.write(3, 60); // 2nd colour
EEPROM.write(4, 127); // 3rd colour
EEPROM.write(5, 160); // 4th colour
*/
}
void loop() {
button.tick(); // Check button
if (map(analogRead(1),0,1023,0,5000) < 3300 ){ // If voltage is under 3.3V-ish
isFlat = true;
}
if (isFlat == false){
if (dispmode < 4){ // User-define colours
for (int i=0; i<strip.numPixels(); i++){
strip.setPixelColor(i, Wheel(wheelcolv[dispmode]));
}
strip.show();
} else if (dispmode == 4){ // Colour wipe mode
if (colwipe == 1) {
colorWipe(strip.Color(255, 0, 0), 20); // Red
}
if (colwipe == 2) {
colorWipe(strip.Color(0, 255, 0), 20); // Green
}
if (colwipe == 3) {
colorWipe(strip.Color(0, 0, 255), 20); // Blue
}
} else if (dispmode == 5){ // Rainbow scroll mode
rainbowCycle(1);
} else if (dispmode == 6){ // Slow fade mode
fade(1);
}
} else { // If the battery is flat
sclear();
for (int i=0; i<5; i++){
strip.setPixelColor(0,255,0,0); // Flash the first LED red
strip.show();
delay(1000);
strip.setPixelColor(0,0,0,0);
strip.show();
delay(1000);
}
digitalWrite(4, LOW);
}
}
void changeMode() { // Change the program
if (dispmode < 6){
dispmode++;
j = 0;
k = 0;
//Serial.println(dispmode);
} else {
dispmode = 0;
}
EEPROM.write(1, dispmode); // Save current program to EEPROM for next start
}
void changeVars(){
if (dispmode < 4){ // If in user-define mode, long press changes the colour
if (millis() - prevMillis > 10){
prevMillis = millis();
if (wheelcolv[dispmode] < 255){
wheelcolv[dispmode]++;
} else {
wheelcolv[dispmode] = 0;
}
}
//delay(20);
} else { // In the other modes, long press changes brightness
if (millis() - prevMillis > 40){
prevMillis = millis();
strip.setBrightness(bright);
bright++;
if (bright > 80 ){
bright = 8;
}
//delay(15);
}
}
}
void saveVars(){ // Save config stuff to EEPROM
EEPROM.write(0, bright);
EEPROM.write(2, wheelcolv[0]);
EEPROM.write(3, wheelcolv[1]);
EEPROM.write(4, wheelcolv[2]);
EEPROM.write(5, wheelcolv[3]);
}
void turnOff(){ // Turn the boost converter off
digitalWrite(4, LOW);
}
void sclear() { // Set strip to off
for (int i = 0; i<strip.numPixels(); i++) {
strip.setPixelColor(i,0,0,0);
}
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint16_t wait) {
if(millis() - previousMillis > 40) {
previousMillis = millis();
if (k < strip.numPixels()){
strip.setPixelColor(k, c);
strip.show();
//delay(wait);
k++;
} else {
k = 0;
colwipe++;
if (colwipe > 3){
colwipe = 1;
}
}
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
if (j < 256) {
if (iterated) {
j += 4;
iterated = false;
}
if (k < strip.numPixels()) {
strip.setPixelColor(k, Wheel(((k * 256 / strip.numPixels()) + j)));
k++;
} else {
k = 0;
iterated = true;
}
strip.show();
if (iterated == true){
delay(wait);
//iterated = false;
}
} else {
j = 0;
}
}
void fade(uint8_t wait) { // Whole-strip fade
if (j < 255) {
if (k < strip.numPixels()){
strip.setPixelColor(k,Wheel(j));
k++;
} else {
k = 0;
j += 4;
}
strip.show();
delay(wait);
} else {
j = 0;
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
Cheers