Run ESP_UniClock on the NixieIN12v2 clock
Adds CLOCK_90 and the nixie595.ino driver: two 74HC595s on hardware SPI (GPIO13/14, latch GPIO15), multiplexed from an IRAM-only timer1 ISR. Neon dots on P1; P2 is the decimal-point line on this board. Also: - NeoPixel on any ESP8266 pin via bit-bang (GPIO12), and take the pin back after SPI.begin() claimed it as MISO - ArduinoOTA (USE_ARDUINO_OTA), with an OTA upload env in platformio.ini - DST: EU end date (last Sunday of October) instead of the first Sunday of November, and recompute the time from the rules when DST is toggled instead of shifting it by 1 h - forward declarations so PlatformIO's .ino conversion compiles - FIRMWARE_SERVER can be overridden; empty for CLOCK_90 Verified on the clock: tubes, order, dots, LEDs, LDR, NTP time with DST. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b347f1c63f
commit
0d3e878051
7 files changed
+304
-34
No files matched your search
@@ -44,6 +44,11 @@
|
||||
#include <stddef.h>
|
||||
//#define byte uint8_t
|
||||
#include "clocks.h" //DEFINE YOUR CLOCKS SETUP IN THIS FILE!!! - clocks.h picks the single active CLOCK_NN block, which #defines the driver macro, pins and feature flags read throughout this file
|
||||
// PlatformIO turns the .ino files into one .cpp and puts prototypes for every function near the top,
|
||||
// without evaluating #ifdefs. Declare the types of optional libraries here so those prototypes compile
|
||||
// when the feature (and its #include) is switched off.
|
||||
class AsyncWiFiManager;
|
||||
struct RgbColor;
|
||||
|
||||
// Detect which generation of the ESP8266 Arduino core is in use: older cores (2.6.x/2.7.x) name the
|
||||
// RAM-resident-ISR attribute ICACHE_RAM_ATTR, while newer cores renamed it to IRAM_ATTR (shared with
|
||||
@@ -161,7 +166,9 @@ unsigned long intCounter = 0; //for testing only, interrupt counter
|
||||
byte c_MinBrightness = RGB_MIN_BRIGHTNESS; //minimum LED brightness
|
||||
byte c_MaxBrightness = RGB_MAX_BRIGHTNESS; //maximum LED brightness
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
#define FIRMWARE_SERVER "http://c.landventure.hu/store" //default OTA update server (see doFirmwareUpdate()); overridable per-clock via prm.firmwareServer / the web admin "firmware" field
|
||||
#ifndef FIRMWARE_SERVER
|
||||
#define FIRMWARE_SERVER "http://c.landventure.hu/store" //default OTA update server (see doFirmwareUpdate()); overridable per-clock via prm.firmwareServer / the web admin "firmware" field
|
||||
#endif
|
||||
String usedPinsStr; //human-readable list of registered GPIOs, built by listPins(), shown on the web admin "clock details" page
|
||||
String driverSetupStr; //driver-specific extra setup info string (set by some drivers), also shown on the web admin page
|
||||
|
||||
@@ -237,6 +244,9 @@ DNSServer dnsServer;
|
||||
#include <Wire.h>
|
||||
#include <EEPROM.h>
|
||||
#include "ArduinoJson.h"
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_NEOPIXEL) || defined(WORDCLOCK)
|
||||
#include <NeoPixelBrightnessBus.h>
|
||||
@@ -441,8 +451,10 @@ IPAddress ip;
|
||||
// switchover DATES are not configurable from the web UI. myTZ is rebuilt with the current offsets
|
||||
// every time updateTimefromTimeserver() runs (WiFi/NTP path only - the GPS-only fallback in gps.ino
|
||||
// uses a simpler, always-on +1h DST rule, see CODE_REVIEW.md).
|
||||
// NOTE: upstream ended DST on the first Sunday of November (the US date). The EU switches at 01:00 UTC:
|
||||
// last Sunday of March 02:00 standard time, last Sunday of October 03:00 summer time.
|
||||
TimeChangeRule myDST = {"DST", Last, Sun, Mar, 2, 0};
|
||||
TimeChangeRule mySTD = {"STD", First, Sun, Nov, 2, 0};
|
||||
TimeChangeRule mySTD = {"STD", Last, Sun, Oct, 3, 0};
|
||||
Timezone myTZ(myDST, mySTD);
|
||||
time_t prevTime = 0; //last second() value that was actually rendered to the display - timeProgram() only redraws when now()!=prevTime, i.e. at most once per real second
|
||||
time_t protectTimer = 0; //timestamp of the last cathode-protect animation, used by timeProgram()'s prm.interval-minute scheduler
|
||||
@@ -589,6 +601,9 @@ void Fdelay(unsigned long d) {
|
||||
#ifdef USE_GPS
|
||||
smartDelay(1); //feed GPS
|
||||
#endif
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
ArduinoOTA.handle(); //also during long animations/startup waits
|
||||
#endif
|
||||
yield();
|
||||
}
|
||||
}
|
||||
@@ -877,6 +892,39 @@ void startMDNS() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Optional ArduinoOTA (USE_ARDUINO_OTA in clocks.h): push a new firmware from PlatformIO/Arduino IDE
|
||||
// over WiFi ("pio run -t upload --upload-port <ip>"). Shows the progress in percent on the two right
|
||||
// tubes. Password from OTA_PASSWORD (secrets.h) if defined.
|
||||
void startArduinoOTA() {
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
static boolean otaStarted = false;
|
||||
if (otaStarted) return;
|
||||
ArduinoOTA.setHostname(OTA_HOSTNAME);
|
||||
#ifdef OTA_PASSWORD
|
||||
ArduinoOTA.setPassword(OTA_PASSWORD);
|
||||
#endif
|
||||
ArduinoOTA.onStart([]() {
|
||||
DPRINTLN(F("ArduinoOTA: update started"));
|
||||
clearDigits();
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
int p = (int)(progress / (total / 100 + 1));
|
||||
digit[1] = (p / 10) % 10;
|
||||
digit[0] = p % 10;
|
||||
});
|
||||
ArduinoOTA.onEnd([]() {
|
||||
DPRINTLN(F("ArduinoOTA: done, rebooting"));
|
||||
});
|
||||
ArduinoOTA.onError([](ota_error_t error) {
|
||||
DPRINTF("ArduinoOTA: error %u\n", error);
|
||||
clearDigits();
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
otaStarted = true;
|
||||
DPRINT(F("ArduinoOTA ready: ")); DPRINTLN(OTA_HOSTNAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
// The Standalone(AP)-mode path (prm.wifiMode==false, or a fallback from a fully-failed STA connect):
|
||||
// the clock hosts its own WiFi hotspot at the fixed address 192.168.4.1 (prm.ApSsid/prm.ApPsw) and
|
||||
// runs a DNS server that answers every query with its own IP (dnsServer.start(53,"*",...)) so most
|
||||
@@ -1242,6 +1290,9 @@ void handleConfigChanged(AsyncWebServerRequest *request) {
|
||||
if (old_utc_offset != prm.utc_offset) { //Change time zone
|
||||
setTime(now()+(prm.utc_offset-old_utc_offset)*3600);
|
||||
updateRTC();
|
||||
mySTD.offset = prm.utc_offset * 60; //keep myTZ current for a later enableDST change
|
||||
myDST.offset = mySTD.offset + (prm.enableDST ? 60 : 0);
|
||||
myTZ = Timezone(myDST, mySTD);
|
||||
}
|
||||
}
|
||||
else if (key == "set12_24") {
|
||||
@@ -1262,13 +1313,15 @@ void handleConfigChanged(AsyncWebServerRequest *request) {
|
||||
// running clock by +-1h right away and re-syncs the RTC, instead of only taking effect on the
|
||||
// next scheduled NTP refresh (myTZ itself is rebuilt from prm.enableDST inside
|
||||
// updateTimefromTimeserver() on that next refresh).
|
||||
// FIXED: this used to shift the clock by a blind +-1h, which is wrong outside the summer period
|
||||
// (switching DST on in winter put the clock 1h ahead until the next NTP sync). Now the local
|
||||
// time is converted back to UTC with the old rules and forward with the new ones.
|
||||
prm.enableDST = (value == "true");
|
||||
if (oldDST && !prm.enableDST) { //Switching off DST
|
||||
setTime(now()-3600);
|
||||
updateRTC();
|
||||
}
|
||||
if (!oldDST && prm.enableDST) { //Switching on DST
|
||||
setTime(now()+3600);
|
||||
if (oldDST != prm.enableDST) {
|
||||
time_t utc = myTZ.toUTC(now());
|
||||
myDST.offset = mySTD.offset + (prm.enableDST ? 60 : 0);
|
||||
myTZ = Timezone(myDST, mySTD);
|
||||
setTime(myTZ.toLocal(utc));
|
||||
updateRTC();
|
||||
}
|
||||
}
|
||||
@@ -1889,10 +1942,11 @@ void setup() {
|
||||
|
||||
startMDNS();
|
||||
startServer();
|
||||
startArduinoOTA();
|
||||
#ifdef USE_MQTT
|
||||
setupMqtt();
|
||||
#endif
|
||||
|
||||
|
||||
showMyIp();
|
||||
Fdelay(500);
|
||||
clearDigits();
|
||||
@@ -3221,6 +3275,9 @@ void loop(void) {
|
||||
}
|
||||
}
|
||||
editor();
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
ArduinoOTA.handle();
|
||||
#endif
|
||||
if (makeFirmwareUpdate) {
|
||||
makeFirmwareUpdate = false;
|
||||
doFirmwareUpdate();
|
||||
|
||||
Reference in new issue
Block a user