Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Arduino source code: SK6812 test fixture, now with row-by-row color mods
// SK6812 RGBW LED array exerciser
// Ed Nisley - KE4ANU - February 2017
// 2020-01-25 add row-by-row color modifications
#include <Adafruit_NeoPixel.h>
//----------
// Pin assignments
const byte PIN_NEO = A3; // DO - data out to first Neopixel
const byte PIN_HEARTBEAT = 13; // DO - Arduino LED
const byte PIN_SELECT = 2; // DI - pattern select input
//----------
// Constants
#define UPDATEINTERVAL 20ul
const unsigned long UpdateMS = UPDATEINTERVAL - 1ul; // update LEDs only this many ms apart minus loop() overhead
// number of steps per cycle, before applying prime factors
#define RESOLUTION 100
// phase difference between LEDs for slowest color
#define BASEPHASE (PI/16.0)
// LEDs in each row
#define NUMCOLS 5
// number of rows
#define NUMROWS 5
#define NUMPIXELS (NUMCOLS * NUMROWS)
#define PINDEX(row,col) (row*NUMCOLS + col)
//----------
// Globals
// instantiate the Neopixel buffer array
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN_NEO, NEO_GRBW + NEO_KHZ800);
uint32_t FullWhite = strip.Color(255,255,255,255);
uint32_t FullOff = strip.Color(0,0,0,0);
struct pixcolor_t {
byte Prime;
unsigned int NumSteps;
unsigned int Step;
float StepSize;
float TubePhase;
byte MaxPWM;
};
// colors in each LED
enum pixcolors {RED, GREEN, BLUE, WHITE, PIXELSIZE};
struct pixcolor_t Pixels[PIXELSIZE]; // all the data for each pixel color intensity
unsigned long MillisNow;
unsigned long MillisThen;
//-- Figure PWM based on current state
byte StepColor(byte Color, float Phi) {
byte Value;
Value = (Pixels[Color].MaxPWM / 2.0) * (1.0 + sin(Pixels[Color].Step * Pixels[Color].StepSize + Phi));
// Value = (Value) ? Value : Pixels[Color].MaxPWM; // flash at dimmest points
// printf("C: %d Phi: %d Value: %d\r\n",Color,(int)(Phi*180.0/PI),Value);
return Value;
}
//-- Helper routine for printf()
int s_putc(char c, FILE *t) {
Serial.write(c);
}
//------------------
// Set the mood
void setup() {
pinMode(PIN_HEARTBEAT,OUTPUT);
digitalWrite(PIN_HEARTBEAT,LOW); // show we arrived
pinMode(PIN_SELECT,INPUT_PULLUP);
Serial.begin(57600);
fdevopen(&s_putc,0); // set up serial output for printf()
printf("WS2812 / SK6812 array exerciser\r\nEd Nisley - KE4ZNU - February 2017\r\n");
/// set up Neopixels
strip.begin();
strip.show();
// lamp test: run a brilliant white dot along the length of the strip
printf("Lamp test: walking white\r\n");
strip.setPixelColor(0,FullWhite);
strip.show();
delay(250);
for (int i=1; i<NUMPIXELS; i++) {
digitalWrite(PIN_HEARTBEAT,HIGH);
strip.setPixelColor(i-1,FullOff);
strip.setPixelColor(i,FullWhite);
strip.show();
digitalWrite(PIN_HEARTBEAT,LOW);
delay(250);
}
strip.setPixelColor(NUMPIXELS - 1,FullOff);
strip.show();
delay(250);
// fill the array, row by row
printf(" ... fill\r\n");
for (int i=NUMROWS-1; i>=0; i--) { // for each row
digitalWrite(PIN_HEARTBEAT,HIGH);
for (int j=NUMCOLS-1; j>=0 ; j--) {
strip.setPixelColor(PINDEX(i,j),FullWhite);
strip.show();
delay(100);
}
digitalWrite(PIN_HEARTBEAT,LOW);
}
// clear to black, column by column
printf(" ... clear\r\n");
for (int j=NUMCOLS-1; j>=0; j--) { // for each column
digitalWrite(PIN_HEARTBEAT,HIGH);
for (int i=NUMROWS-1; i>=0; i--) {
strip.setPixelColor(PINDEX(i,j),FullOff);
strip.show();
delay(100);
}
digitalWrite(PIN_HEARTBEAT,LOW);
}
delay(1000);
// set up the color generators
MillisNow = MillisThen = millis();
printf("First random number: %ld\r\n",random(10));
Pixels[RED].Prime = 3;
Pixels[GREEN].Prime = 5;
Pixels[BLUE].Prime = 7;
Pixels[WHITE].Prime = 11;
printf("Primes: (%d,%d,%d,%d)\r\n",
Pixels[RED].Prime,Pixels[GREEN].Prime,Pixels[BLUE].Prime,Pixels[WHITE].Prime);
unsigned int PixelSteps = (unsigned int) ((BASEPHASE / TWO_PI) *
RESOLUTION * (unsigned int) max(max(max(Pixels[RED].Prime,Pixels[GREEN].Prime),Pixels[BLUE].Prime),Pixels[WHITE].Prime));
printf("Pixel phase offset: %d deg = %d steps\r\n",(int)(BASEPHASE*(360.0/TWO_PI)),PixelSteps);
Pixels[RED].MaxPWM = 255;
Pixels[GREEN].MaxPWM = 255;
Pixels[BLUE].MaxPWM = 255;
Pixels[WHITE].MaxPWM = 32;
for (byte c=0; c < PIXELSIZE; c++) {
Pixels[c].NumSteps = RESOLUTION * (unsigned int) Pixels[c].Prime;
Pixels[c].Step = (3*Pixels[c].NumSteps)/4;
Pixels[c].StepSize = TWO_PI / Pixels[c].NumSteps; // in radians per step
Pixels[c].TubePhase = PixelSteps * Pixels[c].StepSize; // radians per tube
printf("c: %d Steps: %5d Init: %5d",c,Pixels[c].NumSteps,Pixels[c].Step);
printf(" PWM: %3d Phi %3d deg\r\n",Pixels[c].MaxPWM,(int)(Pixels[c].TubePhase*(360.0/TWO_PI)));
}
}
//------------------
// Run the mood
void loop() {
MillisNow = millis();
if ((MillisNow - MillisThen) > UpdateMS) {
digitalWrite(PIN_HEARTBEAT,HIGH);
unsigned int AllSteps = 0;
for (byte c=0; c < PIXELSIZE; c++) { // step to next increment in each color
if (++Pixels[c].Step >= Pixels[c].NumSteps) {
Pixels[c].Step = 0;
printf("Color %d steps %5d at %8ld delta %ld ms\r\n",c,Pixels[c].NumSteps,MillisNow,(MillisNow - MillisThen));
}
AllSteps += Pixels[c].Step; // will be zero only when all wrap at once
}
if (0 == AllSteps) {
printf("Grand cycle at: %ld\r\n",MillisNow);
}
if (digitalRead(PIN_SELECT)) {
for (int col=0; col < NUMCOLS ; col++) { // for each column
byte Value[PIXELSIZE]; // figure first row colors
for (byte p=0; p < PIXELSIZE; p++) { // ... for each color in pixel
Value[p] = StepColor(p,-col*Pixels[p].TubePhase);
}
// just RGB
int row = 0;
uint32_t UniColor = strip.Color(Value[RED],Value[GREEN],Value[BLUE],0);
strip.setPixelColor(col + NUMCOLS*row++,UniColor);
byte MinWhite = min(min(Value[RED],Value[GREEN]),Value[BLUE]);
// only common white
UniColor = strip.Color(0,0,0,MinWhite);
strip.setPixelColor(col + NUMCOLS*row++,UniColor);
// RGB minus common white + white
UniColor = strip.Color(Value[RED]-MinWhite,Value[GREEN]-MinWhite,Value[BLUE]-MinWhite,MinWhite);
strip.setPixelColor(col + NUMCOLS*row++,UniColor);
// RGB minus common white
UniColor = strip.Color(Value[RED]-MinWhite,Value[GREEN]-MinWhite,Value[BLUE]-MinWhite,0);
strip.setPixelColor(col + NUMCOLS*row++,UniColor);
// inverse RGB
UniColor = strip.Color(255 - Value[RED],255 - Value[GREEN],255 - Value[BLUE],0);
strip.setPixelColor(col + NUMCOLS*row++,UniColor);
}
}
else {
for (int k=0; k < NUMPIXELS; k++) { // for each pixel
byte Value[PIXELSIZE];
for (byte c=0; c < PIXELSIZE; c++) { // ... for each color
Value[c] = StepColor(c,-k*Pixels[c].TubePhase); // figure new PWM value
// Value[c] = (c == RED && Value[c] == 0) ? Pixels[c].MaxPWM : Value[c]; // flash highlight for tracking
}
uint32_t UniColor = strip.Color(Value[RED],Value[GREEN],Value[BLUE],Value[WHITE]);
strip.setPixelColor(k,UniColor);
}
}
strip.show();
MillisThen = MillisNow;
digitalWrite(PIN_HEARTBEAT,LOW);
}
}
@ednisley

This comment has been minimized.

Copy link
Owner Author

@ednisley ednisley commented Jan 24, 2020

More details on my blog at https://wp.me/poZKh-8K8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.