From 1c350146413c776006624caab4870fd6ffcf892a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Fernando=20S=C3=A1nchez?= Date: Tue, 14 Aug 2018 23:52:39 +0200 Subject: [PATCH] First commit --- .gitignore | 2 + README.md | 37 ++++ TFT_Clock_Digital_NTP.ino | 360 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 TFT_Clock_Digital_NTP.ino diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..afbc183 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +passwords.h +.* \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..20ca231 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +ESP8266-based clock that uses NTP to stay in sync, and a DHT11/22 to also display the temperature and humidity. + +WORK IN PROGRESS. + +# Connections + +| ILI9341 SPI TFT | NodeMCU | +|-----------------|---------| +| VCC | 3.3V | +| GND | GND | +| CS | D2 | +| REST | RST | +| DC | D1 | +| SDI/MOSI | D7 | +| SCK | D5 | +| LED | 3.3V | +| SDO/MISO | D6 | + + +| DHT11 | NodeMCU | +|-------|---------| +| VCC | 3.3V | +| Data | D0 | +| GND | GND | + +# Arduino ESP8266 support + +Boards manager link: http://arduino.esp8266.com/stable/package_esp8266com_index.json + +# Libraries + +Some of them are available via the Arduino library manager + +* https://github.com/PaulStoffregen/Time +* https://github.com/JChristensen/Timezone +* https://github.com/Bodmer/TFT_eSPI +* https://github.com/beegee-tokyo/DHTesp diff --git a/TFT_Clock_Digital_NTP.ino b/TFT_Clock_Digital_NTP.ino new file mode 100644 index 0000000..d10f05f --- /dev/null +++ b/TFT_Clock_Digital_NTP.ino @@ -0,0 +1,360 @@ + +/* + ESP8266-based clock that uses NTP to stay in sync, and a DHT11/22 + to also display the temperature and humidity. + +| ILI9341 SPI TFT | NodeMCU | +|-----------------|---------| +| VCC | 3.3V | +| GND | GND | +| CS | D2 | +| REST | RST | +| DC | D1 | +| SDI/MOSI | D7 | +| SCK | D5 | +| LED | 3.3V | +| SDO/MISO | D6 | + + +| DHT11 | NodeMCU | +|-------|---------| +| VCC | 3.3V | +| Data | D0 | +| GND | GND | + + + Based on clock sketch by Gilchrist 6/2/2014 1.0 + +A few colour codes: + +code color +0x0000 Black +0xFFFF White +0xBDF7 Light Gray +0x7BEF Dark Gray +0xF800 Red +0xFFE0 Yellow +0xFBE0 Orange +0x79E0 Brown +0x7E0 Green +0x7FF Cyan +0x1F Blue +0xF81F Pink + + */ +#include + +#include "passwords.h" // Define WIFI_PASS and WIFI_SSID here + +#define DHT11_PIN D0 + +DHTesp dht; + +const int INTERVAL_DHT = 30; + +#include // Hardware-specific library https://github.com/Bodmer/TFT_eSPI +#include + +#include +#include +#include + +#include // https://github.com/JChristensen/Timezone + + +// Time variables + +// Central European Time (Frankfurt, Paris) +TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time +TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Time +Timezone CE(CEST, CET); + +TimeChangeRule *tcr; + + +// Wifi variables + +bool connectionWasAlive = false; + +ESP8266WiFiMulti wifiMulti; // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti' + +WiFiUDP UDP; // Create an instance of the WiFiUDP class to send and receive + +IPAddress timeServerIP; // time.nist.gov NTP server address +const char* NTPServerName = "hora.roa.es"; + +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message + +byte NTPBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets + + +unsigned long intervalNTP = 60000; // Request NTP time every minute +unsigned long prevNTP = 0; +unsigned long lastNTPResponse = millis(); +uint32_t timeUNIX = 0; + + +// TFT variables + +#define TFT_GREY 0x5AEB +#define TFT_DARK_GREY 0x7BEF + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +#define FONT_SIZE 7 + +// Clock variables + +uint8_t hh = 0, mm = 0, ss = 0; + +byte omm = 99, oss = 99; +byte xcolon = 0, xsecs = 0; +unsigned int colour = 0; + +uint32_t targetTime = 0; // for next 1 second timeout + + + +// Other variables + +int counter = 0; + +void updateTime() { + unsigned long currentMillis = millis(); + + if (currentMillis - prevNTP > intervalNTP) { // If a minute has passed since last NTP request + prevNTP = currentMillis; + Serial.println("\r\nSending NTP request ..."); + sendNTPpacket(timeServerIP); // Send an NTP request + } + + uint32_t time = getTime(); // Check if an NTP response has arrived and get the (UNIX) time + if (time) { // If a new timestamp has been received + timeUNIX = time; + Serial.print("NTP response:\t"); + Serial.println(timeUNIX); + lastNTPResponse = currentMillis; + } else if ((currentMillis - lastNTPResponse) > 3600000) { + Serial.println("More than 1 hour since last NTP response. Rebooting."); + Serial.flush(); + ESP.reset(); + } + + + time_t t = CE.toLocal(now(), &tcr); + + mm = minute(t); + ss = second(t); + hh = hour(t); + + if ( ss != oss ) { // If a second has passed since last print + Serial.printf("\rLocal time:\t%d:%d:%d ", hh, omm, oss); + } +} + + +void drawTime(){ + int xpos = 20; + int ypos = 65; // Top left corner ot clock text, about half way down + int ysecs = ypos + 24; + + if (omm != mm) { // Redraw hours and minutes time every minute + omm = mm; + // Draw hours and minutes + if (hh < 10) xpos += tft.drawChar('0', xpos, ypos, FONT_SIZE); // Add hours leading zero for 24 hr clock + xpos += tft.drawNumber(hh, xpos, ypos, FONT_SIZE); // Draw hours + xcolon = xpos; // Save colon coord for later to flash on/off later + xpos += tft.drawChar(':', xpos, ypos - 8, FONT_SIZE); + if (mm < 10) xpos += tft.drawChar('0', xpos, ypos, FONT_SIZE); // Add minutes leading zero + xpos += tft.drawNumber(mm, xpos, ypos, FONT_SIZE); // Draw minutes + xsecs = xpos; // Sae seconds 'x' position for later display updates + } + if (oss != ss) { // Redraw seconds time every second + oss = ss; + xpos = xsecs; + + if (ss % 2) { // Flash the colons on/off + tft.setTextColor(0x39C4, TFT_BLACK); // Set colour to grey to dim colon + tft.drawChar(':', xcolon, ypos - 8, FONT_SIZE); // Hour:minute colon + tft.setTextColor(TFT_YELLOW, TFT_BLACK); // Set colour back to yellow + } + else { + tft.drawChar(':', xcolon, ypos - FONT_SIZE, FONT_SIZE); // Hour:minute colon + } + } +} + + +uint32_t getTime() { + if (UDP.parsePacket() == 0) { // If there's no response (yet) + return 0; + } + UDP.read(NTPBuffer, NTP_PACKET_SIZE); // read the packet into the buffer + // Combine the 4 timestamp bytes into one 32-bit number + uint32_t NTPTime = (NTPBuffer[40] << 24) | (NTPBuffer[41] << 16) | (NTPBuffer[42] << 8) | NTPBuffer[43]; + // Convert NTP time to a UNIX timestamp: + // Unix time starts on Jan 1 1970. That's 2208988800 seconds in NTP time: + const uint32_t seventyYears = 2208988800UL; + // subtract seventy years: + uint32_t UNIXTime = NTPTime - seventyYears; + setTime(UNIXTime); + return UNIXTime; +} + +void sendNTPpacket(IPAddress& address) { + memset(NTPBuffer, 0, NTP_PACKET_SIZE); // set all bytes in the buffer to 0 + // Initialize values needed to form NTP request + NTPBuffer[0] = 0b11100011; // LI, Version, Mode + // send a packet requesting a timestamp: + UDP.beginPacket(address, 123); // NTP requests are to port 123 + UDP.write(NTPBuffer, NTP_PACKET_SIZE); + UDP.endPacket(); +} + +inline int getSeconds(uint32_t UNIXTime) { + return UNIXTime % 60; +} + +inline int getMinutes(uint32_t UNIXTime) { + return UNIXTime / 60 % 60; +} + +inline int getHours(uint32_t UNIXTime) { + return UNIXTime / 3600 % 24; +} + + +void monitorWiFi() { + if (wifiMulti.run() != WL_CONNECTED) + { + if (connectionWasAlive) + { + connectionWasAlive = false; + Serial.print("Looking for WiFi "); + } + Serial.print("."); + } + else if (connectionWasAlive == false) + { + connectionWasAlive = true; + Serial.print("Connected to "); + Serial.println(WiFi.SSID()); // Tell us what network we're connected to + Serial.print("IP address:\t"); + Serial.print(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer + Serial.println("\r\n"); + } +} + +void startWiFi() { // Try to connect to some given access points. Then wait for a connection + wifiMulti.addAP(WIFI_SSID, WIFI_PASS); // add Wi-Fi networks you want to connect to + + while (wifiMulti.run() != WL_CONNECTED) { // Wait for the Wi-Fi to connect + delay(250); + monitorWiFi(); + } + Serial.println("\r\n"); +} + +void startUDP() { + Serial.println("Starting UDP"); + UDP.begin(123); // Start listening for UDP messages on port 123 + Serial.print("Local port:\t"); + Serial.println(UDP.localPort()); + Serial.println(); +} + + +void printTemperature() +{ + + float humidity = dht.getHumidity(); + float temperature = dht.getTemperature(); + + Serial.print(dht.getStatusString()); + Serial.print("\t"); + Serial.print(humidity, 1); + Serial.print("\t\t"); + Serial.print(temperature, 1); + Serial.print("\t\t"); + Serial.print(dht.computeHeatIndex(temperature, humidity, false), 1); + Serial.print("\t\t"); + Serial.println(dht.computeHeatIndex(dht.toFahrenheit(temperature), humidity, true), 1); + + int space = 16; + int pos = 24; + int font = 4; + int posy = 180; + tft.setTextSize(1); + tft.setTextColor(TFT_DARK_GREY, TFT_BLACK); + + pos += tft.drawString("T: ", pos, posy+20, font); + + pos += tft.drawNumber(temperature, pos+space, posy, 7) + 2*space; + + pos += tft.drawString("C", pos, posy, font) + space; + + pos += tft.drawString("H: ", pos, posy+20, font); + + pos += tft.drawNumber(humidity, pos + space, posy, 7); + pos += tft.drawChar('%', pos + space, posy, font); + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.setTextSize(2); + +} + + +void setup(void) { + dht.setup(DHT11_PIN, DHTesp::DHT11); // Connect DHT sensor to GPIO 17 + + tft.init(); + tft.setRotation(1); + tft.fillScreen(TFT_BLACK); + + tft.setTextSize(2); + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + + targetTime = millis() + 1000; + + Serial.begin(115200); // Start the Serial communication to send messages to the computer + delay(10); + Serial.println("\r\n"); + + startWiFi(); // Try to connect to some given access points. Then wait for a connection + + startUDP(); + + if(!WiFi.hostByName(NTPServerName, timeServerIP)) { // Get the IP address of the NTP server + Serial.println("DNS lookup failed. Rebooting."); + Serial.flush(); + ESP.reset(); + } + Serial.print("Time server IP:\t"); + Serial.println(timeServerIP); + + Serial.println("\r\nSending NTP request ..."); + sendNTPpacket(timeServerIP); + +} + + +void loop() { + + if (targetTime < millis()) { + targetTime = millis() + 1000; + + monitorWiFi(); + + if ( (counter % INTERVAL_DHT) == 0){ + counter = 0; + printTemperature(); + } + counter = counter+1; + + updateTime(); + + + // Update digital time + drawTime(); + + } +}