Skip to content

Instantly share code, notes, and snippets.

@telent
Created November 23, 2020 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save telent/31b005fcf66606a97ec7f9046d8c229c to your computer and use it in GitHub Desktop.
Save telent/31b005fcf66606a97ec7f9046d8c229c to your computer and use it in GitHub Desktop.
neoxmas.ino
#include <Adafruit_NeoPixel.h>
#include <math.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 2
#define STRIP_LENGTH 150
Adafruit_NeoPixel strip = Adafruit_NeoPixel(STRIP_LENGTH, PIN, NEO_GRB + NEO_KHZ800);
float zero = 0;
int rotation_speed = -20;
int brightness = 18;
struct hsv {
float h,s,v;
};
struct loc {
int offset;
struct hsv color;
};
struct loc initial_config[] = {
(struct loc){ 0, (struct hsv){ 0, 1, 0.10} },
(struct loc){ 10, (struct hsv){ 0, 0.8, 0.7} },
(struct loc){ 20, (struct hsv){ 0, 1, 0.10} },
(struct loc){ 50, (struct hsv){ 0, 1, 0.1} },
(struct loc){ 60, (struct hsv){ 120, 0.8, 0.7} },
(struct loc){ 70, (struct hsv){ 0, 1, 0.1} },
(struct loc){ 100, (struct hsv){ 0, 1, 0.1} },
(struct loc){ 110, (struct hsv){ 240, 0.8, 0.7} },
(struct loc){ 120, (struct hsv){ 0, 1, 0.5} },
(struct loc){ 999, (struct hsv){ 350, 0, 0} },
};
void set_from_hsv(byte * rgb, struct hsv *hsv) {
float chroma = (1 - abs(2 * hsv->v - 1)) * hsv->s;
float h = hsv->h/60;
Serial.println(h);
float x = (1 - abs((int)h % 2 - 1)) * chroma;
float r, g, b;
r = g = b = 0;
if(h < 1) {
r=chroma; g=x; b=0;
} else if(h < 2) {
r = x; g=chroma; b=0;
} else if(h < 3) {
r=0;
g=chroma;
b=x;
} else if(h < 4) {
r=0;
g=x;
b=chroma;
} else if(h < 5) {
r=x; g=0; b=chroma;
} else {
r=chroma;
g=0;
b=x;
}
float m = hsv->v - chroma/2;
rgb[0] = (byte) brightness*(r+m);
rgb[1] = (byte) brightness*(g+m);
rgb[2] = (byte) brightness*(b+m);
}
byte lights[STRIP_LENGTH][3];
struct hsv *interpolate(struct hsv *start, struct hsv *target,
int width, int remaining) {
float proportion = 1.0 * remaining/width;
static hsv r;
hsv *result = &r;
result->h = start->h*(proportion) + target->h*(1-proportion);
result->s = start->s*(proportion) + target->s*(1-proportion);
result->v = start->v*(proportion) + target->v*(1-proportion);
return result;
}
void set_strip(struct loc targets[]) {
struct loc *target = targets;
int i = target->offset;
struct hsv * prev_color = &(target->color);
while(i< STRIP_LENGTH) {
target++;
int target_index = (target+1)->offset;
if(target->offset > STRIP_LENGTH) {
/* wrap around */
target = targets;
target_index = target->offset + STRIP_LENGTH;
} else {
target_index = target->offset;
}
int distance = target_index - i;
while(i<= target_index) {
hsv *c = interpolate(prev_color, &(target->color),
distance, target_index - i);
set_from_hsv(lights[i % STRIP_LENGTH], c);
i++;
}
}
}
void set_strip1(struct loc locations[]) {
int i=1;
struct hsv *target_color = 0;
loc *v=locations;
for(; v->offset < STRIP_LENGTH; v++) {
int offset = v->offset;
struct hsv * start_color = target_color;
target_color = &(v->color);
int w = offset - i;
while(i<offset) {
struct hsv *c = interpolate(start_color, target_color, w, offset-i);
set_from_hsv(lights[i], c);
i++;
}
set_from_hsv(lights[offset], target_color);
}
if(i < STRIP_LENGTH) {
lights[i][0] = 0;
lights[i][1] = 0;
lights[i][2] = 0;
i++;
}
}
int rotated(int i) {
return ((int)floor(zero) + i + STRIP_LENGTH) % STRIP_LENGTH;
}
void setup() {
Serial.begin(115200);
while (!Serial) {;}
Serial.println("HEY ");
strip.begin();
set_strip(initial_config);
strip.show();
}
void loop() {
float dt = 0.01;
delay(dt * 1000);
zero = (zero + dt*rotation_speed + STRIP_LENGTH) ;
while(zero > (1.0* STRIP_LENGTH)) zero -= STRIP_LENGTH;
for(int i = 0; i< STRIP_LENGTH; i++) {
byte *col = lights[rotated(i)];
strip.setPixelColor(i, strip.Color(col[0], col[1], col[2]));
}
strip.show();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment