Skip to content

Instantly share code, notes, and snippets.

@cmsj
Last active January 21, 2023 23:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmsj/ad9d7497d7092c1000ce742f605a34fd to your computer and use it in GitHub Desktop.
Save cmsj/ad9d7497d7092c1000ce742f605a34fd to your computer and use it in GitHub Desktop.
#include <Adafruit_NeoPixel.h>
#include <Adafruit_DotStar.h>
// led_effects
// by Chris Jones <cmsj@tenshu.net>
// Released under the MIT License.
// RGB LED built in to the Trinket M0
Adafruit_DotStar dot = Adafruit_DotStar(1, INTERNAL_DS_DATA, INTERNAL_DS_CLK, DOTSTAR_BGR);
// NeoPixel Jewel
#define NEOPIXEL_PIN 4
#define NEOPIXEL_CNT 7
Adafruit_NeoPixel jewel = Adafruit_NeoPixel(NEOPIXEL_CNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Choose which effect to implement. Only one of these should be uncommented.
#define EFFECT_STATIC 1
// #define EFFECT_RAINBOW 1
// #define EFFECT_STATIC_SPIN 1
// #define EFFECT_STATIC_PULSE 1
// Globals useful to effects
int fps = 60;
uint32_t target_color = jewel.Color(255, 0, 0);
void *effect_data = NULL;
char debug[255];
// Our entrypoint. Initialise serial and boot the LEDs.
void setup() {
// Pseudo-random seed - some effects need reasonable random numbers
// randomSeed();
// Initialise our serial port
Serial.begin(9600);
// Don't uncomment this in a production build, it will probably cause startup to hang indefinitely.
// Uncomment it if you want to guarantee you get all messages from setup() over serial:
while(!Serial);
Serial.println("Booting LEDs...");
dot.begin();
dot.clear();
dot.show();
jewel.begin();
jewel.clear();
jewel.show();
Serial.println("Done.");
Serial.flush();
Serial.println("Calling effect_setup()...");
effect_data = effect_setup();
Serial.println("Done.");
Serial.flush();
}
void loop() {
// Capture the time at the start of this iteration
unsigned long t_start = millis();
// Clear the current LED state
dot.clear();
jewel.clear();
// Iterate the effect
effect_loop();
// Commit the LED state
dot.show();
jewel.show();
// Calculate the length of this iteration
unsigned long t_stop = millis();
unsigned long t_len = t_stop - t_start;
// If we took less than our target frame time, sleep for the remainder of the time.
// If we took more than our target frame time, log an error and don't sleep.
if (t_len > 1000/fps) {
sprintf(debug, "loop() frame time: %lu ms, max target is %d ms. Effect is too complex, or 50 day millis() rollover occurred", t_len, 1000/fps);
Serial.println(debug);
} else {
unsigned long t_frame_left = 1000/fps - t_len;
// sprintf(debug, "loop() frame time: %lu/%d ms, sleeping for %lu", t_len, 1000/fps, t_frame_left);
// Serial.println(debug);
delay(floor(t_frame_left));
}
}
// Below here are the effects.
#ifdef EFFECT_STATIC
// EFFECT: Static
// Apply a plain static color to all LEDs
void* effect_setup() {
fps = 1;
return NULL;
}
void effect_loop() {
dot.fill(target_color, 0, 1);
jewel.fill(target_color, 0, NEOPIXEL_CNT);
}
#endif
#ifdef EFFECT_RAINBOW
// EFFECT: Rainbow cycle.
// Cycle through various colours on all LEDs simultaneously
struct rainbow_cycle_data {
long red;
long green;
long blue;
float r_angle;
float g_angle;
float b_angle;
int rand_min;
int rand_max;
};
void* effect_setup() {
fps = 30;
rainbow_cycle_data *data = (rainbow_cycle_data *)malloc(sizeof(rainbow_cycle_data));
data->red = random(0, 254);
data->green = random(0, 254);
data->blue = random(0, 254);
data->r_angle = 0;
data->g_angle = 90;
data->b_angle = 180;
data->rand_min = 1;
data->rand_max = 3;
return (void *)data;
}
void effect_loop() {
rainbow_cycle_data *data = (rainbow_cycle_data *)effect_data;
dot.fill(dot.Color(data->red, data->green, data->blue));
jewel.fill(jewel.Color(data->red, data->green, data->blue));
data->r_angle = data->r_angle + (float)random(data->rand_min, data->rand_max) / 10;
data->g_angle = data->g_angle + (float)random(data->rand_min, data->rand_max) / 10;
data->b_angle = data->b_angle + (float)random(data->rand_min, data->rand_max) / 10;
data->red = (sin(data->r_angle) + 1) * 128;
data->green = (sin(data->g_angle) + 1) * 128;
data->blue = (sin(data->b_angle) + 1) * 128;
}
#endif
#ifdef EFFECT_STATIC_SPIN
// EFFECT: Static Spin.
// Cycle through the LEDs individually, with whatever the target color is set to
struct static_spin_data {
int i;
};
void* effect_setup() {
fps = 30;
static_spin_data *data = (static_spin_data *)malloc(sizeof(static_spin_data));
data->i = 1;
return (void *)data;
}
void effect_loop() {
static_spin_data *data = (static_spin_data *)effect_data;
jewel.setPixelColor(data->i, target_color);
data->i++;
if (data->i > NEOPIXEL_CNT) {
data->i = 1;
}
}
#endif
#ifdef EFFECT_STATIC_PULSE
// EFFECT: Static Pulse.
// Pulse the brightness of the target color
struct static_pulse_data {
int brightness_delta;
};
void* effect_setup() {
fps = 90;
static_pulse_data *data = (static_pulse_data *)malloc(sizeof(static_pulse_data));
data->brightness_delta = 2;
jewel.fill(target_color);
jewel.setBrightness(254);
jewel.show();
return (void *)data;
}
void effect_loop() {
static_pulse_data *data = (static_pulse_data *)effect_data;
uint8_t current_brightness = jewel.getBrightness();
if (current_brightness <= 20 || current_brightness >= 254) {
data->brightness_delta = -(data->brightness_delta);
}
jewel.fill(target_color);
jewel.setBrightness(current_brightness + data->brightness_delta);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment