Еще один интересный вариант и реализация разноцветного кольца на светодиодах WS2812b или ленте. Найден на просторах интернета. Комментарии автора сохранены.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define NEOPIXEL_PIN 6
#define NUM_PIXELS 30
#define BRIGHTNESS 160
int mod(int x, int m) {
// modulo operator doesn't work as expected for negative numbers
int r = x%m;
return r<0 ? r+m : r;
}
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_RGBW + NEO_KHZ800);
// G R B W
uint32_t K = strip.Color(0, 0, 0, 0);
uint32_t G = strip.Color(255, 0, 0, 0);
uint32_t R = strip.Color(0, 255, 0, 0);
uint32_t B = strip.Color(0, 0, 255, 0);
uint32_t M = strip.Color(0, 255, 255, 0);
uint32_t C = strip.Color(255, 0, 255, 0);
uint32_t Y = strip.Color(255, 255, 0, 0);
uint32_t W = strip.Color(255, 255, 255, 0);
uint32_t WK = strip.Color(0, 0, 0, 255);
uint32_t WG = strip.Color(255, 0, 0, 255);
uint32_t WR = strip.Color(0, 255, 0, 255);
uint32_t WB = strip.Color(0, 0, 255, 255);
uint32_t WM = strip.Color(0, 255, 255, 255);
uint32_t WC = strip.Color(255, 0, 255, 255);
uint32_t WY = strip.Color(255, 255, 0, 255);
uint32_t WW = strip.Color(255, 255, 255, 255);
uint32_t buffer[NUM_PIXELS];
/*
struct spinner {
int position; // in pixels
int tail_length; // in pixels
uint32_t color; // base color
int delay; // update time
bool direction; // 0=CW, 1=CCW
unsigned long last_update; // in ms since boot
};
spinner spinner1 = {10, R, 10, 0};
spinner spinner2 = {5, G, 5, 1};
*/
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
strip.setBrightness(BRIGHTNESS);
Serial.begin(9600);
delay(500);
Serial.println("start");
//spinner_init(10, 0, R);
strip.show();
}
void spinner_init(int len, int offset, uint32_t color) {
for(uint16_t i=offset; i<len; i++) {
strip.setPixelColor(i % NUM_PIXELS, color);
}
}
uint32_t color, new_color;
int t=0;
unsigned long time;
int num_updates;
void loop() {
// ring_test();
// animate_arbitrary_time_space(t);
// animate_simple_spinner(t);
animate_multiple_spinners();
t++;
}
// how do i struct
const int NUM_SPINNERS = 3;
int starts[NUM_SPINNERS] = {0, 30, 0};
int lengths[NUM_SPINNERS] = {8, 10, 12};
int dirs[NUM_SPINNERS] = {1, -1, 1};
uint32_t colors[NUM_SPINNERS] = {R, G, B};
int delays[NUM_SPINNERS] = {25, 90, 50};
int last_updates[NUM_SPINNERS] = {0, 0, 0};
void animate_multiple_spinners() {
time = millis();
num_updates = update_spinners(time);
if(num_updates > 0) {
draw_spinners_to_buffer();
strip.show();
}
}
int update_spinners(unsigned long time) {
int num_updates = 0;
for(int spinner_idx=0; spinner_idx<NUM_SPINNERS; spinner_idx++) {
if(time - last_updates[spinner_idx] > delays[spinner_idx]) {
starts[spinner_idx] = mod(starts[spinner_idx] + dirs[spinner_idx], NUM_PIXELS);
last_updates[spinner_idx] = time;
num_updates++;
}
}
return num_updates;
}
void draw_spinners_to_buffer() {
int pixel;
clear_buffer();
for(int spinner_idx=0; spinner_idx<NUM_SPINNERS; spinner_idx++) {
for(int n=0; n<lengths[spinner_idx]; n++) {
pixel = mod(starts[spinner_idx] + dirs[spinner_idx] * n, NUM_PIXELS);
color = strip.getPixelColor(pixel);
new_color = color | decay_color(colors[spinner_idx], lengths[spinner_idx] - 1 - n);
strip.setPixelColor(pixel, new_color);
}
}
}
uint32_t decay_color(uint32_t color, int n) {
int32_t blue = color & 0xFF;
int32_t red = (color >> 8) & 0xFF;
int32_t green = (color >> 16) & 0xFF;
int32_t white = (color >> 24) & 0xFF;
red = decay_kernel_exponential(red, n);
green = decay_kernel_exponential(green, n);
blue = decay_kernel_exponential(blue, n);
white = decay_kernel_exponential(white, n);
return white << 24 | green << 16 | red << 8 | blue;
}
byte decay_kernel_exponential(byte channel, int n) {
return channel * pow(0.75, n);
}
byte decay_kernel_linear(byte channel, int n) {
return max(channel - 16 * n, 0);
}
void clear_buffer() {
for(int i=0; i<NUM_PIXELS; i++) {
strip.setPixelColor(i, 0);
}
}
/////////////////////////////////////////
void animate_simple_spinner(int t) {
update_spinner(t, 10, 1, R);
delay(20);
}
void update_spinner(int t, int len, int speed, uint32_t color) {
int head_index = (speed*t+len) % NUM_PIXELS;
int tail_index = speed*t % NUM_PIXELS;
strip.setPixelColor(tail_index, K);
strip.setPixelColor(head_index, color);
}
void animate_arbitrary_time_space(int t) {
for(uint16_t i=0; i<60; i++) {
color = get_ring_color(t, i);
strip.setPixelColor(i, color);
delay(5);
}
}
uint32_t c[10] = {R, G, B, C, M, Y, W, WR, WG, WB};
uint32_t get_ring_color(int t, int i) {
return c[i/6];
}
void ring_test() {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, 69, 174, 177);
strip.show();
delay(32);
}
}