Lichterketten Ferbverläufe mit NeoPixel

Für Arduino


/*
 * NeoPixel Lampen & LED-Strip Steuerung mit Button
 * Für: Arduino UNO, Nano, Mega2560, Digispark USB, ...
 * Bitte beachte: je nach Programmspeicher koennen verschieden viele LED's angeschlossen werden.
 * 
 * BEDIENUNGSANLEITUNG:
 * 
 * WENN DIE LAMPE AN IST:
 * KURZ DRUECKEN: 
 * schaltet zu den verschiedenen Fade-Modi.
 * Es gibt fünf Fade-Modi in den folgenden Farbstimmungen:
 * Orange, Lila, Türkis, Grün, Weiß (weiß= alle Farben)
 * LANG DRUECKEN:
 * die Lampen beginnen die Farbe schnell zu wechseln bis losgelassen wird.
 * So laesst sich eine feste Farbe einstellen.
 * 2X SCHNELL DRUECKEN:
 * Schaltet die Lampen in den Standby.
 * Durch einmaliges kurzes Druecken werden sie wieder eingeschalten.
 * Der zuletzt eingestellte Modi wird nach dem Einschalten wieder abgerufen.
 * 
 * WENN DIE LAMPE AUS IST:
 * KURZ DRUECKEN:
 * Schaltet die Lampe ein.
 * LANG DRUECKEN:
 * Schaltet die Lampe ein und dimmt diese.
 * Die Helligkeit verändert sich, bis man die Taste los lässt.
 * SEHR LANGE DRÜCKEN -> RESET
 * Wird die Lampe beim Einschalten länger als 15 Sekunden gedrückt, wird ein Reset ausgelöst.
 * Die Lampe beginnt nach dem Reset weiß zu blinken, bis man loslässt
 * 
 * WENN DIE LAMPE KAPUTT IST:
 * Sie bekommen 1 Jahr Garantie, d. h. ich repariere Ihnen defekte Lampen, 
 * sofern Sie diese nicht aus Eigenverschulden grob fahrlässig beschädigt haben.
 * SELBER REPARIEREN:
 * Abgebrochene Teile mit farblosen Sekundenkleber oder Zweikomponentenkleber befestigen.
 * VERDRAHTUNG:
 * WS2812: DI an Pin 0, GND zu GND, VIN/5V an 5V
 * Button zwischen Pin 1 & Pin 2
 * ENTSORGUNG:
 * Ich kann mich um die fachgerechte Demontage und Entsorgung kümmern.
 * ANSONSTEN:
 * Die Elektronik ausbauen und als Elektronikmüll entsorgen.
 * Den Lampenschirm in den gelben Sack legen.
 * Den Untersetzer je nach Material:
 * Gips zum Bauschutt, Holz zu den Gartenabfällen, Glas & Spiegel zum Altglas, Aluuntersetzer in Alusammelbehälter.
 * 
 * Autor: Veit Goetz
 * Date:  06.01.2017 V.1.1
 *        15.01.2017 V.1.2
 *        20.02.2017 V.1.3
 *        23.03.2017 V.1.3.1
 *        27.03.2017 V.1.4
 * Email: goetz@veit.tk
 * Web:   www.goetz-veit.tk
 *        www.3d-druck.tk
 */

/* ------------------ Librarys ------------------- */


//#include <avr/wdt.h>
/*void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
void wdt_init(void)
{
 MCUSR = 0;
 wdt_disable();
 return;
}*/

 // Include Librarys
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>

/* ---------------- Main Settings ---------------- */

#define ledPin     1  // Pin to connect the LED's
#define pixels     12 // Number of pixels - Anzahl LEDs
#define buttonOut  3  // Button pin (output)
#define buttonIn   2  // Button pin
#define RESET_PIN  4  // Wire to reset pin

/* ---------------- other Settings --------------- */

// Hier koennen Farben definiert werden, die in den Farbverlaufen vorkommen sollen
const byte colors[][3] = {// Statische Farben {r, g, b}, -> Nummerierung automatisch nach Reihenfolge
  {255, 150, 150}, // 0=White
  {255,   90,   0}, // 1=Yellow
  {255,   60,   0}, // 2=yellow-orange
  {255,   40,   0}, // 3=Orange
  {255,   0,   0}, // 4=Red
  {255,   0,  80}, // 5=Pink
  {150,   0, 200}, // 6=Purple
  {  0,   0, 255}, // 7=Blue
  {  0, 186, 255}, // 8=Light Blue
  {  0, 255,   0}, // 9=Green
  {200, 255,   0}, // 10=Light green
};
const byte colorCnt = 11; // number of colors - Anzahl der Farben

// hier koennen verschiedene Farbverlaeufe erstellt werden
const byte modes[][colorCnt+1] = {   // Fade-Programme {Anzahl Farben, [Farbnummer] },
  {10, 0,2,6,3,8,5,1,7,4,9}, // Fade each color
  {3, 1,10,3},               // Fade yellow
  {4, 3,1,2,4},                // Fade orange
  {3, 4,3,5},                // Fade red
  {4, 5,6,7},                // Fade purple
  {3, 7,8,6},                // Fade Blue
  {4, 9,10,8,1},             // Fade green
};
const byte modeCnt = 7; // number of Fade-programmes - Anzahl der Fade-Programme im Array

const unsigned int fadeSteps   = 255; // default:255 // Anzahl Zwischenschritte zwischen zwei Farben
const unsigned int fadeDelay   = 20;  // default:20  // Pause zwischen zwei Zwischenschritten
/* LED's  delay
 *  7     20
 *  12    17
 *  16    15
 *  24    10
 */
const unsigned int fastFade    = 2;   // default:2   // Pause bei schnellem Farbwechsel (bei 24 LED's:1)
const float fadeSize           = 0.1; // default:0.5 // Groeße des Farbverlaufs (0-1) - 1=alle LED's gleichzeitig 0=alle hintereinander
const unsigned int longPress   = 500; // default:500 // time (in ms) for long pressdown - Schwellwert für langen Tastendruck (in ms)
const unsigned int dubblePress = 600; // default:600 // max. time for dubble pressdown - Schwellwert für zweifachen Tastendruck

const byte EprAddr1 = 2;  // default:2  // Eeprom address for "mode"
const byte EprAddr2 = 6;  // default:6  // Eeprom address for "color"
const byte EprAddr3 = 10; // default:10 // Eeprom address for "pos"


/* ----------------- global vars ----------------- */

unsigned int mode = 0;         // current Modus (0-4=fade 5=static color)
unsigned int currentColor = 0; // current color
unsigned int pos = 0;          // current fade Position
//int intensy = 255;             // current brightnes
bool swichOff = false;         // Standby = true, wird durch zweifachen Tastendruck geändert

int fadeStartPos = 0;         // Startpixel for color fade, wird automatisch (zufällig) bestimmt

bool buttonPressed = false;    // if the button pressed - zwischenspeicher, wenn Button gedrückt ist
unsigned long downTime = 0;    // time of Pressdown - Zwischenspeicher für die Dauer, die der Button gedrückt ist
bool longStart = false;        // did the long pressdown allready start - zwischenspeicher , ob dies jetzt ein langer Tastendruck ist

bool modeSaved = true;    // Zwischenspeicher, ob aktueller Mode schon im EEPROM abgelegt wurde

/* ----------------- Initialize ------------------ */

Adafruit_NeoPixel strip = Adafruit_NeoPixel(pixels, ledPin, NEO_GRB + NEO_KHZ800); // initialize (LED's, pin, mode)


void setup() {
  initVars();
  #ifdef buttonOut
    pinMode(buttonOut, OUTPUT); // set the button as output
    digitalWrite(buttonOut, LOW); // Set one button PIN to LOW
  #endif
  pinMode(buttonIn, INPUT_PULLUP); // set the button as input with pullup
  strip.begin(); // start library
  strip.setBrightness(255); // set the max Brightness (0-255)
}

#ifdef RESET_PIN
void softReset()
{
  pinMode(RESET_PIN, OUTPUT);    // sets the digital pin as output
  digitalWrite(RESET_PIN, LOW);  // sets the LED off
  delay(20);
  digitalWrite(RESET_PIN, HIGH); // sets the LED on
  
}
#endif

/* ------------------ Main Loop ------------------ */

void loop() { // code runs repeatly
  if(!swichOff&&(mode<modeCnt||longStart)){ // if in Fade mode
    pos = (pos+1) % fadeSteps; // Fade
    if(pos==0){ // new color
      currentColor = (currentColor+1) % ((mode<modeCnt)?modes[mode][0]:colorCnt); // calculate color
      fadeStartPos = random(pixels-1); // get random start position
    }
    setRgb(); // update LED's
  }

  delay((mode<modeCnt||swichOff)?fadeDelay:fastFade); // slow/fast fade

  
  bool btState = 1-digitalRead(buttonIn); // read button
  if(btState==LOW&&!swichOff&&!modeSaved&&millis()-downTime>dubblePress){ // save current mode
    EEPROM.write(EprAddr1, mode); // Save in EEPROM
    modeSaved = true; // mark data as saved
  }
  if(buttonPressed==true){ // button was still pressed down (by the last request)
    if(btState==LOW){ // ButtonPressUp now
      longStart = false;
      if(!swichOff){ // if LED is on -> swich of
        if(millis()-downTime<longPress){ // Short pressup
          changeMode(1); // next Fade-Mode
          modeSaved = false; // mode was changed but not saved in EEPROM yet
        }else{ // long pressup
          EEPROM.write(EprAddr2, currentColor); // Save current static color in EEPROM
          EEPROM.write(EprAddr3, pos); // save current static fade position in EEPROM
        }
      }else if(downTime>0){ // led was off -> swich on
        if(millis()-downTime<longPress){ // Short pressup
          swich_On(); // Swich the lamp on
          swichOff=false; // save, that lamp is now swiched on
        }else{ // swich on with long press
          #ifdef RESET_PIN
            softReset(); //call reset
          #endif
        }
      }
    }else if(!longStart&&millis()-downTime>longPress){ // start long Pressdown
      if(downTime>0){ // lamp is on
        longStart = true;
        if(!swichOff){ // if the lamp is allready on
          if(mode!=modeCnt){ // from fade to static mode
            currentColor = modes[mode][1+currentColor]; // get current color
            mode = modeCnt; // set to static mode (fast fade each color)
            EEPROM.write(EprAddr1, mode); // Save "static mode" to EEPROM
          }
        }
      }
    }
  }
  else if(buttonPressed==false&&btState==HIGH){ // new ButtonPressDown
    if(millis()-downTime<dubblePress&&!swichOff){ // dubble pressdown
      swich_Off(); // swich off
      downTime = 0;
      //asm volatile ( "jmp 0");  
    }else{
      downTime = millis(); // save the time of Pressdown
      if(swichOff){
        //swich_On(); // Swich the lamp on
      }
    }
  }
  if(buttonPressed!=btState) buttonPressed = btState; // ButtonChange

}

/* -------------------- init --------------------- */

void initVars(){
  mode = EEPROM.read(EprAddr1);// %(modeCnt+1); // get the current mode
  currentColor = EEPROM.read(EprAddr2)%((mode<modeCnt)?modes[mode][0]:colorCnt); // get the current color
  pos = EEPROM.read(EprAddr3)%(fadeSteps); // get the current fade pos.
  strip.setBrightness(200); // set Brightness && Initialize all pixels
  return;
}


/* -------------- Lamp Swich on/off -------------- */

void swich_On(){
  mode = EEPROM.read(EprAddr1);//%(modeCnt+1); // get the current mode
  currentColor = EEPROM.read(EprAddr2); // get the current color
  pos = EEPROM.read(EprAddr3)%(fadeSteps); // get the current fade pos.
  setRgb(); // Update mode on LED's
  return;
}

void swich_Off(){
  swichOff=true; // swich off
  for(unsigned long n=0;n<pixels; n++){ // Set Color to each LED
    //strip.setPixelColor(n, 0, 0, 0); // Swich OFF
    strip.setPixelColor(n, strip.Color(0, 0, 0)); // Swich OFF
  }
  strip.show(); // Show update on LED-Strip
  return;
}


/* ---------- Caclculate RGB and upload ---------- */

void setRgb(){
  float col[3];
  float fadeStart = (0.5+fadeSize)*pos/fadeSteps;
  float fadeEnd = fadeStart-fadeSize;
  for(long n=0;n<pixels; n++){ // Set Color to each LED
    float distance = 1.0*abs(n-fadeStartPos)/pixels; if(distance>0.5) distance = 1-distance;
    float intensy = (distance>=fadeStart)?0:(distance<=fadeEnd)?1:(fadeStart-distance)/fadeSize;
    if(mode==modeCnt) intensy = 1.0*pos/fadeSteps;
    for(byte n=0;n<3;n++){ // calculate RGB-Value
      byte col1 = colors[ (mode<modeCnt) ? modes[mode][1+currentColor] : currentColor ][n];
      byte col2 = colors[ (mode<modeCnt) ? modes[mode][1+((currentColor+1)%modes[mode][0])] : ((currentColor+1)%colorCnt) ][n];
      col[n] = 1.0*(col2-col1)*intensy + col1 ;
    }
    //strip.setPixelColor(n, col[0], col[1], col[2]);
    strip.setPixelColor(n, strip.Color(col[0], col[1], col[2]));
  }
  strip.show(); // Show update on LED-Strip
  return;
}

/* ---------- Swich between Color-Modes ---------- */

void changeMode(int change){ // Update fade mode & LED's
  mode = (mode+change)%(modeCnt);
  pos=0;
  currentColor = 0; //mode%colorCnt;
  setRgb();
  return;
}


© Veit Götz 2012 - 2019
Impressum
Datenschutz
Statistiken
Spenden