initial commit
This commit is contained in:
commit
cfbe271e45
5
.gitignore
vendored
Executable file
5
.gitignore
vendored
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/
|
||||||
|
.travis.yml
|
||||||
|
.BROWSE*
|
||||||
|
lib/
|
152
include/colors.h
Executable file
152
include/colors.h
Executable file
@ -0,0 +1,152 @@
|
|||||||
|
typedef struct {
|
||||||
|
double r; // a fraction between 0 and 1
|
||||||
|
double g; // a fraction between 0 and 1
|
||||||
|
double b; // a fraction between 0 and 1
|
||||||
|
} rgb;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double h; // angle in degrees
|
||||||
|
double s; // a fraction between 0 and 1
|
||||||
|
double v; // a fraction between 0 and 1
|
||||||
|
} hsv;
|
||||||
|
|
||||||
|
static rgb int2rgb(uint32_t in);
|
||||||
|
static hsv rgb2hsv(rgb in);
|
||||||
|
static rgb hsv2rgb(hsv in);
|
||||||
|
|
||||||
|
rgb int2rgb(uint32_t in)
|
||||||
|
{
|
||||||
|
rgb out;
|
||||||
|
out.r = (in >> 16) & 255;
|
||||||
|
out.g = (in >> 8) & 255;
|
||||||
|
out.b = in & 255;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
hsv rgb2hsv(rgb in)
|
||||||
|
{
|
||||||
|
hsv out;
|
||||||
|
double min, max, delta;
|
||||||
|
|
||||||
|
min = in.r < in.g ? in.r : in.g;
|
||||||
|
min = min < in.b ? min : in.b;
|
||||||
|
|
||||||
|
max = in.r > in.g ? in.r : in.g;
|
||||||
|
max = max > in.b ? max : in.b;
|
||||||
|
|
||||||
|
out.v = max;
|
||||||
|
delta = max - min;
|
||||||
|
|
||||||
|
if (delta < 0.00001)
|
||||||
|
{
|
||||||
|
out.s = 0;
|
||||||
|
out.h = 0;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
if(max > 0.0)
|
||||||
|
{
|
||||||
|
out.s = (delta / max);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.s = 0.0;
|
||||||
|
out.h = 0;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in.r >= max)
|
||||||
|
out.h = ( in.g - in.b ) / delta;
|
||||||
|
else if(in.g >= max)
|
||||||
|
out.h = 2.0 + ( in.b - in.r ) / delta;
|
||||||
|
else
|
||||||
|
out.h = 4.0 + ( in.r - in.g ) / delta;
|
||||||
|
|
||||||
|
out.h *= 60.0;
|
||||||
|
|
||||||
|
if(out.h < 0.0)
|
||||||
|
out.h += 360.0;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rgb hsv2rgb(hsv in)
|
||||||
|
{
|
||||||
|
double hh, p, q, t, ff;
|
||||||
|
long i;
|
||||||
|
rgb out;
|
||||||
|
|
||||||
|
if(in.s <= 0.0)
|
||||||
|
{
|
||||||
|
out.r = in.v;
|
||||||
|
out.g = in.v;
|
||||||
|
out.b = in.v;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
hh = in.h;
|
||||||
|
|
||||||
|
if(hh >= 360.0)
|
||||||
|
hh = 0.0;
|
||||||
|
|
||||||
|
hh /= 60.0;
|
||||||
|
i = (long)hh;
|
||||||
|
ff = hh - i;
|
||||||
|
p = in.v * (1.0 - in.s);
|
||||||
|
q = in.v * (1.0 - (in.s * ff));
|
||||||
|
t = in.v * (1.0 - (in.s * (1.0 - ff)));
|
||||||
|
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
out.r = in.v;
|
||||||
|
out.g = t;
|
||||||
|
out.b = p;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
out.r = q;
|
||||||
|
out.g = in.v;
|
||||||
|
out.b = p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
out.r = p;
|
||||||
|
out.g = in.v;
|
||||||
|
out.b = t;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
out.r = p;
|
||||||
|
out.g = q;
|
||||||
|
out.b = in.v;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
out.r = t;
|
||||||
|
out.g = p;
|
||||||
|
out.b = in.v;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
default:
|
||||||
|
out.r = in.v;
|
||||||
|
out.g = p;
|
||||||
|
out.b = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb gradient(rgb start, rgb end, double ratio)
|
||||||
|
{
|
||||||
|
if(ratio < 0)
|
||||||
|
ratio = 0;
|
||||||
|
if(ratio > 1)
|
||||||
|
ratio = 1;
|
||||||
|
|
||||||
|
auto start_hsv = rgb2hsv(start);
|
||||||
|
auto end_hsv = rgb2hsv(end);
|
||||||
|
|
||||||
|
hsv result;
|
||||||
|
result.h = start_hsv.h + ratio * (end_hsv.h - start_hsv.h);
|
||||||
|
result.s = start_hsv.s + ratio * (end_hsv.s - start_hsv.s);
|
||||||
|
result.v = start_hsv.v + ratio * (end_hsv.v - start_hsv.v);
|
||||||
|
|
||||||
|
return hsv2rgb(result);
|
||||||
|
}
|
22
include/config.h
Normal file
22
include/config.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SSID "Galaxy"
|
||||||
|
#define PASSWORD "changeme"
|
||||||
|
|
||||||
|
#define NTP_SERVER "0.be.pool.ntp.org"
|
||||||
|
|
||||||
|
#define PIN D4
|
||||||
|
#define NUMPIXELS 20
|
||||||
|
|
||||||
|
const uint32_t PALETTES[] =
|
||||||
|
{
|
||||||
|
0xc43f1a, 0x75266f, 0x43aba3,
|
||||||
|
0x542424, 0xe1b343, 0xefc988,
|
||||||
|
0xAA5E47, 0xDDA254, 0x4D7A5C,
|
||||||
|
0x034F4D, 0x53BD99, 0x1A8263,
|
||||||
|
0xfb9568, 0x729575, 0x1eeac5,
|
||||||
|
0x2F66C4, 0xF04F4F, 0x1EBA8B,
|
||||||
|
0x428529, 0xFFCBB5, 0x767FA6
|
||||||
|
};
|
||||||
|
|
||||||
|
const int PALETTE_COUNT = sizeof(PALETTES) / sizeof(uint32_t) / 3;
|
11
platformio.ini
Executable file
11
platformio.ini
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
[env:d1_mini_lite]
|
||||||
|
platform = espressif8266
|
||||||
|
board = d1_mini_lite
|
||||||
|
framework = arduino
|
||||||
|
build_flags = -fexceptions
|
||||||
|
build_unflags = -fno-exceptions
|
||||||
|
; upload_protocol = espota
|
||||||
|
; upload_port = 192.168.1.157
|
||||||
|
; upload_speed = 115200
|
||||||
|
lib_deps = Adafruit NeoPixel
|
||||||
|
NTPClient
|
143
src/main.cpp
Executable file
143
src/main.cpp
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
#include <NTPClient.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "colors.h"
|
||||||
|
|
||||||
|
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
WiFiUDP ntpUDP;
|
||||||
|
NTPClient timeClient(ntpUDP, NTP_SERVER, 60 * 60);
|
||||||
|
|
||||||
|
const int LEDS_HOURS_1[] = { 2, 3, 4, 5 };
|
||||||
|
const int LEDS_HOURS_2[] = { 1, 0 };
|
||||||
|
const int LEDS_MINUTES_1[] = { 9, 10, 11, 12 };
|
||||||
|
const int LEDS_MINUTES_2[] = { 8, 7, 6 };
|
||||||
|
const int LEDS_SECONDS_1[] = { 16, 17, 18, 19 };
|
||||||
|
const int LEDS_SECONDS_2[] = { 15, 14, 13 };
|
||||||
|
|
||||||
|
rgb start = int2rgb(0xff0000);
|
||||||
|
rgb end = int2rgb(0x49cb2c);
|
||||||
|
|
||||||
|
void display_progress(int percentage)
|
||||||
|
{
|
||||||
|
pixels.clear();
|
||||||
|
int activeLedCount = (int)(NUMPIXELS / 100.0 * percentage);
|
||||||
|
|
||||||
|
|
||||||
|
for(int i=0; i<activeLedCount; i++)
|
||||||
|
{
|
||||||
|
auto color = gradient(start, end, i/(double)NUMPIXELS);
|
||||||
|
pixels.setPixelColor(i, color.r, color.g, color.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
pixels.begin();
|
||||||
|
pixels.clear();
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
|
||||||
|
WiFi.hostname("BinaryClock2");
|
||||||
|
WiFi.begin(SSID, PASSWORD);
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
while(WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
|
delay(500);
|
||||||
|
auto color = gradient(start, end, i/(double)NUMPIXELS);
|
||||||
|
pixels.setPixelColor(i++, color.r, color.g, color.b);
|
||||||
|
pixels.show();
|
||||||
|
if(i >= NUMPIXELS)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
pixels.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(WiFi.isConnected())
|
||||||
|
{
|
||||||
|
Serial.print(WiFi.localIP().toString());
|
||||||
|
|
||||||
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
display_progress(progress / (total / 100.0));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ArduinoOTA.onEnd([]()
|
||||||
|
{
|
||||||
|
for(int i=0; i<NUMPIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, 0x51, 0x6f, 0xf6);
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
delay(40);
|
||||||
|
}
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
timeClient.begin();
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayBinary(int value, const int* leds, uint32_t color)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
while(value != 0)
|
||||||
|
{
|
||||||
|
bool isOn = value & 0b1;
|
||||||
|
value = value >> 1;
|
||||||
|
if(isOn)
|
||||||
|
pixels.setPixelColor(leds[index], color);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if(WiFi.isConnected())
|
||||||
|
{
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
timeClient.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int seconds = timeClient.getSeconds();
|
||||||
|
int minutes = timeClient.getMinutes();
|
||||||
|
int hours = timeClient.getHours();
|
||||||
|
int hours_1 = hours % 10;
|
||||||
|
int hours_2 = (hours / 10) % 10;
|
||||||
|
int minutes_1 = minutes % 10;
|
||||||
|
int minutes_2 = (minutes / 10) % 10;
|
||||||
|
int seconds_1 = seconds % 10;
|
||||||
|
int seconds_2 = (seconds / 10) % 10;
|
||||||
|
|
||||||
|
int palette_index = hours % PALETTE_COUNT;
|
||||||
|
uint32_t color_hours = PALETTES[palette_index];
|
||||||
|
uint32_t color_minutes = PALETTES[palette_index + 1];
|
||||||
|
uint32_t color_seconds = PALETTES[palette_index + 2];
|
||||||
|
|
||||||
|
pixels.clear();
|
||||||
|
|
||||||
|
displayBinary(hours_1, &LEDS_HOURS_1[0], color_hours);
|
||||||
|
displayBinary(hours_2, &LEDS_HOURS_2[0], color_hours);
|
||||||
|
displayBinary(minutes_1, &LEDS_MINUTES_1[0], color_minutes);
|
||||||
|
displayBinary(minutes_2, &LEDS_MINUTES_2[0], color_minutes);
|
||||||
|
displayBinary(seconds_1, &LEDS_SECONDS_1[0], color_seconds);
|
||||||
|
displayBinary(seconds_2, &LEDS_SECONDS_2[0], color_seconds);
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user