323 lines
9.9 KiB
C++
323 lines
9.9 KiB
C++
#include "time.h"
|
|
#include <TaskScheduler.h>
|
|
#include <NeoPixelBrightnessBus.h>
|
|
#include <IotWebConf.h>
|
|
#include <IotWebConfUsing.h>
|
|
// UpdateServer includes
|
|
#ifdef ESP8266
|
|
#include <ESP8266WiFi.h>
|
|
# include <ESP8266HTTPUpdateServer.h>
|
|
#include <TZ.h>
|
|
#define MYTZ TZ_Europe_Berlin
|
|
#include <coredecls.h> // settimeofday_cb()
|
|
//#include <Schedule.h>
|
|
//#include <PolledTimeout.h>
|
|
#include <sys/time.h> // struct timeval
|
|
#include <sntp.h> // sntp_servermode_dhcp()
|
|
#elif defined(ESP32)
|
|
#include <WiFi.h>
|
|
// For ESP32 IotWebConf provides a drop-in replacement for UpdateServer.
|
|
# include <IotWebConfESP32HTTPUpdateServer.h>
|
|
#endif
|
|
|
|
|
|
#define MOD(a,b) ((((a)%(b))+(b))%(b))
|
|
/* Model I
|
|
LDR (GL5516 ) is connected to GPIO 34 (Analog ADC1_CH6, 12bit resolution default
|
|
Light Resistance (at 10 Lux): 5-10 Kohm
|
|
Dark Resistance: 0.5 Mohm
|
|
over a 56k voltage divider . Dark (0.5MOhm) , 10Lux (5-10kOhm)
|
|
-----------------
|
|
ESP8266 24LED
|
|
5V--10k-+-LDR--GND -ADC
|
|
- 150k--220k-+-100k--GND
|
|
*/
|
|
#ifdef ESP8266
|
|
#define LDR_PIN A0
|
|
#define IOTWEBCONF_DEBUG_DISABLED
|
|
#define DATA_PIN D7 //DMA RDX0/GPIO3 | Uart1 TXD1/GPIO2 | UART0 GPIO1
|
|
#elif defined(ESP32)
|
|
#define LDR_PIN A6
|
|
#define DATA_PIN 17
|
|
#endif
|
|
/* useful preselection
|
|
NO following hour
|
|
NO three block hour marking
|
|
quarter hour marking
|
|
*/
|
|
#define NUM_LEDS 60 //24
|
|
#define SERIAL_BAUD 115200
|
|
|
|
#define RGBW
|
|
const bool clockwiseRing = false;
|
|
volatile bool singleSecond = false; //show seconds
|
|
volatile bool allDotsOn = true; //lighten up all leds
|
|
#if NUM_LEDS == 60
|
|
volatile bool followingHour = true; //move hour like an analog one
|
|
#else
|
|
//#endif
|
|
//#if NUM_LEDS == 24
|
|
volatile bool followingHour = false; //disabled due limited resolution
|
|
#endif
|
|
volatile int hourOffset = 0;
|
|
|
|
void bootAnimCallback();
|
|
void clockTickCallback();
|
|
void ledRefreshCallback();
|
|
void brightnessAdjustmentCallback();
|
|
|
|
#ifdef RGBW
|
|
#define MINIMAL_BRIGHTNESS 5
|
|
#define LDR_SCALE 16
|
|
#define colorSaturation 255
|
|
#ifdef ESP8266
|
|
//NeoPixelBrightnessBus<NeoGrbwFeature, Neo800KbpsMethod> strip(NUM_LEDS);//RDX0 GPIO3
|
|
//NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266AsyncUart0Sk6812Method> strip(NUM_LEDS);
|
|
//NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266Uart0Sk6812Method> strip(NUM_LEDS);
|
|
NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266BitBang800KbpsMethod> strip(NUM_LEDS, DATA_PIN);
|
|
#elif defined(ESP32)
|
|
NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //ESP32
|
|
#endif
|
|
RgbwColor red(colorSaturation, 0, 0, 0);
|
|
RgbwColor green(0, colorSaturation, 0, 0);
|
|
RgbwColor blue(0, 0, colorSaturation, 0);
|
|
RgbwColor realWhite(colorSaturation);
|
|
RgbwColor white(0, 0, 0, 40); //darkish dirt
|
|
RgbwColor whiter(0, 0, 0, 120); //darkish dirt
|
|
RgbwColor white12(0, 0, 0, 192); //darkish dirt
|
|
RgbwColor black(0);
|
|
RgbwColor gold(HtmlColor( 0xFFD700 ) );
|
|
RgbwColor orangered(HtmlColor( 0xFF4500 ) );
|
|
RgbwColor orange(HtmlColor( 0xFFA500 ) );
|
|
RgbwColor darkred(HtmlColor( 0x800000) );
|
|
RgbwColor darkgreen(HtmlColor( 0x006400) );
|
|
RgbwColor lightgreen(HtmlColor( 0x30ee30) );
|
|
RgbwColor temp;
|
|
RgbwColor secondsColor = black;
|
|
RgbwColor minuteColor = darkred;
|
|
RgbwColor hourColor = gold;
|
|
RgbwColor highnoonColor = white12;
|
|
RgbwColor backlightColor = white;
|
|
RgbwColor hourMarkingColor = whiter;
|
|
|
|
void transformtoHtmlColor (char* sOutput, RgbwColor* inputColor) {
|
|
//Serial.printf("InputColor: R:%i G:%i B:%i W:%i\n", inputColor.R, inputColor.G, inputColor.B, inputColor.W);
|
|
|
|
if (inputColor->IsMonotone())
|
|
{
|
|
//Serial.print("White: "); Serial.println(inputColor->W);
|
|
HtmlColor(RgbColor(inputColor->W, inputColor->W, inputColor->W)).ToNumericalString(sOutput, 12);
|
|
//Serial.println((char*)sOutput);
|
|
}
|
|
else {
|
|
//Serial.print("Color: "); Serial.print(inputColor->R); Serial.print(inputColor->G); Serial.println(inputColor->B);
|
|
HtmlColor(RgbColor(inputColor->R, inputColor->G, inputColor->B)).ToNumericalString(sOutput, 12);
|
|
//Serial.println((char*)sOutput);
|
|
}
|
|
}
|
|
|
|
void transformHtmltoStrip(RgbwColor* outputColor, char* sInput) {
|
|
HtmlColor htmlTemp;
|
|
//Serial.print("HtmltoStrip ");
|
|
//Serial.println((char*)sInput);
|
|
htmlTemp.Parse<HtmlColorNames>( sInput );
|
|
RgbwColor stripColor( htmlTemp );
|
|
//Serial.printf("StripColor: R:%i G:%i B:%i W:%i\n", stripColor.R, stripColor.G, stripColor.B, stripColor.W);
|
|
memcpy(outputColor, &stripColor, sizeof(stripColor));
|
|
}
|
|
|
|
|
|
#else
|
|
#define MINIMAL_BRIGHTNESS 20
|
|
#define LDR_SCALE 16
|
|
#define colorSaturation 192
|
|
#ifdef ESP8266
|
|
//NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> strip(NUM_LEDS);//RDX0 GPIO3 Broken due IoTWebConf
|
|
NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Uart1800KbpsMethod> strip(NUM_LEDS);
|
|
//NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266BitBang800KbpsMethod> strip(NUM_LEDS, DATA_PIN);
|
|
#elif defined(ESP32)
|
|
NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //ESP32
|
|
#endif
|
|
RgbColor red(colorSaturation, 0, 0);
|
|
RgbColor green(0, colorSaturation, 0);
|
|
RgbColor blue(0, 0, colorSaturation);
|
|
RgbColor realWhite(colorSaturation);
|
|
RgbColor black(0);
|
|
RgbColor white(30, 40, 35); //darkish dirt
|
|
RgbColor whiter(120, 120, 120); //darkish dirt
|
|
RgbColor white12(255, 255, 255); //darkish dirt
|
|
RgbColor gold(HtmlColor( 0xFFD700 ));
|
|
RgbColor orangered(HtmlColor( 0xFF4500 ));
|
|
RgbColor orange(HtmlColor( 0xFFA500 ));
|
|
RgbColor darkred(HtmlColor( 0x800000 ));
|
|
RgbColor darkgreen(HtmlColor( 0x006400 ));
|
|
RgbColor lightgreen(HtmlColor( 0x90ee90 ));
|
|
RgbColor temp;
|
|
RgbColor secondsColor = black;
|
|
RgbColor minuteColor = darkred;
|
|
RgbColor hourColor = gold;
|
|
RgbColor highnoonColor = white12;
|
|
RgbColor backlightColor = white;
|
|
RgbColor hourMarkingColor = whiter;
|
|
|
|
void transformtoHtmlColor (char* sOutput, RgbColor* inputColor) {
|
|
HtmlColor(RgbColor(inputColor->R, inputColor->G, inputColor->B)).ToNumericalString(sOutput, 12);
|
|
}
|
|
|
|
void transformHtmltoStrip(RgbColor* outputColor, char* sInput) {
|
|
HtmlColor htmlTemp;
|
|
//Serial.print("HtmltoStrip ");
|
|
//Serial.println((char*)sInput);
|
|
htmlTemp.Parse<HtmlColorNames>( sInput );
|
|
RgbColor stripColor( htmlTemp );
|
|
//Serial.printf("StripColor: R:%i G:%i B:%i W:%i\n", stripColor.R, stripColor.G, stripColor.B, stripColor.W);
|
|
memcpy(outputColor, &stripColor, sizeof(stripColor));
|
|
}
|
|
|
|
#endif
|
|
|
|
//const char* ntpServer = "pool.ntp.org";
|
|
const long gmtOffset_sec = 3600; //ToDo changable from user
|
|
const int daylightOffset_sec = 3600;
|
|
struct tm timeinfo;
|
|
|
|
volatile int currentSec = 59;
|
|
volatile int currentMin = 1;
|
|
volatile int currentHour = 2;
|
|
volatile bool NTPreachable = false;
|
|
|
|
#ifdef LDR_PIN
|
|
// variable for storing the potentiometer value
|
|
volatile unsigned int ldrValue = 0;
|
|
#endif
|
|
volatile int MAX_BRIGHTNESS = 200;
|
|
|
|
Task bootAnim(200, TASK_FOREVER, &bootAnimCallback);
|
|
Task clockTick(1000, TASK_FOREVER, &clockTickCallback);
|
|
Task ledRefresh(200, TASK_FOREVER, &ledRefreshCallback);
|
|
#ifdef LDR_PIN
|
|
Task brightness(10000, TASK_FOREVER, &brightnessAdjustmentCallback);
|
|
#endif
|
|
//Task iotwebconfLoop(200, TASK_FOREVER, &iotWebConf.doLoop);
|
|
Scheduler runner;
|
|
|
|
|
|
// WebPortal
|
|
const char thingName[] = "NTP-Clock-RGBLED";
|
|
const char wifiInitialApPassword[] = "12345678";
|
|
#define STRING_LEN 63
|
|
#define NUMBER_LEN 4
|
|
// -- Maximal length the input-range attributes can have.
|
|
#define COLOR_ATTR_LENGTH 60
|
|
// -- Configuration specific key. The value should be modified if config structure was changed.
|
|
#define CONFIG_VERSION "V1.1.5"
|
|
DNSServer dnsServer;
|
|
WebServer server(80);
|
|
#ifdef ESP8266
|
|
ESP8266HTTPUpdateServer httpUpdater;
|
|
#elif defined(ESP32)
|
|
HTTPUpdateServer httpUpdater;
|
|
#endif
|
|
IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword, CONFIG_VERSION);
|
|
|
|
void setup() {
|
|
#ifdef LDR_PIN
|
|
pinMode(LDR_PIN, INPUT_PULLUP);
|
|
#endif
|
|
pinMode(DATA_PIN, OUTPUT);
|
|
|
|
Serial.begin(SERIAL_BAUD);
|
|
Serial.flush();
|
|
Serial.print("\n\n\nCPU Frequency is: ");
|
|
#ifdef ESP8266
|
|
Serial.print(ESP.getCpuFreqMHz());
|
|
#elif defined(ESP32)
|
|
Serial.print(getCpuFrequencyMhz()); //Get CPU clock
|
|
#endif
|
|
Serial.println(" Mhz");
|
|
Serial.print("MAC address: ");
|
|
Serial.println(WiFi.macAddress()); //Get CPU clock
|
|
|
|
strip.Begin();
|
|
strip.ClearTo(white);
|
|
strip.SetBrightness( MINIMAL_BRIGHTNESS );
|
|
strip.Show();
|
|
|
|
runner.init();
|
|
runner.addTask(ledRefresh);
|
|
runner.addTask(clockTick);
|
|
#ifdef LDR_PIN
|
|
runner.addTask(brightness);
|
|
#endif
|
|
runner.addTask(bootAnim);
|
|
bootAnim.enable();
|
|
|
|
iotWebConf_Setup();
|
|
//Serial.end();
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
runner.execute();
|
|
iotWebConf.doLoop();
|
|
/*
|
|
while (Serial.available())
|
|
Serial.read();
|
|
*/
|
|
}
|
|
|
|
|
|
// Scheduler
|
|
void clockTickCallback() {
|
|
#ifdef LDR_PIN
|
|
ldrValue = (ldrValue + analogRead(LDR_PIN));
|
|
#endif
|
|
if (clockwiseRing) {
|
|
if (currentSec >= 60) {
|
|
currentSec = 0;
|
|
currentMin++;
|
|
if (!NTPreachable) {
|
|
syncNTP();
|
|
}
|
|
if (currentMin >= 60) {
|
|
currentMin = 0;
|
|
currentHour++;
|
|
if (currentHour >= 12) {
|
|
currentHour = 0;
|
|
syncNTP();
|
|
}
|
|
}
|
|
if (followingHour) {
|
|
hourOffset = int (currentMin * NUM_LEDS / 60 / 12); //negative value
|
|
//Serial.println("hourOffset: " + String(hourOffset));
|
|
}
|
|
//Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS)));
|
|
}
|
|
currentSec++;
|
|
|
|
}
|
|
else {
|
|
if (currentSec < 0) {
|
|
currentSec = 59;
|
|
currentMin--;
|
|
if (!NTPreachable) {
|
|
syncNTP();
|
|
}
|
|
if (currentMin < 0) {
|
|
currentMin = 59;
|
|
currentHour--;
|
|
if (currentHour < 0) {
|
|
currentHour = 11;
|
|
syncNTP();
|
|
}
|
|
}
|
|
if (followingHour) {
|
|
hourOffset = 0 + int((60 - currentMin * NUM_LEDS / 60) / 12); //negative value
|
|
//Serial.println("hourOffset: " + String(hourOffset));
|
|
}
|
|
//Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS)));
|
|
}
|
|
currentSec--;
|
|
}
|
|
}
|