I had a Neopixel clock using a Nano with a RTC DS3231 and a OLED display. After about 6 months the time was off by a few minutes. I decided to change to a ESP32 Dev Module and read the time from a NTP server.
I am able to read the NTP server and display the date and time on the OLED display, I am having troubles with getting the Neopixel ring to work. The problem is I am not sure what format the NTP time variables are and I need to convert them to an integer for the pixels.
This is the line that reads the time for the OLED, “Serial.println(&timeinfo, "%A, %B %d %Y %I:%M:%S");”
In this block of code in the “void printLocalTime()” function
unsigned char hourPos = ((now.hour() % 12) * 5 + (now.minute() + 6) / 12);
Ring.setPixelColor((hourPos + 59) % 60, Ring.Color(255, 0, 0));
Ring.setPixelColor(((hourPos) % 60), Ring.Color(255, 0, 0));
Ring.setPixelColor(((hourPos + 1) % 60), Ring.Color(255, 0, 0));
Ring.setPixelColor(((now.minute()) % 60) % 60, Ring.Color(0, 255, 0));
Ring.setPixelColor(((now.second()) % 60) % 60, Ring.Color(0, 0, 255));
I need to replace now.hours with %I, now.minute with %M and now.second with %S. the now tags were what I used from the RTC, it doesn’t matter what tags I use here Hrs, Min and Sec will be fine.
I’ve tried a couple of ways to convert it but obviously none are working for me.
Thanks for your help, here is the full sketch.
/* New Neo-pixal clock wuth ESP32
using NTP server time
*/
#include <WiFi.h>
#include "time.h"
#include "esp_sntp.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_NeoPixel.h>
// Reset pin not used but needed for library
#define OLED_RESET -1
//Adafruit_SSD1306 display(OLED_RESET);
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LEDStripPin 4 // Pin used for the data to the LED strip
#define menuPin 0 // Pin used for the menu button (green stripe)
#define numLEDs 60 // Number of LEDs in strip
Adafruit_NeoPixel Ring = Adafruit_NeoPixel(numLEDs, LEDStripPin, NEO_GRB + NEO_KHZ800);
const char *ssid = "My_SSID";
const char *password = "My_Password";
const char *ntpServer1 = "pool.ntp.org";
const char *ntpServer2 = "time.nist.gov";
const long gmtOffset_sec = 18000; // 5 hours
const int daylightOffset_sec = 3600;
const char *time_zone = "CET-1CEST,M3.5.0,M10.5.0/3"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional)
void printLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("No time available (yet)");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %I:%M:%S");
// clear LED array
Ring.clear(); // Set all pixel colors to 'off'
unsigned char hourPos = ((now.hour() % 12) * 5 + (now.minute() + 6) / 12);
Ring.setPixelColor((hourPos + 59) % 60, Ring.Color(255, 0, 0));
Ring.setPixelColor(((hourPos) % 60), Ring.Color(255, 0, 0));
Ring.setPixelColor(((hourPos + 1) % 60), Ring.Color(255, 0, 0));
Ring.setPixelColor(((now.minute()) % 60) % 60, Ring.Color(0, 255, 0));
Ring.setPixelColor(((now.second()) % 60) % 60, Ring.Color(0, 0, 255));
Ring.show(); // Send the updated pixel colors to the hardware.
// Clear the display
display.clearDisplay();
//Set the color - always use white despite actual display color
display.setTextColor(WHITE);
//Set the font size
display.setTextSize(2);
//Set the cursor coordinates
display.setCursor(0, 10);
// display.print("Time");
display.setCursor(20, 15);
display.print(&timeinfo, "%I:%M:%S");
// display date
display.setCursor(7, 45);
display.print(&timeinfo, "%b/%d/%y");
display.display(); // Update screen
}
// Callback function (gets called when time adjusts via NTP)
void timeavailable(struct timeval *t) {
Serial.println("Got time adjustment from NTP!");
printLocalTime();
}
void setup() {
Serial.begin(115200);
// First step is to configure WiFi STA and connect in order to get the current time and date.
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
Wire.begin(); // Starts the Wire library allows I2C communication
esp_sntp_servermode_dhcp(1); // (optional)
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
// set notification call-back function
sntp_set_time_sync_notification_cb(timeavailable);
/**
* This will set configured ntp servers and constant TimeZone/daylightOffset
* should be OK if your time zone does not need to adjust daylightOffset twice a year,
* in such a case time adjustment won't be handled automagically.
*/
configTime(-gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
// initialize OLED with I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// Start LEDs
Ring.begin();
Ring.setBrightness(15);
Ring.show(); // Initialize all pixels to 'off'
} //end setup
void loop() {
delay(1000);
printLocalTime(); // it will take some time to sync time :)
} //end loop