Explorar el Código

Create WIFI_NTP_CLOCK.ino

Lixie Labs hace 6 años
padre
commit
2f6f387852
Se han modificado 1 ficheros con 410 adiciones y 0 borrados
  1. 410 0
      examples/ESP8266_ONLY/WIFI_NTP_CLOCK/WIFI_NTP_CLOCK.ino

+ 410 - 0
examples/ESP8266_ONLY/WIFI_NTP_CLOCK/WIFI_NTP_CLOCK.ino

@@ -0,0 +1,410 @@
+#include <Lixie_II.h>            // https://github.com/connornishijima/Lixie_II
+
+#include <ESP8266WiFi.h>         // https://github.com/esp8266/Arduino
+#include <DNSServer.h>           //  |
+#include <ESP8266WebServer.h>    //  |
+#include <WiFiUdp.h>             //  |
+#include <FS.h>                  // <
+
+#include <WiFiManager.h>         // https://github.com/tzapu/WiFiManager
+#include <NTPClient.h>           // https://github.com/arduino-libraries/NTPClient
+#include <ArduinoJson.h>         // https://github.com/bblanchon/ArduinoJson
+
+/*
+ * Lixie II NTP Clock Example for ESP8266
+ * by Connor Nishijima (November 2nd, 2019)
+ * 
+ * This example relies on an ESP8266/ESP32 controller,
+ * which is used to pull UTC time from an NTP server over WiFi.
+ * 
+ * It requires two external buttons to fully function: (defined as HUE_BUTTON and HOUR_BUTTON below)
+ * one for changing color/modes, and one for setting the UTC offset (timezone)
+ * 
+ * Upon booting, it will failt to connect to WiFi as it doesn't yet know your
+ * credentials. It will then host it's own WiFi access point named "LIXIE CONFIG"
+ * that you can connect your phone to.
+ * 
+ * Once connected, go to http://192.168.4.1 in your phone's browser, and you
+ * will see a menu that will let you send the WiFi details down to the clock,
+ * to be remembered from this point forward. (Even through power cycles!)
+ * 
+ * A short tap of the HUE button will change color modes, and holding it down will
+ * start to cycle the displays through the color wheel. Release the HUE button
+ * when it gets to a color you like.
+ * 
+ * A short tap of the HOUR button will increase the UTC offset by 1, (wrapping back
+ * to -12 after +12) and a long tap toggles between 12 and 24-hour mode.
+ * 
+ * Holding the HOUR button down during power up will let you access the WiFi 
+ * configuration page again.
+ * 
+ * MAKE SURE SPIFFS IS ENABLED in Tools > Flash Size
+ * 
+ * Enjoy!
+ */
+
+// USER SETTINGS //////////////////////////////////////////////////////////////////
+#define DATA_PIN        D7      // Lixie DIN connects to this pin
+#define NUM_DIGITS      4
+
+#define SIX_DIGIT_CLOCK false   // 6 or 4-digit clock? (6 has seconds shown)
+
+#define HOUR_BUTTON       D1      // These are pulled up internally, and should be
+#define HUE_BUTTON      D3      // tied to GND through momentary switches
+///////////////////////////////////////////////////////////////////////////////////
+
+Lixie_II lix(DATA_PIN, NUM_DIGITS);
+WiFiUDP ntp_UDP;
+NTPClient time_client(ntp_UDP, "pool.ntp.org", 3600, 60000);
+#define SECONDS_PER_HOUR 3600
+int16_t time_zone_shift = 0;
+uint8_t hour_12_mode = false;
+bool time_found = false;
+
+uint32_t settings_last_update = 0;
+bool settings_changed = false;
+const char* settings_file = "/settings.json";
+
+uint32_t t_now = 0;
+uint8_t last_seconds = 0;
+
+#define STABLE 0
+#define RISE   1
+#define FALL   2
+bool hour_button_state   = HIGH;
+bool hue_button_state  = HIGH;
+bool hour_button_state_last   = HIGH;
+bool hue_button_state_last = HIGH;
+uint8_t hour_button_edge   = STABLE;
+uint8_t hue_button_edge = STABLE;
+uint32_t hour_button_last_hit = 0;
+uint32_t hue_button_last_hit = 0;
+uint32_t hour_button_start = 0;
+uint16_t hour_button_wait = 1000;
+bool hour_mode_started = false;
+uint32_t hue_button_start = 0;
+uint8_t button_debounce_ms = 100;
+
+uint8_t base_hue = 0;
+uint16_t hue_countdown = 255;
+uint16_t hue_push_wait = 500;
+
+uint8_t current_mode = 0;
+
+#define NUM_MODES 7
+
+#define MODE_SOLID          0
+#define MODE_GRADIENT       1
+#define MODE_DUAL           2
+#define MODE_NIXIE          3
+#define MODE_INCANDESCENT   4
+#define MODE_VFD            5
+#define MODE_WHITE          6
+
+void setup() {
+  Serial.begin(115200);
+  init_fs();
+  load_settings();
+
+  init_displays();
+  init_buttons();
+  init_wifi();
+  init_ntp();
+}
+
+void loop() {
+  run_clock();
+  yield();
+}
+
+void run_clock() {
+  t_now = millis();
+  time_client.update();
+
+  if (time_client.getSeconds() != last_seconds) {
+    show_time();
+  }
+
+  if (t_now % 20 == 0) { // 50 FPS
+    color_for_mode();
+    check_buttons();
+
+    lix.run();
+  }
+
+  if (t_now - settings_last_update > 5000 && settings_changed == true) {
+    settings_changed = false;
+    save_settings();
+  }
+}
+
+void save_settings() {
+  StaticJsonBuffer<200> jsonBuffer;
+  JsonObject& root = jsonBuffer.createObject();
+
+  root["base_hue"] = base_hue;
+  root["mode"] = current_mode;
+  root["offset"] = time_zone_shift;
+  root["hour_mode"] = hour_12_mode;
+  
+  String settings;
+  root.printTo(settings);
+  Serial.println(settings);
+
+  File f = SPIFFS.open(settings_file, "w+");
+
+  if (!f) {
+    Serial.println("settings file open failed");
+  }
+  else {
+    //Write data to file
+    f.print(settings);
+    f.close();  //Close file
+  }
+}
+
+void load_settings() {
+  String input = "";
+
+  //Read File data
+  File f = SPIFFS.open(settings_file, "r");
+  if (!f) {
+    Serial.println("settings file open failed");
+  }
+  else {
+    for (uint16_t i = 0; i < f.size(); i++) {
+      input += (char)f.read();
+    }
+    f.close();  //Close file
+  }
+
+  StaticJsonBuffer<200> jsonBuffer;
+  JsonObject& root = jsonBuffer.parseObject(input);
+
+  base_hue = root["base_hue"];
+  current_mode = root["mode"];
+  time_zone_shift = root["offset"];
+  hour_12_mode = root["hour_mode"];
+}
+
+void show_time() {
+  uint8_t hh = time_client.getHours();
+  uint8_t mm = time_client.getMinutes();
+  uint8_t ss = time_client.getSeconds();
+
+  if (hour_12_mode == true) {
+    if (hh > 12) {
+      hh -= 12;
+    }
+    if (hh == 0) {
+      hh = 12;
+    }
+  }
+
+  uint32_t t_lixie = 1000000; // "1000000" is used to get zero-padding on hours digits
+  // This turns a time of 22:34:57 into the integer (1)223457, whose leftmost numeral will not be shown
+  t_lixie += (hh * 10000);
+  t_lixie += (mm * 100);
+  t_lixie += ss;
+
+  if (!SIX_DIGIT_CLOCK) {
+    t_lixie /= 100; // Eliminate second places
+  }
+
+  lix.write(t_lixie);
+  if (!time_found) {
+    time_found = true;
+    lix.fade_in();
+  }
+  Serial.println(t_lixie);
+
+  last_seconds = ss;
+}
+
+void color_for_mode() {
+  uint8_t temp_hue = base_hue + hue_countdown;
+
+  if (current_mode == MODE_SOLID) {
+    lix.color_all(ON, CHSV(temp_hue, 255, 255));
+    lix.color_all(OFF, CRGB(0, 0, 0));
+  }
+  else if (current_mode == MODE_GRADIENT) {
+    lix.gradient_rgb(ON, CHSV(temp_hue, 255, 255), CHSV(temp_hue + 90, 255, 255));
+    lix.color_all(OFF, CRGB(0, 0, 0));
+  }
+  else if (current_mode == MODE_DUAL) {
+    lix.color_all_dual(ON, CHSV(temp_hue, 255, 255), CHSV(temp_hue + 90, 255, 255));
+    lix.color_all(OFF, CRGB(0, 0, 0));
+  }
+  else if (current_mode == MODE_NIXIE) {
+    lix.color_all(ON, CRGB(255, 70, 7));
+    CRGB col_off = CRGB(0, 100, 255);
+    const uint8_t nixie_aura_level = 8;
+
+    col_off.r *= (nixie_aura_level / 255.0);
+    col_off.g *= (nixie_aura_level / 255.0);
+    col_off.b *= (nixie_aura_level / 255.0);
+
+    lix.color_all(OFF, col_off);
+  }
+  else if (current_mode == MODE_INCANDESCENT) {
+    lix.color_all(ON, CRGB(255, 100, 25));
+    lix.color_all(OFF, CRGB(0, 0, 0));
+  }
+  else if (current_mode == MODE_VFD) {
+    lix.color_all(ON, CRGB(100, 255, 100));
+    lix.color_all(OFF, CRGB(0, 0, 0));
+  }
+  else if (current_mode == MODE_WHITE) {
+    lix.color_all(ON, CRGB(255, 255, 255));
+  }
+}
+
+void check_buttons() {
+  hour_button_state   = digitalRead(HOUR_BUTTON);
+  hue_button_state  = digitalRead(HUE_BUTTON);
+
+  if (hour_button_state > hour_button_state_last) {
+    hour_button_edge = RISE;
+  }
+  else if (hour_button_state < hour_button_state_last) {
+    if (t_now - hour_button_last_hit >= button_debounce_ms) {
+      hour_button_last_hit = t_now;
+      hour_button_edge = FALL;
+    }
+  }
+  else {
+    hour_button_edge = STABLE;
+  }
+
+  if (hue_button_state > hue_button_state_last) {
+    hue_button_edge = RISE;
+  }
+  else if (hue_button_state < hue_button_state_last) {
+    if (t_now - hue_button_last_hit >= button_debounce_ms) {
+      hue_button_last_hit = t_now;
+      hue_button_edge = FALL;
+    }
+  }
+  else {
+    hue_button_edge = STABLE;
+  }
+
+  parse_buttons();
+
+  hour_button_state_last   = hour_button_state;
+  hue_button_state_last  = hue_button_state;
+}
+
+void parse_buttons() {
+  if (hour_button_edge == FALL) { // PRESS STARTED
+    hour_button_start = t_now;
+  }
+  else if (hour_button_edge == RISE) { // PRESS ENDED
+    uint16_t hour_button_duration = t_now - hour_button_start;
+    if (hour_button_duration < hour_button_wait) { // RELEASED QUICKLY
+      Serial.println("UP");
+      time_zone_shift += 1;
+
+      if(time_zone_shift >= 12){
+        time_zone_shift = -12;
+      }
+      
+      time_client.setTimeOffset(time_zone_shift * SECONDS_PER_HOUR);
+      show_time();
+      update_settings();
+    }
+    else { // RELEASED AFTER LONG PRESS
+      hour_mode_started = false;
+    }
+  }
+
+  if (hue_button_edge == FALL) { // PRESS STARTED
+    Serial.println("HUE");
+    hue_button_start = t_now;
+  }
+  else if (hue_button_edge == RISE) { // PRESS ENDED
+    uint16_t hue_button_duration = t_now - hue_button_start;
+    if (hue_button_duration < hue_push_wait) { // RELEASED QUICKLY
+      Serial.println("NEXT MODE");
+      current_mode++;
+      if (current_mode >= NUM_MODES) {
+        current_mode = 0;
+      }
+      hue_countdown = 127;
+      update_settings();
+    }
+  }
+
+  if (hue_button_state == LOW) { // CURRENTLY PRESSING
+    uint16_t hue_button_duration = t_now - hue_button_start;
+    if (hue_button_duration >= hue_push_wait) {
+      base_hue++;
+      Serial.print("HUE: ");
+      Serial.println(base_hue);
+      update_settings();
+    }
+  }
+
+  if (hour_button_state == LOW) { // CURRENTLY PRESSING
+    uint16_t hour_button_duration = t_now - hour_button_start;
+    if (hour_button_duration >= hour_button_wait && hour_mode_started == false) {
+      hour_mode_started = true;
+      Serial.println("CHANGE HOUR MODE");
+      hour_12_mode = !hour_12_mode;
+      update_settings();
+    }
+  }
+
+  if (hue_countdown < 255) {
+    hue_countdown += 6;
+    if (hue_countdown > 255) {
+      hue_countdown = 255;
+    }
+  }
+}
+
+void update_settings() {
+  settings_changed = true;
+  settings_last_update = t_now;
+}
+
+void init_wifi() {
+  WiFiManager wifiManager;
+  if (digitalRead(HOUR_BUTTON) == LOW) {
+    wifiManager.resetSettings();
+    lix.write(808080);
+    lix.color_all(ON, CRGB(64,0,255));
+  }
+
+  wifiManager.autoConnect("LIXIE CONFIG");
+  lix.sweep_color(CRGB(0, 255, 127), 20, 3, false);
+  lix.clear(); // Removes "8"s before fading in the time
+  color_for_mode();
+}
+
+void init_ntp() {
+  time_client.begin();
+  time_client.setTimeOffset(time_zone_shift * SECONDS_PER_HOUR);
+}
+
+void init_fs() {
+  Serial.print("SPIFFS Initialize....");
+  if (SPIFFS.begin()) {
+    Serial.println("ok");
+  }
+  else {
+    Serial.println("failed");
+  }
+}
+
+void init_buttons() {
+  pinMode(HOUR_BUTTON,   INPUT_PULLUP);
+  pinMode(HUE_BUTTON,  INPUT_PULLUP);
+}
+
+void init_displays() {
+  lix.begin();
+  lix.max_power(5, 1000);
+  lix.write(888888);
+}