Changeset - 05931ab4f666
[Not reviewed]
tip default
0 1 0
Dennis Fink - 5 years ago 2019-08-31 11:30:25
dennis.fink@c3l.lu
Added Spinner pattern
1 file changed with 31 insertions and 1 deletions:
0 comments (0 inline, 0 general)
Neopixel_Goggles.ino
Show inline comments
 
#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
 

	
 
#define SPINNER_PIXELS_MIN 1
 
#define SPINNER_PIXELS_MAX 10
 

	
 
// End config section
 

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

	
 
class NeoPatterns : public Adafruit_NeoPixel {
 
  public:
 
    pattern  ActivePattern;
 

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

	
 
    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;
 
          case SPINNER:
 
            SpinnerUpdate();
 
            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();
 
    }
 

	
 
    void Spinner(uint32_t color, uint16_t spinner_pixels, uint16_t interval) {
 
      ActivePattern = SPINNER;
 
      Interval = interval;
 
      TotalSteps = 32;
 
      PixelColor = color;
 
      Index = 0;
 
      SpinnerPixels = spinner_pixels;
 
    }
 

	
 
    void SpinnerUpdate() {
 
      ColorSet(Color(0, 0, 0));
 
      for (int i = 0; i < numPixels() / 2; i++) {
 
        if ((Index + i) % SpinnerPixels == 0) {
 
          DoubleSet(i, 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;
 
    case 9:
 
      Rings.Spinner(color, random(SPINNER_PIXELS_MIN, SPINNER_PIXELS_MAX + 1), slow_interval);
 
      break;
 
    default:
 
      break;
 
  }
 
}
0 comments (0 inline, 0 general)