Using a Neopixel strip to display a color based representation of the time (Day,Hour,Minute,Second). Eventually I'll hook up a RTC source to make it accurate.
When I run the program, there's a slight hiccup when it changes seconds:
This is Day:Hour:Minute:Second then the values stored in the pix[] array:
There are two pixels (out of 8)to display each unit of time. Both pixels should have identical values all of the time. I can't even see the hiccup, as it only exists for a fraction of a second, so it's not a project killer, but the fact it exits confounds me. Any suggestions?
#include <Time.h>
#include <Adafruit_NeoPixel.h>
template<class T> inline Print &operator <<(Print &obj, T arg)
{
obj.print(arg);
return obj;
}
#define RED 0
#define GREEN 1
#define BLUE 2
#define PIXELS 8
#define PIN 6
int newcol[3]; //Stores the color values from NewCol, 0-255
int pix[PIXELS]; //Stores the color values assigned to each pixel, 0-764
int i;
Adafruit_NeoPixel strip =Adafruit_NeoPixel(PIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup()
{
strip.begin();
strip.show();
Serial.begin(9600);
for(int i=0; i<PIXELS; i++)
{
pix[i]=0;
}
}
void loop()
{
for(i=0; i<PIXELS/4; i++)
{
pix[i]=764*day()/31;
pix[i+PIXELS/4]=764*hour()/23;
pix[i+2*(PIXELS/4)]=764U*minute()/59;
pix[i+3*(PIXELS/4)]=764U*second()/59;
Serial << day() << ":"<<hour() <<":" << minute() << ":" << second()<<" ";
for(int x=0; x<PIXELS; x++)
{
Serial << pix[x] << " ";
}
Serial << "\n";
}
for(i=0; i<PIXELS; i++)
{
ColorWheel(newcol, pix[i]);
strip.setPixelColor(i,newcol[RED],newcol[GREEN],newcol[BLUE]);
}
strip.show();
}
void ColorWheel(int* ptr, int wpos)
{
if (wpos > 764 || wpos < 0) // Bright white if out of bounds
{
ptr[0]=255;
ptr[1]=255;
ptr[2]=255;
}
else if(wpos <=255)
{
ptr[0]=255-wpos;
ptr[1]=wpos;
ptr[2]=0;
}
else if (wpos > 255 && wpos < 511)
{
ptr[0]=0;
ptr[1]=510-wpos;
ptr[2]=wpos-255;
}
else
{
ptr[0]= wpos - 510;
ptr[1]= 0;
ptr[2]=765-wpos;
}
}
I figured the time rolls over in the middle of the for() loop, so each value displayed is correct to when it was assigned. I then went to check the data because surely there would be an instance where both values were changed on the same loop.
This loop calculates the even-addressed pixels, then prints all of them out. Then goes around the loop and calculates the odd-addressed pixels and then prints everything again.
It would make more sense to calculate all 8 pixel entries and then print them once:
You should also change this to avoid the rollover. You can read the day, hour, minutes and seconds into variables before entering the for loop and then reference those variables in the for loop.
The amount of pixels might vary depending on how the final device is built, and I'm planning a variety of different types. Some will have 8 pixels, some will have 12, others 24 or 32. So it's supposed to calculate the first pixel of each "block", and then the next, and so on. Some blocks might have 8 or more pixels in them. So assigning 8 values in one loop isn't an option (unless it is?), I want it flexible so I just have to change the #define.
I don't see anything different in the code block you posted Pete.
Accounting for the rollover is a good idea, and is on the 'to do' list once I get a RTC module. For now, they are just going to be placed in a light diffuser (Nice whiskey bottle or canning jar with translucent stones, there's also a dozen or so other color pattern programs included in the final sketch that will get cycled between), so the colors get muddled and mixed (intentional). Reading the exact time from this display will be quite difficult, so if it does happen to crash, or get out of time, I'm not too worried about it. (You did mean the max millis() value rollover right?)
And the Serial Prints are there just for debugging, the final product won't have any connections.
Marmotjr:
Just after Posting, I had an "Ahha!" moment.
I figured the time rolls over in the middle of the for() loop, so each value displayed is correct to when it was assigned.
I have not studied you code but the usual answer for that problem is to save the time before you start the FOR loop and use the saved time in all calculations in the FOR loop.
Annnnnd I feel stupid, I don't have to run it to see the error. My "debugging" was adding a false bug. And it explains both scenarios where either the first or second element was getting updated before the other one.
Robin2:
I have not studied you code but the usual answer for that problem is to save the time before you start the FOR loop and use the saved time in all calculations in the FOR loop.
...R
That was my intention, but the Time library and I were not getting along, so I had it working as written, but couldn't figure out how to feed the functions a value.