HEY! If you’re finding this page then you’re probably just as excited to make the Neopixel clock you saw on Hackster.io as much as I am. BUT IT’S GONE!
Never fear, it was licensed under Creative Commons 3.0 non-commercial, so even though the website has evaporated we can work on!
The original project can be found here. And a full mini project can be found here on hackaday.io.
Here’s the original video:
Just incase you thought it was impossible to replicate, here’s somebody’s replication.
But I hear you asking, what about the files?
Here’s the Gerber file for the PCBs. I recommend using JLCPCB if you’re not in a position to make it yourself.
This is my best guess at how to attach the components to the back. Hope it’s enough for you.
This is the code:
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 9
#define SEGMENTS_PER_DIGIT 7
#define LEDS_PER_SEGMENT 2
#define LEDS_PER_DIGIT 14
#define GRID_WIDTH 17
#define GRID_HEIGHT 7
#define NUMPIXELS 58
#include <Wire.h>
#include "RTClib.h"
#include <Encoder.h>
RTC_DS3231 rtc;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int mode = 0;
bool justEnteredMode = true;
double timeOfLastInput = 0;
double timeOfLastRefresh = 0;
int inactivityTimeoutDuration = 3000;
uint32_t startColor,endColor;
uint16_t startHue = 0;
uint16_t endHue = 80;
int brightness = 10;
int buttonPin = 10;
bool oldButtonState = 1;
Encoder myEnc(3, 2);
long oldPosition = -999;
int inputHours = 1;
int inputTenMinutes = 0;
int inputMinutes = 0;
int inputColor = 0;
int inputColorShift = 12;
int inputColorDirection = 0;
// Defines the light number for each light by its position in a grid covering the whole clock face
// 999 indicates positions where no light exists
const int PROGMEM pixelNumber[7][17] =
{
{999, 0, 1,999,999, 14, 15,999,999,999, 30, 31,999,999, 44, 45,999},
{ 11,999,999, 2, 25,999,999, 16,999, 41,999,999, 32, 55,999,999, 46},
{ 10,999,999, 3, 24,999,999, 17, 29, 40,999,999, 33, 54,999,999, 47},
{999, 12, 13,999,999, 26, 27,999,999,999, 42, 43,999,999, 56, 57,999},
{ 9,999,999, 4, 23,999,999, 18, 28, 39,999,999, 34, 53,999,999, 48},
{ 8,999,999, 5, 22,999,999, 19,999, 38,999,999, 35, 52,999,999, 49},
{999, 7, 6,999,999, 21, 20,999,999,999, 37, 36,999,999, 51, 50,999},
};
const int pixelValues[][14] = {
{1,1,1,1,1,1,1,1,1,1,1,1,0,0}, // Number 0
{0,0,1,1,1,1,0,0,0,0,0,0,0,0}, // Number 1
{1,1,1,1,0,0,1,1,1,1,0,0,1,1}, // Number 2
{1,1,1,1,1,1,1,1,0,0,0,0,1,1}, // Number 3
{0,0,1,1,1,1,0,0,0,0,1,1,1,1}, // Number 4
{1,1,0,0,1,1,1,1,0,0,1,1,1,1}, // Number 5
{1,1,0,0,1,1,1,1,1,1,1,1,1,1}, // Number 6
{1,1,1,1,1,1,0,0,0,0,0,0,0,0}, // Number 7
{1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Number 8
{1,1,1,1,1,1,1,1,0,0,1,1,1,1}, // Number 9
{0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Digit off
};
void setup () {
Serial.begin(9600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
// Uncomment below to set time to compile time.
// THIS WILL KEEP RESETTING THE TIME EVERY BOOT UNTIL CODE WITH THIS DISABLED IS UPLOADED
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
strip.begin(); // This initializes the NeoPixel library.
pinMode(buttonPin, INPUT_PULLUP); // sets the digital pin as output
}
void loop () {
if (digitalRead(buttonPin) == 0 && oldButtonState == 1) {
mode++;
justEnteredMode = true;
timeOfLastInput = millis(); // Count mode switching as an input
}
oldButtonState = digitalRead(buttonPin);
int delayNum = 500;
DateTime now = rtc.now();
int convertedHour;
if (now.hour() > 12) {
convertedHour = now.hour() - 12;
}
else {
convertedHour = now.hour();
}
int num0 = (convertedHour /10) % 10;
int num1 = convertedHour % 10;
int num2 = (now.minute() /10) % 10;
int num3 = now.minute() % 10;
// Time display and brightness adjust mode
if (mode == 0) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 0, display time");
}
justEnteredMode = false;
adjustVariable(&brightness, 1, 1, 20);
updateDigits(num0,num1,num2,num3);
inputColor += 5;
}
// Color set mode
else if (mode == 1) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 1, set color 1");
updateDigits(1, 10, 10, 10);
delay(500);
}
justEnteredMode = false;
adjustVariable(&inputColor, 10, 0, 360);
resetModeAfterInactivity();
updateDigits(8, 8, 8, 8);
}
// Color shift amount set mode
else if (mode == 2) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 2, set color shift amount");
updateDigits(2, 10, 10, 10);
delay(500);
}
justEnteredMode = false;
adjustVariable(&inputColorShift, 1, 0, 30);
resetModeAfterInactivity();
updateDigits(8, 8, 8, 8);
}
// Gradient direction set mode
else if (mode == 3) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 3, set gradient direction");
updateDigits(3, 10, 10, 10);
delay(500);
}
justEnteredMode = false;
adjustVariable(&inputColorDirection, 1, 0, 2);
resetModeAfterInactivity();
updateDigits(8, 8, 8, 8);
}
// Hour set mode
else if (mode == 4) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 4, set hour");
}
justEnteredMode = false;
adjustVariable(&inputHours, 1, 1, 12);
int digitOne = (inputHours / 10) % 10;
int digitTwo = inputHours % 10;
resetModeAfterInactivity();
updateDigits(digitOne, digitTwo, 10, 10);
rtc.adjust(DateTime(now.year(), now.month(), now.day(), inputHours, now.minute(), now.second()));
}
//Ten minute set mode
else if (mode == 5) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 5, set ten minutes");
}
justEnteredMode = false;
adjustVariable(&inputTenMinutes, 1, 0, 5);
resetModeAfterInactivity();
updateDigits(10, 10, inputTenMinutes, 10);
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), inputTenMinutes*10, 0));
}
//Minute set mode
else if (mode == 6) {
// Run only on first instance of loop
if (justEnteredMode == true) {
Serial.println("Mode 6, set minute");
}
justEnteredMode = false;
adjustVariable(&inputMinutes, 1, 0, 9);
resetModeAfterInactivity();
updateDigits(10, 10, 10, inputMinutes);
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), (inputTenMinutes*10) + inputMinutes, 0));
}
else {
mode = 0;
}
}
void resetModeAfterInactivity() {
if (timeOfLastInput + inactivityTimeoutDuration < millis()) {
Serial.print("Time of last input: ");
Serial.print(timeOfLastInput);
Serial.print(". Current milis: ");
Serial.println(millis());
mode = 0;
}
}
void updateDigits(int num0, int num1, int num2, int num3) {
if (timeOfLastRefresh + 100 < millis()) {
timeOfLastRefresh = millis();
// Set the segments
for (int v=0; v<GRID_HEIGHT; v++) {
for (int h=0; h<GRID_WIDTH; h++) {
int currentPixelNumber = pgm_read_word_near(&(pixelNumber[v][h]));
if (currentPixelNumber != 999) {
// There is a pixel here, see if it should be lit
int digitOffset = 0;
// Track which number we want to draw to the current digit position
int numberToDraw;
// Track if we're on a divider pixel
bool divider = false;
// First digit
if (h >= 0 && h < LEDS_PER_SEGMENT + 2) {
digitOffset = 0;
numberToDraw = num0;
if (numberToDraw == 0) {
numberToDraw = 10;
}
}
// Second digit
if (h >=LEDS_PER_SEGMENT + 2 && h < (LEDS_PER_SEGMENT * 2) + 4) {
digitOffset = LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT;
numberToDraw = num1;
}
// Divider
if (h == (LEDS_PER_SEGMENT * 2) + 4) {
digitOffset = (LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT) * 2;
divider = true;
}
if (h >= (LEDS_PER_SEGMENT * 2) + 5 && h <= (LEDS_PER_SEGMENT * 3) + 6) {
digitOffset = (LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT) * 2 + 2;
numberToDraw = num2;
}
if (h >= (LEDS_PER_SEGMENT * 3) + 7 && h <= (LEDS_PER_SEGMENT * 4) + 8) {
digitOffset = (LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT) * 3 + 2;
numberToDraw = num3;
}
if (pixelValues[numberToDraw][currentPixelNumber-digitOffset] == 1 || divider == true) {
if (inputColorDirection == 0) {
strip.setPixelColor(currentPixelNumber, HSV_to_RGB(inputColor + h*inputColorShift,100,brightness));
}
else if (inputColorDirection == 1) {
strip.setPixelColor(currentPixelNumber, HSV_to_RGB(inputColor + v*inputColorShift,100,brightness));
}
else {
strip.setPixelColor(currentPixelNumber, HSV_to_RGB(inputColor,100,brightness));
}
}
else {
strip.setPixelColor(currentPixelNumber, strip.Color(0,0,0));
}
strip.show();
}
else {
// 999 means no pixel here, do nothing
}
}
}
}
}
void adjustVariable(int *variable, int increment, int minNum, int maxNum) {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
if (oldPosition > newPosition) {
*variable -= increment;
timeOfLastInput = millis();
if (*variable < minNum) {
*variable = maxNum;
}
Serial.print("Decrease to");
Serial.println(*variable + increment);
}
if (oldPosition < newPosition) {
*variable += increment;
timeOfLastInput = millis();
if (*variable > maxNum) {
*variable = minNum;
}
Serial.print("Increase to ");
Serial.println(*variable - increment);
}
oldPosition = newPosition;
}
}
uint32_t HSV_to_RGB(float h, float s, float v) {
int i;
float f,p,q,t;
uint8_t r,g,b;
while (h >= 360) {
h = h - 360;
}
while (h < 0) {
h = h + 360;
}
h = max(0.0, min(360.0, h));
s = max(0.0, min(100.0, s));
v = max(0.0, min(100.0, v));
s /= 100;
v /= 100;
if(s == 0) {
// Achromatic (grey)
r = g = b = round(v*255);
return;
}
h /= 60; // sector 0 to 5
i = floor(h);
f = h - i; // factorial part of h
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch(i) {
case 0:
r = round(255*v);
g = round(255*t);
b = round(255*p);
break;
case 1:
r = round(255*q);
g = round(255*v);
b = round(255*p);
break;
case 2:
r = round(255*p);
g = round(255*v);
b = round(255*t);
break;
case 3:
r = round(255*p);
g = round(255*q);
b = round(255*v);
break;
case 4:
r = round(255*t);
g = round(255*p);
b = round(255*v);
break;
default: // case 5:
r = round(255*v);
g = round(255*p);
b = round(255*q);
}
return strip.Color(r,g,b);
};
#include <Adafruit_NeoPixel.h>
#include <math.h>
#include <Wire.h>
#include "RTClib.h"
#include <Encoder.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 9
#define SEGMENTS_PER_DIGIT 7
#define LEDS_PER_SEGMENT 2
#define LEDS_PER_DIGIT 14
#define GRID_WIDTH 17
#define GRID_HEIGHT 7
#define NUMPIXELS 58
RTC_DS3231 rtc;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int mode = 0;
bool justEnteredMode = true;
double timeOfLastInput = 0;
double timeOfLastRefresh = 0;
int inactivityTimeoutDuration = 10000;
uint32_t startColor,endColor;
uint16_t startHue = 0;
uint16_t endHue = 80;
int brightness = 5;
int inputHours = 1;
int inputMinutes = 0;
int inputColor = 0;
int inputColorShift = 12;
int inputColorDirection = 0;
int analogInput = 0;
bool upIsPressed, rightIsPressed, downIsPressed, leftIsPressed, centerIsPressed = false;
int upHeldCycles, rightHeldCycles, downHeldCycles, leftHeldCycles, centerHeldCycles = 0;
// Defines the light number for each light by its position in a grid covering the whole clock face
// 0 indicates positions where no light exists
const int PROGMEM pixelNumber[7][17] =
{
{ 0, 1, 2, 0, 0,15,16, 0, 0, 0,31,32, 0, 0,45,46, 0},
{12, 0, 0, 3, 26, 0, 0,17, 0, 42, 0, 0,33, 56, 0, 0,47},
{11, 0, 0, 4, 25, 0, 0,18, 30, 41, 0, 0,34, 55, 0, 0,48},
{ 0,13,14, 0, 0,27,28, 0, 0, 0,43,44, 0, 0,57,58, 0},
{10, 0, 0, 5, 24, 0, 0,19, 29, 40, 0, 0,35, 54, 0, 0,49},
{ 9, 0, 0, 6, 23, 0, 0,20, 0, 39, 0, 0,36, 53, 0, 0,50},
{ 0, 8, 7, 0, 0,22,21, 0, 0, 0,38,37, 0, 0,52,51, 0},
};
const int pixelValues[][14] =
{
{1,1,1,1,1,1,1,1,1,1,1,1,0,0}, // Number 0
{0,0,1,1,1,1,0,0,0,0,0,0,0,0}, // Number 1
{1,1,1,1,0,0,1,1,1,1,0,0,1,1}, // Number 2
{1,1,1,1,1,1,1,1,0,0,0,0,1,1}, // Number 3
{0,0,1,1,1,1,0,0,0,0,1,1,1,1}, // Number 4
{1,1,0,0,1,1,1,1,0,0,1,1,1,1}, // Number 5
{1,1,0,0,1,1,1,1,1,1,1,1,1,1}, // Number 6
{1,1,1,1,1,1,0,0,0,0,0,0,0,0}, // Number 7
{1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Number 8
{1,1,1,1,1,1,1,1,0,0,1,1,1,1}, // Number 9
{0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Digit off
};
void setup ()
{
Serial.begin(9600);
if (! rtc.begin())
{
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower())
{
Serial.println("RTC lost power, lets set the time!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
// Uncomment below to set time to compile time.
// THIS WILL KEEP RESETTING THE TIME EVERY BOOT UNTIL CODE WITH THIS DISABLED IS UPLOADED
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
strip.begin(); // This initializes the NeoPixel library.
pinMode(A3, INPUT);
}
void loop ()
{
analogInput = analogRead(A2);
if (upIsPressed)
upHeldCycles++;
else
upHeldCycles = 0;
if (rightIsPressed)
rightHeldCycles++;
else
rightHeldCycles = 0;
if (downIsPressed)
downHeldCycles++;
else
downHeldCycles = 0;
if (leftIsPressed)
leftHeldCycles++;
else
leftHeldCycles = 0;
if (centerIsPressed)
centerHeldCycles++;
else
centerHeldCycles = 0;
upIsPressed = rightIsPressed = downIsPressed = leftIsPressed = centerIsPressed = false;
// Set isPressedValues
if (analogInput > 30 && analogInput < 60)
{
upIsPressed = true;
timeOfLastInput = millis();
Serial.print("up ");
Serial.println(upHeldCycles);
}
else if (analogInput > 160 && analogInput < 200)
{
rightIsPressed = true;
timeOfLastInput = millis();
Serial.print("right ");
Serial.println(rightHeldCycles);
}
else if (analogInput > 500 && analogInput < 550)
{
downIsPressed = true;
timeOfLastInput = millis();
Serial.print("down ");
Serial.println(downHeldCycles);
}
else if (analogInput > 660 && analogInput < 720)
{
leftIsPressed = true;
timeOfLastInput = millis();
Serial.print("left ");
Serial.println(leftHeldCycles);
}
else if (analogInput > 1000 && analogInput < 1025)
{
centerIsPressed = true;
timeOfLastInput = millis();
Serial.print("center ");
Serial.println(centerHeldCycles);
}
if (leftHeldCycles == 1)
{
mode--;
justEnteredMode = true;
}
if (rightHeldCycles == 1)
{
mode++;
justEnteredMode = true;
}
int delayNum = 500;
DateTime now = rtc.now();
int convertedHour;
if (now.hour() > 12)
{
convertedHour = now.hour() - 12;
}
else
{
convertedHour = now.hour();
}
int num0 = (convertedHour /10) % 10;
int num1 = convertedHour % 10;
int num2 = (now.minute() /10) % 10;
int num3 = now.minute() % 10;
// Time display and brightness adjust mode
if (mode == 0)
{
// Run only on first instance of loop
if (justEnteredMode == true)
{
Serial.println("Mode 0, display time");
Serial.print(num0);
Serial.print(num1);
Serial.print(":");
Serial.print(num2);
Serial.println(num3);
}
justEnteredMode = false;
if (upIsPressed)
{
adjustVariable(&brightness, 1, 1, 100);
Serial.print("Brightness raised to ");
Serial.println(brightness);
}
if (downIsPressed)
{
adjustVariable(&brightness, -1, 1, 100);
Serial.print("Brightness lowered to ");
Serial.println(brightness);
}
updateDigits(num0,num1,num2,num3);
inputColor += 5;
}
// Color set mode
else if (mode == 1)
{
// Run only on first instance of loop
if (justEnteredMode == true)
{
Serial.println("Mode 1, set color 1");
updateDigits(1, 10, 10, 10);
delay(300);
}
justEnteredMode = false;
if (upIsPressed)
{
adjustVariable(&inputColor, -5, 0, 360);
Serial.print("Input color raised to ");
Serial.println(inputColor);
}
if (downIsPressed)
{
adjustVariable(&inputColor, 5, 0, 360);
Serial.print("Input color lowered to ");
Serial.println(inputColor);
}
resetModeAfterInactivity();
updateDigits(8, 8, 8, 8);
}
// Color shift amount set mode
else if (mode == 2)
{
// Run only on first instance of loop
if (justEnteredMode == true)
{
Serial.println("Mode 2, set color shift amount");
updateDigits(2, 10, 10, 10);
delay(300);
}
justEnteredMode = false;
if (upIsPressed)
{
adjustVariable(&inputColorShift, -1, -30, 30);
Serial.print("Color shift amount raised to ");
Serial.println(inputColorShift);
}
if (downIsPressed)
{
adjustVariable(&inputColorShift, 1, -30, 30);
Serial.print("Color shift amount lowered to ");
Serial.println(inputColorShift);
}
resetModeAfterInactivity();
updateDigits(8, 8, 8, 8);
}
// Gradient direction set mode
else if (mode == 3)
{
// Run only on first instance of loop
if (justEnteredMode == true)
{
Serial.println("Mode 3, set gradient direction");
updateDigits(3, 10, 10, 10);
delay(300);
}
justEnteredMode = false;
if (upIsPressed)
{
adjustVariable(&inputColorDirection, -1, 0, 2);
Serial.print("Input color direction set to ");
Serial.println(inputColorDirection);
}
if (downIsPressed)
{
adjustVariable(&inputColorDirection, 1, 0, 2);
Serial.print("Input color direction set to ");
Serial.println(inputColorDirection);
}
resetModeAfterInactivity();
updateDigits(8, 8, 8, 8);
}
// Hour set mode
else if (mode == 4)
{
// Run only on first instance of loop
if (justEnteredMode == true)
{
Serial.println("Mode 4, set hour");
}
justEnteredMode = false;
if (upIsPressed)
{
adjustVariable(&inputHours, 1, 1, 12);
Serial.print("Hours raised to ");
Serial.println(inputHours);
}
if (downIsPressed)
{
adjustVariable(&inputHours, -1, 1, 12);
Serial.print("Hours lowered to ");
Serial.println(inputHours);
}
int digitOne = (millis() % 1000 < 800) ? (inputHours / 10) % 10 : 10;
int digitTwo = (millis() % 1000 < 800) ? inputHours % 10 : 10;
resetModeAfterInactivity();
updateDigits(digitOne, digitTwo, num2, num3);
rtc.adjust(DateTime(now.year(), now.month(), now.day(), inputHours, now.minute(), 0));
}
// Minute set mode
else if (mode == 5)
{
inputMinutes = now.minute();
// Run only on first instance of loop
if (justEnteredMode == true)
{
Serial.println("Mode 6, set minutes");
}
justEnteredMode = false;
if (upIsPressed)
{
adjustVariable(&inputMinutes, 1, 0, 59);
Serial.print("Minutes raised to ");
Serial.println(inputMinutes);
}
if (downIsPressed)
{
adjustVariable(&inputMinutes, -1, 0, 59);
Serial.print("Minutes lowered to ");
Serial.println(inputMinutes);
}
resetModeAfterInactivity();
int digitThree = (millis() % 1000 < 800) ? floor(inputMinutes/10) : 10;
int digitFour = (millis() % 1000 < 800) ? (inputMinutes % 10) : 10;
//int digitThree = floor(inputMinutes / 10);
//int digitFour = inputMinutes % 10;
updateDigits(num0, num1, digitThree, digitFour);
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), inputMinutes, 0));
}
else
{
mode = 0;
}
}
void resetModeAfterInactivity()
{
if (timeOfLastInput + inactivityTimeoutDuration < millis())
{
Serial.print("Time of last input: ");
Serial.print(timeOfLastInput);
Serial.print(". Current milis: ");
Serial.println(millis());
mode = 0;
}
}
void updateDigits(int num0, int num1, int num2, int num3)
{
if (timeOfLastRefresh + 100 < millis())
{
timeOfLastRefresh = millis();
// Set the segments
for (int v=0; v<GRID_HEIGHT; v++)
{
for (int h=0; h<GRID_WIDTH; h++)
{
// Subtract one from the value we retrieve because
// we're starting at 1 in the array
// but at 0 on strip.setPixelColor
int currentPixelNumber = pgm_read_word_near(&(pixelNumber[v][h])) - 1;
if (currentPixelNumber >= 0)
{
// There is a pixel here, see if it should be lit
int digitOffset = 0;
// Track which number we want to draw to the current digit position
int numberToDraw;
// Track if we're on a divider pixel
bool divider = false;
// First digit
if (h >= 0 && h < LEDS_PER_SEGMENT + 2)
{
digitOffset = 0;
numberToDraw = num0;
if (numberToDraw == 0)
{
numberToDraw = 10;
}
}
// Second digit
if (h >=LEDS_PER_SEGMENT + 2 && h < (LEDS_PER_SEGMENT * 2) + 4)
{
digitOffset = LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT;
numberToDraw = num1;
}
// Divider
if (h == (LEDS_PER_SEGMENT * 2) + 4)
{
digitOffset = (LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT) * 2;
divider = true;
}
if (h >= (LEDS_PER_SEGMENT * 2) + 5 && h <= (LEDS_PER_SEGMENT * 3) + 6)
{
digitOffset = (LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT) * 2 + 2;
numberToDraw = num2;
}
if (h >= (LEDS_PER_SEGMENT * 3) + 7 && h <= (LEDS_PER_SEGMENT * 4) + 8)
{
digitOffset = (LEDS_PER_SEGMENT * SEGMENTS_PER_DIGIT) * 3 + 2;
numberToDraw = num3;
}
if (pixelValues[numberToDraw][currentPixelNumber-digitOffset] == 1 || divider == true)
{
if (inputColorDirection == 0)
{
uint32_t color = HSV_to_RGB(inputColor + h*inputColorShift,100,brightness);
strip.setPixelColor(currentPixelNumber, color);
}
else if (inputColorDirection == 1)
{
uint32_t color = HSV_to_RGB(inputColor + v*inputColorShift,100,brightness);
strip.setPixelColor(currentPixelNumber, color);
}
else
{
uint32_t color = HSV_to_RGB(inputColor,100,brightness);
strip.setPixelColor(currentPixelNumber, color);
}
}
else
{
uint32_t color = strip.Color(0,0,0);
strip.setPixelColor(currentPixelNumber, color);
}
strip.show();
}
}
}
}
}
void adjustVariable(int *variable, int change, int minNum, int maxNum)
{
*variable += change;
if (*variable < minNum)
*variable = maxNum;
if (*variable > maxNum)
*variable = minNum;
}
uint32_t HSV_to_RGB(float h, float s, float v)
{
int i;
float f,p,q,t;
uint8_t r,g,b;
while (h >= 360)
{
h = h - 360;
}
while (h < 0)
{
h = h + 360;
}
h = max(0.0, min(360.0, h));
s = max(0.0, min(100.0, s));
v = max(0.0, min(100.0, v));
s /= 100;
v /= 100;
if (s == 0)
{
// Achromatic (grey)
r = g = b = round(v*255);
return;
}
h /= 60; // sector 0 to 5
i = floor(h);
f = h - i; // factorial part of h
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch(i)
{
case 0:
r = round(255*v);
g = round(255*t);
b = round(255*p);
break;
case 1:
r = round(255*q);
g = round(255*v);
b = round(255*p);
break;
case 2:
r = round(255*p);
g = round(255*v);
b = round(255*t);
break;
case 3:
r = round(255*p);
g = round(255*q);
b = round(255*v);
break;
case 4:
r = round(255*t);
g = round(255*p);
b = round(255*v);
break;
default: // case 5:
r = round(255*v);
g = round(255*p);
b = round(255*q);
}