Files @ 964740ba66ed
Branch filter:

Location: Wearables/Neopixel-Goggles/Neopixel_Goggles.ino - annotation

Dennis Fink
Added readme
a4ad34889569
fb907b72aae9
6ca9558755f3
a4ad34889569
a4ad34889569
a4ad34889569
6ca9558755f3
6255b67a731b
a4ad34889569
a4ad34889569
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
2de2ee7f659f
2de2ee7f659f
2de2ee7f659f
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6255b67a731b
6ca9558755f3
6255b67a731b
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
03483f073427
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
03483f073427
03483f073427
03483f073427
a4ad34889569
a4ad34889569
03483f073427
a4ad34889569
03483f073427
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
03483f073427
a4ad34889569
03483f073427
a4ad34889569
a4ad34889569
03483f073427
a4ad34889569
03483f073427
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
03483f073427
03483f073427
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a5be02268126
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
03483f073427
03483f073427
03483f073427
03483f073427
03483f073427
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
0dd7c07f8c8e
a4ad34889569
a4ad34889569
a4ad34889569
6255b67a731b
6255b67a731b
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
e12ecbf1cb9f
95fca30ce7ec
95fca30ce7ec
95fca30ce7ec
95fca30ce7ec
95fca30ce7ec
95fca30ce7ec
e12ecbf1cb9f
a4ad34889569
e12ecbf1cb9f
a4ad34889569
a4ad34889569
a4ad34889569
95fca30ce7ec
6255b67a731b
e292df7a2a7a
6255b67a731b
95fca30ce7ec
a4ad34889569
a4ad34889569
6255b67a731b
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
6255b67a731b
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
a4ad34889569
#include <Adafruit_NeoPixel.h>

#ifdef __AVR_ATtiny85__
#include <avr/power.h>
#endif

// Begin config section

#define PIN 0

#define BRIGHTNESS 64

#define MODE_CHANGE_TIME 10000

#define COLOR_MIN 0
#define COLOR_MAX 255

#define STEPS_MIN 5
#define STEPS_MAX 10

#define SLOW_INTERVAL_MIN 25
#define SLOW_INTERVAL_MAX 55

#define RAINBOW_CYCLE_MIN_INTERVAL 1
#define RAINBOW_CYCLE_MAX_INTERVAL 10

#define BLINK_MIN_INTERVAL 250
#define BLINK_MAX_INTERVAL 500

// End config section

enum  pattern {
  RAINBOW_CYCLE,
  COLOR_WIPE,
  DOUBLE_COLOR_WIPE,
  SCANNER,
  DOUBLE_SCANNER,
  RANDOM,
  DOUBLE_RANDOM,
  BLINK,
  DOT
};

class NeoPatterns : public Adafruit_NeoPixel {
  public:
    pattern  ActivePattern;

    uint16_t Interval;
    unsigned long lastUpdate;
    uint32_t PixelColor;
    uint16_t TotalSteps;
    uint16_t Index;

    void (*OnComplete)();

    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)()) : Adafruit_NeoPixel(pixels, pin, type) {
      OnComplete = callback;
    }

    void Update() {
      if ((millis() - lastUpdate) > Interval) {
        lastUpdate = millis();
        switch (ActivePattern) {
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case DOUBLE_COLOR_WIPE:
            DoubleColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case DOUBLE_SCANNER:
            DoubleScannerUpdate();
            break;
          case RANDOM:
            RandomUpdate();
            break;
          case DOUBLE_RANDOM:
            DoubleRandomUpdate();
            break;
          case BLINK:
            BlinkUpdate();
            break;
          case DOT:
            DotUpdate();
            break;
          default:
            break;
        }
      }
    }

    void Increment() {
      show();
      Index++;
      if (Index >= TotalSteps) {
        Index = 0;
        OnComplete();
      }
    }

    void RainbowCycle(uint16_t interval) {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
    }

    void RainbowCycleUpdate() {
      for (int i = 0; i < numPixels(); i++) {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      Increment();
    }

    void ColorWipe(uint32_t color, uint16_t interval) {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      PixelColor = color;
      Index = 0;
    }

    void ColorWipeUpdate() {
      setPixelColor(Index, PixelColor);
      Increment();
    }

    void DoubleColorWipe(uint32_t color, uint16_t interval) {
      ActivePattern = DOUBLE_COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels() / 2;
      PixelColor = color;
      Index = 0;
    }

    void DoubleColorWipeUpdate() {
      DoubleSet(Index, PixelColor);
      Increment();
    }

    void Scanner(uint32_t color, uint16_t interval) {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      PixelColor = color;
      Index = 0;
    }

    void ScannerUpdate() {
      for (int i = 0; i < numPixels(); i++) {
        uint32_t c;
        if (i == Index || i == TotalSteps - Index) {
          c = PixelColor;
        }
        else {
          c = DimColor(getPixelColor(i));
        }
        setPixelColor(i, c);
      }
      Increment();
    }

    void DoubleScanner(uint32_t color, uint16_t interval) {
      ActivePattern = DOUBLE_SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() / 2);
      PixelColor = color;
      Index = 0;
    }

    void DoubleScannerUpdate() {
      for (int i = 0; i < numPixels() / 2; i++) {
        uint32_t c;
        if (i == Index) {
          c = PixelColor;
        }
        else {
          c = DimColor(getPixelColor(i));
        }
        DoubleSet(i, c);
      }
      Increment();
    }

    void Random(uint32_t color, uint16_t steps, uint16_t interval) {
      ActivePattern = RANDOM;
      Interval = interval;
      TotalSteps = steps;
      PixelColor = color;
      Index = 0;
    }

    void RandomUpdate() {
      setPixelColor(random(numPixels()), PixelColor);
      Increment();
    }

    void DoubleRandom(uint32_t color, uint16_t steps, uint16_t interval) {
      ActivePattern = DOUBLE_RANDOM;
      Interval = interval;
      TotalSteps = steps;
      PixelColor = color;
      Index = 0;
    }

    void DoubleRandomUpdate() {
      int i = random(numPixels() / 2); // this saves 4 bytes instead of calling random in the function call of DoubleSet
      DoubleSet(i, PixelColor);
      Increment();
    }

    void Blink(uint32_t color, uint16_t steps, uint16_t interval) {
      ActivePattern = BLINK;
      Interval = interval;
      if (steps % 2 != 0) {
        steps++;
      }
      TotalSteps = steps;
      PixelColor = color;
      Index = 0;
    }

    void BlinkUpdate() {
      uint32_t c;
      if (Index % 2 == 0) {
        c = PixelColor;
      } else {
        c = Color(0, 0, 0);
      }
      ColorSet(c);
      Increment();
    }

    void Dot(uint32_t color, uint16_t steps, uint16_t interval) {
      ActivePattern = DOT;
      Interval = interval;
      TotalSteps = steps;
      PixelColor = color;
      Index = 0;
    }

    void DotUpdate() {
      ColorSet(Color(0, 0, 0));
      show();
      setPixelColor(random(numPixels()), PixelColor);
      Increment();
    }

    uint32_t DimColor(uint32_t color) {
      return Color(((color >> 16) & 0xFF) >> 1, ((color >> 8) & 0xFF) >> 1, (color & 0xFF) >> 1);
    }

    uint32_t Wheel(byte WheelPos) {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85) {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170) {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }

    void ColorSet(uint32_t color) {
      for (int i = 0; i < numPixels(); i++) {
        setPixelColor(i, color);
      }
    }

    void DoubleSet(uint16_t i, uint32_t color) {
      setPixelColor(i, color);
      setPixelColor(numPixels() - 1 - i, color);
    }
};

void RingsComplete();

NeoPatterns Rings(32, PIN, NEO_GRB + NEO_KHZ800, &RingsComplete);
uint8_t mode = 0;
uint32_t prev_time;

void setup() {
#ifdef __AVR_ATtiny85__
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  Rings.begin();
  Rings.setBrightness(BRIGHTNESS);
  Rings.RainbowCycle(random(RAINBOW_CYCLE_MIN_INTERVAL, RAINBOW_CYCLE_MAX_INTERVAL + 1));
  prev_time = millis();
}

void loop() {
  Rings.Update();
  /*
     We could store the return of the first millis call in a variable.
     But this routine is fast, so we only loose some milliseconds (if even)
     and we are not that time critical, that the MODE changes extacly after
     MODE_CHANGE_TIME. Calling millis twice, saves us 8 bytes, which is critical
     for the small storage space we have.
  */
  if ((millis() - prev_time) >= MODE_CHANGE_TIME) {
    mode = random(0, 9);
    prev_time = millis();
  }
}

void RingsComplete() {
  uint16_t slow_interval = random(SLOW_INTERVAL_MIN, SLOW_INTERVAL_MAX + 1);
  uint16_t steps = random(STEPS_MIN, STEPS_MAX + 1);
  uint32_t color = Rings.Wheel(random(COLOR_MIN, COLOR_MAX + 1));

  switch (mode) {
    case 0:
      Rings.RainbowCycle(random(RAINBOW_CYCLE_MIN_INTERVAL, RAINBOW_CYCLE_MAX_INTERVAL + 1));
      break;
    case 1:
      Rings.ColorWipe(color, slow_interval);
      break;
    case 2:
      Rings.DoubleColorWipe(color, slow_interval);
      break;
    case 3:
      Rings.Scanner(color, slow_interval);
      break;
    case 4:
      Rings.DoubleScanner(color, slow_interval);
      break;
    case 5:
      Rings.Random(color, steps, slow_interval);
      break;
    case 6:
      Rings.DoubleRandom(color, steps, slow_interval);
      break;
    case 7:
      Rings.Blink(color, steps, random(BLINK_MIN_INTERVAL, BLINK_MAX_INTERVAL + 1));
      break;
    case 8:
      Rings.Dot(color, steps, slow_interval);
      break;
    default:
      break;
  }
}