Arduino source code: SK6812 LED test exerciser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SK6812 RGBW LED array exerciser | |
// Ed Nisley - KE4ANU - February 2017 | |
#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 | |
//---------- | |
// 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 | |
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); | |
} | |
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
More details on my blog at http://wp.me/poZKh-6Aa