// SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries // // SPDX-License-Identifier: MIT #include #include #include #include #include "HsvConverter.h" int ledMode = 0; //FIRST ACTIVE MODE // Number of Pixies in the fiber optics #define NUM_PIXIES 5 // Use the built-in UART for buttery-smooth serial updates #define pixieSerial Serial1 // Milliseconds of stillness to reset calibration #define STILL_TIME 5000 // How much jitter the accelerometer has #define ACCEL_JITTER 160 // Sparkle probability is 1 over this. Lower number = more frequent. #define SPARKLE_PROB 30 Adafruit_Pixie strip = Adafruit_Pixie(NUM_PIXIES, &pixieSerial); Adafruit_MSA311 accel = Adafruit_MSA311(); void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); accel.begin(); accel.setPowerMode(MSA301_NORMALMODE); accel.setDataRate(MSA301_DATARATE_1000_HZ); accel.setBandwidth(MSA301_BANDWIDTH_500_HZ); accel.setRange(MSA301_RANGE_2_G); accel.setResolution(MSA301_RESOLUTION_14); accel.enableInterrupts(true, true); // enable single/double tap accel.enableAutoRange(true); pixieSerial.begin(115200); strip.setBrightness(0x60); strip.show(); // Initialize all pixels to off } // Global hue, sat, val, color uint16_t hue = 0x00; uint16_t sat = 0xff; uint16_t val = 0xff; uint32_t color = 0; // Global tick count uint32_t ticks = 0; void loop() { static bool enabled = true; static uint8_t mode = 0; uint8_t motionstat = accel.getMotionInterruptStatus(); switch (motionstat & 0b00110000) { case 0b00100000: // Single Tap mode++; break; case 0b00010000: // Double Tap enabled = !enabled; break; } calibrated_read(); hue = (hue + HsvConverter::maxHue + accel.y) % HsvConverter::maxHue; val = 0xa0 - (accel.x << 1); color = HsvConverter::getColorFromHSV(hue, sat, val); if (enabled) { switch (mode) { case 0: chase(); break; case 1: sparkle(); break; case 2: disco_fever(); break; default: mode = 0; } } else { strip.clear(); } strip.show(); hello(); delay(10); ticks++; } /** * Blink the built-in LED at startup */ void hello() { if (ticks >= 500) { return; } bool on = (ticks%10 == 0); #ifdef SEEED_XIAO_M0 on = !on; #endif digitalWrite(LED_BUILTIN, on); } void disco_fever() { static uint16_t count = 0; strip.setPixelColor(0, color); } void chase() { static uint8_t which = 0; if (ticks % 30 == 0) { which = (which + 1) % NUM_PIXIES; } strip.clear(); strip.setPixelColor(which, color); } void sparkle() { if (ticks % 5) { return; } for (uint16_t i = 0; i < NUM_PIXIES; i++) { uint32_t color = 0; if (random(SPARKLE_PROB) == 0) { color = HsvConverter::getColorFromHSV(hue, sat >> 3, val); } strip.setPixelColor(i, color); } } void calibrated_read() { static int16_t calibration[3] = {0}; static int16_t lastvals[3] = {0}; static unsigned long still_since = 0; int16_t a[3] = {0}; bool is_still = true; accel.read(); a[0] = accel.x - calibration[0]; a[1] = accel.y - calibration[1]; a[2] = accel.z - calibration[2]; is_still = is_still && (abs(a[0] - lastvals[0]) < ACCEL_JITTER); is_still = is_still && (abs(a[1] - lastvals[1]) < ACCEL_JITTER); is_still = is_still && (abs(a[2] - lastvals[2]) < ACCEL_JITTER); if (is_still || !still_since) { if (!still_since || (millis() - still_since > STILL_TIME)) { Serial.printf("Recalibrating\n"); calibration[0] += a[0]; calibration[1] += a[1]; calibration[2] += a[2]; still_since = millis(); } } else { still_since = millis(); } lastvals[0] = a[0]; lastvals[1] = a[1]; lastvals[2] = a[2]; accel.x = a[0] / ACCEL_JITTER; accel.y = a[1] / ACCEL_JITTER; accel.z = a[2] / ACCEL_JITTER; }