/*True Binary Clock * Written by Vikram Kashyap, 2020 * vikramkashyap.com * * NOTE: settings page is served on 192.168.1.1 */ #include #include #include #include #include #include #include #define SWITCHPIN 12 //D6 #define LED_DATA_PIN 0 //D3 #define SEC_DAY 86400 //# of Seconds in one day #define NUM_LEDS 24 #define SSID_ADDR 0 #define PASS_ADDR 128 #define NTPSERVER_ADDR 256 #define TZOFFSET_ADDR 384 /*AP wifi config*/ const char* SAPssid = "TrueBinary"; const char* SAPpass = "thepowerof2"; /*NTP values*/ char* ntpserver; float tzoffset; /*Time and Wifi global vars*/ ESP8266WebServer server(80); WiFiUDP ntpUDP; NTPClient* timeClient; IPAddress local_ip(192,168,1,1); IPAddress gateway(192,168,1,1); IPAddress subnet(255,255,255,0); /*LED global array*/ CRGB leds[NUM_LEDS]; /*Turn an led on in the array by display index*/ void setDisplay(int index) { //REPLACE WITH DETAILS FOR YOUR OWN DISPLAY /* if (index <= 3) { leds[index*2].setRGB(100, 0, 0); } else if (index <= 7) { leds[22-index*2].setRGB(0, 100, 0); } else { leds[index*2].setRGB(0, 0, 100); }*/ } /*Set led array to all black*/ void clearDisplay() { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CRGB::Black; } } /*Write C-string to EEPROM*/ void writeEEPROMString(int addr, String s) { for (char c : s) { EEPROM.write(addr, c); addr++; } EEPROM.write(addr, '\0'); } /*Read C-string from EEPROM*/ char* readEEPROMString(int addr) { char* str = new char[64]; char* strstart = str; while ((*(str++)=EEPROM.read(addr++)) != '\0') {} return strstart; } /*Serve Wifi/Time settings input page*/ void handleRoot() { const char page[] = R"=====(

True Binary Clock Config

Enter your wifi network information here

Wifi SSID:


Wifi Password:


NTP Server:


Timezone offset from UTC in hours (e.g. 1.5 or -10):




)====="; //Send input page server.send(200, "text/html", page); } /*Save wifi/time settings from settings page*/ void handleInput() { String wifissid = server.arg("ssid"); String wifipass = server.arg("pass"); String ntpserver = server.arg("ntpserver"); tzoffset = server.arg("tzoffset").toFloat(); //Save to EEPROM EEPROM.begin(512); writeEEPROMString(SSID_ADDR, wifissid); writeEEPROMString(PASS_ADDR, wifipass); writeEEPROMString(NTPSERVER_ADDR, ntpserver); EEPROM.put(TZOFFSET_ADDR, tzoffset); EEPROM.commit(); server.send(200, "text/html", "Submitted. Return?"); } void setup() { pinMode(SWITCHPIN, INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); /* WiFi.disconnect(); WiFi.softAPdisconnect(true); */ //Start serial comm Serial.begin(9600); delay(1000); Serial.println("Starting up"); //Setup LEDs FastLED.addLeds(leds, NUM_LEDS); //Turn off all LEDS clearDisplay(); FastLED.show(); //Enter Settings Mode if switch on if (digitalRead(SWITCHPIN) == HIGH) { Serial.println("Entering Settings Mode"); WiFi.mode(WIFI_AP); WiFi.softAPConfig(local_ip, gateway, subnet); WiFi.softAP(SAPssid, SAPpass); server.on("/", handleRoot); server.on("/settingsinput", handleInput); server.begin(); Serial.println("Server started"); Serial.println(WiFi.softAPIP()); //Keep serving till reset while (true) { server.handleClient(); } } //Enter Clock Mode Serial.println("Entering Clock Mode"); //Get Wifi settings from storage Serial.println("Reading Wifi settings from EEPROM:"); EEPROM.begin(512); char* wifissid = readEEPROMString(SSID_ADDR); char* wifipass = readEEPROMString(PASS_ADDR); ntpserver = readEEPROMString(NTPSERVER_ADDR); EEPROM.get(TZOFFSET_ADDR, tzoffset); Serial.println("Values read from EEPROM-----------"); Serial.println(wifissid); Serial.println(wifipass); Serial.println(ntpserver); Serial.println(tzoffset); Serial.println("----------------------------------"); //Try to connect to wifi /* WiFi.mode(WIFI_OFF); delay(1000); */ WiFi.mode(WIFI_STA); if (WiFi.getMode() == WIFI_STA) { Serial.println("Mode: WIFI_STA"); } else { Serial.println("Mode switch failed"); } Serial.print("Connecting"); WiFi.begin(wifissid, wifipass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } //print a new line, then print WiFi connected and the IP address Serial.println(""); Serial.println("WiFi connected"); digitalWrite(LED_BUILTIN, HIGH); //Indicate connection // Print the IP address Serial.println(WiFi.localIP()); //Connect to NTP timeClient = new NTPClient(ntpUDP, ntpserver, (long)tzoffset*3600, 3600000); //Update with NTP every hour timeClient->begin(); } void loop() { //Call update on clock (only sends NTP request if update time has elapsed) timeClient->update(); Serial.print(timeClient->getFormattedTime() + " "); clearDisplay(); long secs = timeClient->getHours()*3600+timeClient->getMinutes()*60+timeClient->getSeconds(); //How many seconds elapsed today long dayportion = 86400; //Current binary portion of day being evaluated in seconds (starts at full day) for (int p = 0; p < 12; p++) { dayportion /= 2; //Half the reference binary portion if (secs > dayportion) { //Compare to reference binary day portion //Digit 1 setDisplay(p); Serial.print("1"); secs-=dayportion; } else { //Digit 0 Serial.print("0"); } } Serial.println(); //Show LEDS FastLED.show(); //Wait a 20 seconds (smallest binary timekeeping incremement is 1day/2^12 = ~21 seconds) delay(20000); }