I am making a project with a big led matrix that will show time and current weekday, I have a problem with drawing dots between the hours and minutes, each second when dots update matrix just goes black for a bit then turns back on. It's a really small detail and everyone I showed my matrix to said that they didn't notice anything wrong but it's really annoying for me to look at.
#include <FastLED.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <WiFi.h>
#include <time.h>
#include "esp_system.h"
#include "drawings.h"
#define CurrentWeekDayXs 1
#define CurrentWeekDayYs 1
#define CurrentWeekDayXf 66
#define CurrentWeekDayYf 5
#define CurrentNumberXs 10
#define CurrentNumberYs 14
#define ClkAlign 1
#define PirPin 13
#define Width 66
#define Height 21
#define LED_TYPE WS2812B
#define LED_PIN 23
#define NUM_LEDS 1452
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
struct tm timeinfo;
// time things //
const char* ssid = "DNA-WLAN-2G-CB18";
const char* password = "44995489940";
const char* ntpServer = "pool.ntp.org";
const int gmtOffset = 7200;
const int daylight = 3600;
const char* WEEKDAYS[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
int previousWeekday = -1;
int currentWeekday = -1;
int lastDrawnMinutes = -1;
int currentMinutes = 0;
int lastDrawnHours = -1;
int currentHours = 0;
unsigned long lastTimeCheck = 0;
unsigned long timeCheckInterval = 1000;
unsigned long lastPresenceDetected = 0;
unsigned long PresenceDetectionInterval = 20000;
bool SleepMode = false;
int TimeDrawingStartPosX = 1;
int TimeDrawingStartPosY = 7;
bool AreDotsOn = false;
void setup() {
Serial.begin(9600);
delay(1000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
configTime(gmtOffset, daylight, ntpServer);
if (!getLocalTime(&timeinfo)) {
return;
}
pinMode(PirPin, INPUT);
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.clear();
FastLED.setBrightness(20);
currentHours = timeinfo.tm_hour;
currentMinutes = timeinfo.tm_min;
currentWeekday = timeinfo.tm_wday;
previousWeekday = currentWeekday;
DrawWeekday(currentWeekday, 1, 1);
DrawFrame();
delay(1000);
}
void loop() {
if (!SleepMode) {
if (millis() - lastTimeCheck >= timeCheckInterval) {
dots();
if (getLocalTime(&timeinfo)) {
lastTimeCheck = millis();
currentHours = timeinfo.tm_hour;
currentMinutes = timeinfo.tm_min;
if (previousWeekday != currentWeekday) {
currentWeekday = timeinfo.tm_wday;
previousWeekday = currentWeekday;
DrawWeekday(currentWeekday, 1, 1);
}
if (lastDrawnHours != currentHours) {
if (currentHours < 10) {
DrawNumber(0, CalcAlignNumb(47, 1), TimeDrawingStartPosY);
DrawNumber(currentHours, CalcAlignNumb(47, 1) + 11, TimeDrawingStartPosY);
} else {
DrawNumber(currentHours / 10, CalcAlignNumb(47, 1), TimeDrawingStartPosY);
DrawNumber(currentHours % 10, CalcAlignNumb(47, 1) + 11, TimeDrawingStartPosY);
}
lastDrawnHours = currentHours;
}
if (lastDrawnMinutes != currentMinutes) {
if (currentMinutes < 10) {
DrawNumber(0, CalcAlignNumb(47, 1) + 27, TimeDrawingStartPosY);
DrawNumber(currentMinutes, CalcAlignNumb(47, 1) + 39, TimeDrawingStartPosY);
} else {
DrawNumber(currentMinutes / 10, CalcAlignNumb(47, 1) + 27, TimeDrawingStartPosY);
DrawNumber(currentMinutes % 10, CalcAlignNumb(47, 1) + 39, TimeDrawingStartPosY);
}
lastDrawnMinutes = currentMinutes;
}
}
}
if (millis() - lastPresenceDetected >= PresenceDetectionInterval) {
WiFi.disconnect();
SleepMode = true;
CleanScreenCord(0, 0, Width, Height + 1);
for (int i = 23; i > -14; i--) {
delay(20);
CleanScreenCord(0, 0, Width, Height + 1);
DrawDrawing(GoingDrawing, CalcAlign(GoingDrawing, 1), i);
}
for (int i = 23; i > -14; i--) {
delay(20);
CleanScreenCord(0, 0, Width, Height + 1);
DrawDrawing(ToDrawing, CalcAlign(ToDrawing, 1), i);
}
DrawSleepDrawing();
}
}
if (digitalRead(PirPin) == 1) {
lastPresenceDetected = millis();
if (SleepMode) {
previousWeekday = -1;
lastDrawnHours = -1;
lastDrawnMinutes = -1;
SleepMode = false;
reconnectWiFi();
DrawFrame();
}
}
delay(10);
}
void dots() {
AreDotsOn = !AreDotsOn;
if (!AreDotsOn) {
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 3)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 3)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 4)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 4)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 8)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 8)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 9)] = CRGB::Purple;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 9)] = CRGB::Purple;
FastLED.show();
} else {
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 3)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 3)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 4)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 4)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 8)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 8)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 23, TimeDrawingStartPosY + 9)] = CRGB::Black;
leds[getLedIndex(CalcAlignNumb(47, 1) + 24, TimeDrawingStartPosY + 9)] = CRGB::Black;
FastLED.show();
}
};
int getLedIndex(int x, int y) {
if (y % 2 == 1) {
return y * Width + x;
} else {
return y * Width + (Width - 1 - x);
}
}
void DrawDrawing(const Drawing& drw, int8_t DrwX, int8_t DrwY) {
int arrayIndex = 0;
for (int8_t x = 0; x < drw.width; x++) {
for (int8_t y = 0; y < drw.height; y++) {
int8_t pixel = drw.drawing[arrayIndex];
if (pixel) {
int16_t matrixX = DrwX + x;
int16_t matrixY = DrwY + y;
if (matrixX < Width && matrixY < Height && matrixX >= 0 && matrixY >= 0) {
leds[getLedIndex(matrixX, matrixY)] = drw.color;
}
}
arrayIndex++;
}
}
FastLED.show();
}
void DrawWeekday(int theWeekDay, uint8_t WeekDayY, uint8_t Align) {
CleanScreenCord(CurrentWeekDayXs, CurrentWeekDayYs, CurrentWeekDayXf, CurrentWeekDayYf);
switch (theWeekDay) {
case 0:
DrawDrawing(SundayDrawing, CalcAlign(SundayDrawing, Align), WeekDayY);
break;
case 1:
DrawDrawing(MondayDrawing, CalcAlign(MondayDrawing, Align), WeekDayY);
break;
case 2:
DrawDrawing(TuesdayDrawing, CalcAlign(TuesdayDrawing, Align), WeekDayY);
break;
case 3:
DrawDrawing(WednesdayDrawing, CalcAlign(WednesdayDrawing, Align), WeekDayY);
break;
case 4:
DrawDrawing(ThursdayDrawing, CalcAlign(ThursdayDrawing, Align), WeekDayY);
break;
case 5:
DrawDrawing(FridayDrawing, CalcAlign(FridayDrawing, Align), WeekDayY);
break;
case 6:
DrawDrawing(SaturdayDrawing, CalcAlign(SaturdayDrawing, Align), WeekDayY);
break;
}
}
void DrawNumber(uint8_t TheNumber, uint8_t NumberX, uint8_t NumberY) {
CleanScreenCord(NumberX, NumberY, NumberX + CurrentNumberXs + 1, NumberY + CurrentNumberYs);
switch (TheNumber) {
case 0:
DrawDrawing(ZeroDrawing, NumberX, NumberY);
break;
case 1:
DrawDrawing(OneDrawing, NumberX, NumberY);
break;
case 2:
DrawDrawing(TwoDrawing, NumberX, NumberY);
break;
case 3:
DrawDrawing(ThreeDrawing, NumberX, NumberY);
break;
case 4:
DrawDrawing(FourDrawing, NumberX, NumberY);
break;
case 5:
DrawDrawing(FiveDrawing, NumberX, NumberY);
break;
case 6:
DrawDrawing(SixDrawing, NumberX, NumberY);
break;
case 7:
DrawDrawing(SevenDrawing, NumberX, NumberY);
break;
case 8:
DrawDrawing(EightDrawing, NumberX, NumberY);
break;
case 9:
DrawDrawing(NineDrawing, NumberX, NumberY);
break;
}
}
uint8_t CalcAlign(const Drawing& drw, uint8_t Align) {
int TheX;
switch (Align) {
case 0:
TheX = 0;
return TheX;
break;
case 1:
TheX = (Width - drw.width) / 2;
return TheX;
break;
case 2:
TheX = Width - drw.width;
return TheX;
break;
}
}
uint8_t CalcAlignNumb(uint8_t Numb, uint8_t Align) {
int TheX;
switch (Align) {
case 0:
TheX = 0;
return TheX;
break;
case 1:
TheX = (Width - Numb) / 2;
return TheX;
break;
case 2:
TheX = Width - Numb;
return TheX;
break;
}
}
void CleanScreenCord(uint8_t Xs, uint8_t Ys, uint8_t Xf, uint8_t Yf) {
for (int y = Ys; y < Yf; y++) {
for (int x = Xs; x < Xf; x++) {
leds[getLedIndex(x, y)] = CRGB::Black;
}
}
}
void DrawFrame() {
for (int y = 0; y < 22; y++) {
leds[getLedIndex(65, y)] = CRGB::DarkBlue;
leds[getLedIndex(65, y)].nscale8(30);
};
for (int y = 21; y >= 0; y--) {
leds[getLedIndex(0, y)] = CRGB::DarkBlue;
leds[getLedIndex(0, y)].nscale8(30);
};
for (int x = 0; x < Width; x++) {
leds[getLedIndex(x, 0)] = CRGB::DarkBlue;
leds[getLedIndex(x, 0)].nscale8(30);
}
for (int x = 0; x < Width; x++) {
leds[getLedIndex(x, Height)] = CRGB::DarkBlue;
leds[getLedIndex(x, Height)].nscale8(30);
}
FastLED.show();
}
void GradientXY(uint8_t x, uint8_t y, bool isVertical, uint8_t dir, uint8_t length, CRGB ColorA, CRGB ColorB) {
if (length == 0) return;
if (!isVertical) {
if (dir == 0) {
for (int i = 0; i < length; i++) {
int xi = x + i;
if (xi >= 0 && xi < Width && y >= 0 && y < Height) {
leds[getLedIndex(xi, y)] = blend(ColorA, ColorB, (uint8_t)((i * 255) / (length - 1)));
}
}
} else if (dir == 1) {
for (int i = 0; i < length; i++) {
int xi = x - i;
if (xi >= 0 && xi < Width && y >= 0 && y < Height) {
leds[getLedIndex(xi, y)] = blend(ColorA, ColorB, (uint8_t)((i * 255) / (length - 1)));
}
}
}
} else {
if (dir == 0) {
for (int i = 0; i < length; i++) {
int yi = y + i;
if (x >= 0 && x < Width && yi >= 0 && yi < Height) {
leds[getLedIndex(x, yi)] = blend(ColorA, ColorB, (uint8_t)((i * 255) / (length - 1)));
}
}
} else if (dir == 1) {
for (int i = 0; i < length; i++) {
int yi = y - i;
if (x >= 0 && x < Width && yi >= 0 && yi < Height) {
leds[getLedIndex(x, yi)] = blend(ColorA, ColorB, (uint8_t)((i * 255) / (length - 1)));
}
}
}
}
}
void DrawSleepDrawing() {
for (int i = 37; i > 0; i--) {
uint8_t scale = constrain(i * 20, 50, 255);
CleanScreenCord(0, 0, Width, Height);
int drawX = CalcAlign(SleepDrawing, 1);
int drawY = i - 14;
int arrayIndex = 0;
for (int8_t x = 0; x < SleepDrawing.width; x++) {
for (int8_t y = 0; y < SleepDrawing.height; y++) {
int8_t pixel = SleepDrawing.drawing[arrayIndex++];
if (!pixel) continue;
int16_t matrixX = drawX + x;
int16_t matrixY = drawY + y;
if (matrixX >= 0 && matrixX < Width && matrixY >= 0 && matrixY < Height) {
int ledIndex = getLedIndex(matrixX, matrixY);
if (ledIndex >= 0 && ledIndex < NUM_LEDS) {
leds[ledIndex] = blend(SleepDrawing.color, CRGB::Black, 255-scale);
}
}
}
}
FastLED.show();
delay(20);
}
FastLED.clear();
FastLED.show();
}
void reconnectWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
Separate drawings file just contains arrays with the drawings and noting else that matters to the problem.
Also if someone notices any flaws in any other parts of my code feel free to tell me about them.
I use esp32 220 ohm resistor for data line and 1000uf capacitor for power