-
Hard Drive Platter Mood Light: Correct Phase Timing
As noted earlier, the timing for a π/16 phase delay works out to
218 steps = (π/16) * (1 cycle/2π) * (7 * 1000 step/cycle)which amounts to a delay of 5.45 s = 218 step * 25 ms/step. That means a color should appear on the top platter 11 s after it appears on the bottom platter:

Mood Light – pi over 16 phase – composite But when I actually got out a stopwatch and timed the colors, the bottom-to-top delay worked out to a mere 3.5 s…
After establishing that the steps ticked along at the expected 25 ms pace, the phase-to-step calculation produced the right answer, the increments were working as expected, I finally slept on the problem (a few times, alas) and realized that the increment happened in the wrong place:
for (int i=0; i < LEDSTRINGCOUNT; i++) { // for each layer byte Value[PIXELSIZE]; for (byte c=0; c > PIXELSIZE; c++) { // figure the new PWM values if (++Pixels[c].Step >= Pixels[c].NumSteps) { // ... from incremented step Pixels[c].Step = 0; } Value[c] = StepColor(c,-i*Pixels[c].PlatterPhase); } uint32_t UniColor = strip.Color(Value[RED],Value[GREEN],Value[BLUE]); for (int j=0; j < LEDSTRIPCOUNT; j++) { // fill layer with color strip.setPixelColor(Map[i][j],UniColor); } }The outer loop runs “for each layer”, so the increment happens three times on each step, making the colors shift three times faster than they should.
Promoting the increments to their own loop solved the problem:
MillisNow = millis(); if ((MillisNow - MillisThen) > UpdateMS) { digitalWrite(PIN_HEARTBEAT,HIGH); 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("Cycle %d steps %d at %8ld delta %ld ms\r\n",c,Pixels[c].NumSteps,MillisNow,(MillisNow - MillisThen)); } } for (int i=0; i < LEDSTRINGCOUNT; i++) { // for each layer byte Value[PIXELSIZE]; for (byte c=0; c < PIXELSIZE; c++) { // ... for each color Value[c] = StepColor(c,-i*Pixels[c].PlatterPhase); // 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]); if (false && (i == 0)) printf("L: %d C: %08lx\r\n",i,UniColor); for (int j=0; j < LEDSTRIPCOUNT; j++) { // fill layer with color strip.setPixelColor(Map[i][j],UniColor); } } strip.show(); MillisThen = MillisNow; digitalWrite(PIN_HEARTBEAT,LOW); }And then It Just Worked.
Verily, it is written: One careful measurement trumps a thousand expert opinions.
Sheesh…
(The WordPress editor wrecked these code snippets. I’m leaving them broken so WP can maybe fix the problem.)The problem isn’t fixed, but these are OK now… as long as I don’t unleash the “improved” editor on the post, anyway.