Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Berndeutsch layout 11x10 + Sunset feature #51

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ We've got some interesting branches in this repo inspired by user feedback. Thes
- 6 modes (Clock, Digital Clock, SPIRAL animation, TETRIS, SNAKE, PONG)
- time update via NTP server
- automatic summer/wintertime change
- automatic timezone selection
- easy WIFI setup with WifiManager
- configurable color
- configurable night mode (start and end time)
Expand Down
2 changes: 1 addition & 1 deletion data/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ <h1 id="headline">WORDCLOCK 2.0</h1>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-255-0')" class="buttonClass" style="background:rgb(0,255,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=128-255-0')" class="buttonClass" style="background:rgb(128,255,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=200-200-0')" class="buttonClass" style="background:rgb(200,200,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-128-0')" class="buttonClass" style="background:rgb(255,128,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-255-200')" class="buttonClass" style="background:rgb(255,255,200);"></a></span></div>
</div>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion ledmatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ void LEDMatrix::drawOnMatrix(float factor){
// loop over all minute indicator leds
for(int i = 0; i < 4; i++){
uint32_t filteredColor = interpolateColor24bit(currentindicators[i], targetindicators[i], factor);
(*neomatrix).drawPixel(WIDTH - (1+i), HEIGHT, color24to16bit(filteredColor));
(*neomatrix).drawPixel(3-i, HEIGHT, color24to16bit(filteredColor));
//(*neomatrix).drawPixel(WIDTH - (1+i), HEIGHT, color24to16bit(filteredColor));
currentindicators[i] = filteredColor;
totalCurrent += calcEstimatedLEDCurrent(filteredColor);
}
Expand Down
2 changes: 1 addition & 1 deletion ledmatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// width of the led matrix
#define WIDTH 11
// height of the led matrix
#define HEIGHT 11
#define HEIGHT 10

#define DEFAULT_CURRENT_LIMIT 9999

Expand Down
72 changes: 36 additions & 36 deletions multicastUDP_receiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@
import queue

# ip address of network interface
MCAST_IF_IP = '192.168.178.38'
MCAST_IF_IP = '192.168.1.55'

multicast_group = '230.120.10.2'
server_address = ('', 8123)


def start(filters=None):
if filters is None:
filters = []

def start(filter = None):
# Create the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

Expand All @@ -23,51 +19,55 @@ def start(filters=None):

print("Start")

# Tell the operating system to add the socket to the multicast group on the specified interface
# Tell the operating system to add the socket to the multicast group
# on all interfaces.
group = socket.inet_aton(multicast_group)
mreq = struct.pack('4s4s', group, socket.inet_aton(MCAST_IF_IP))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

print("Ready")
saveCounter = 0

# Initialize buffers and save counters for each filter
buffers = {filter_val: queue.Queue(20) for filter_val in filters}
save_counters = {filter_val: 0 for filter_val in filters}
buffer = queue.Queue(20)

# Receive/respond loop
while True:
data, address = sock.recvfrom(1024)
data_str = data.decode("utf-8").strip()
timestamped_data = f"[{address[0]} - {datetime.now().strftime('%b-%d-%Y_%H:%M:%S')}] {data_str}"
print(timestamped_data)

# Check each filter and process data accordingly
for filter_val in filters:
if filter_val in data_str:
buffers[filter_val].put(timestamped_data)
if buffers[filter_val].full():
buffers[filter_val].get()

# Save data if specific keywords are found or if save counter is active
if "NTP-Update not successful" in data_str or "Start program" in data_str:
with open(f"log_{filter_val}.txt", 'a') as f:
while not buffers[filter_val].empty():
f.write(buffers[filter_val].get() + "\n")
save_counters[filter_val] = 20 # Start the save counter

if save_counters[filter_val] > 0:
with open(f"log_{filter_val}.txt", 'a') as f:
f.write(timestamped_data + "\n")
if save_counters[filter_val] == 1:
f.write("\n")
save_counters[filter_val] -= 1
if filter is not None and filter not in data_str:
continue
data_str = "[" + str(address[0]) + " - " + datetime.now().strftime('%b-%d-%Y_%H:%M:%S') + "] " + data_str
print(data_str)
buffer.put(data_str)
if buffer.full():
buffer.get()


if "NTP-Update not successful" in data_str or "Start program" in data_str:
f = open("log.txt",'a')
while not buffer.empty():
f.write(buffer.get())
f.write("\n")
f.close()
saveCounter = 20

if saveCounter > 0:
f = open("log.txt",'a')
f.write(data_str)
f.write("\n")
if saveCounter == 1:
f.write("\n")
f.close()
saveCounter -= 1


# Main
if __name__ == '__main__':
# Check if filters are given
# Use filters as arguments: python3 multicastUDP_receiver.py "filter1" "filter2" ...

# Check if a filter is given
# use filter as argument to filter messages: python3 multicastUDP_receiver.py "filter"

if len(sys.argv) > 1:
start(sys.argv[1:])
start(sys.argv[1])
else:
start()
16 changes: 13 additions & 3 deletions ntp_client_plus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ void NTPClientPlus::calcDate()
daysInMonth[2] = 28;
}

unsigned int dayOfYear = (days1900 - ((this->_dateYear - 1900) * 365) - leapDays);
this->_dayOfYear = (days1900 - ((this->_dateYear - 1900) * 365) - leapDays);

// calc current month
this->_dateMonth = this->getMonth(dayOfYear);
this->_dateMonth = this->getMonth(this->_dayOfYear);

this->_dateDay = 0;

Expand All @@ -277,7 +277,7 @@ void NTPClientPlus::calcDate()
{
this->_dateDay = this->_dateDay + daysInMonth[i];
}
this->_dateDay = dayOfYear - this->_dateDay;
this->_dateDay = this->_dayOfYear - this->_dateDay;

// calc day of week:
// Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7
Expand Down Expand Up @@ -314,6 +314,16 @@ unsigned int NTPClientPlus::getDayOfWeek()
return this->_dayOfWeek;
}

/**
* @brief Getter for day of the year
*
* @return unsigned int
*/
unsigned int NTPClientPlus::getDayOfYear()
{
return this->_dayOfYear;
}

/**
* @brief Function to calc current year
*
Expand Down
2 changes: 2 additions & 0 deletions ntp_client_plus.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class NTPClientPlus{
String getFormattedDate();
void calcDate();
unsigned int getDayOfWeek();
unsigned int getDayOfYear();
unsigned int getYear();
bool isLeapYear(unsigned int year);
int getMonth(int dayOfYear);
Expand Down Expand Up @@ -60,6 +61,7 @@ class NTPClientPlus{
unsigned int _dateMonth = 0;
unsigned int _dateDay = 0;
unsigned int _dayOfWeek = 0;
unsigned int _dayOfYear = 0;


byte _packetBuffer[NTP_PACKET_SIZE];
Expand Down
2 changes: 1 addition & 1 deletion pong.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#define DEBOUNCE_TIME_PONG 10 // in ms

#define X_MAX 11
#define Y_MAX 11
#define Y_MAX 10

#define GAME_DELAY_PONG 80 // in ms
#define BALL_DELAY_MAX 350 // in ms
Expand Down
2 changes: 1 addition & 1 deletion snake.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#define DEBOUNCE_TIME_SNAKE 300 // in ms

#define X_MAX 11
#define Y_MAX 11
#define Y_MAX 10

#define GAME_DELAY_SNAKE 400 // in ms

Expand Down
2 changes: 1 addition & 1 deletion tetris.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
#define LEVELUP 4 // Number of rows before levelup, default 5

#define WIDTH 11
#define HEIGHT 11
#define HEIGHT 10

class Tetris{

Expand Down
66 changes: 59 additions & 7 deletions wordclock_esp8266.ino
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ enum direction {right, left, up, down};
// width of the led matrix
#define WIDTH 11
// height of the led matrix
#define HEIGHT 11
#define HEIGHT 10

// own datatype for state machine states
#define NUM_STATES 6
Expand Down Expand Up @@ -127,6 +127,10 @@ const char WebserverURL[] = "www.wordclock.local";

int utcOffset = 60; // UTC offset in minutes

const unsigned int num_coeff = 5; // number of coeffients + 1
// Sunsetminutes (without summer- wintertimeshift!)
const double sunsetMinutes[] = { 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1019, 1020, 1021, 1023, 1024, 1026, 1027, 1028, 1030, 1031, 1033, 1034, 1036, 1037, 1039, 1040, 1042, 1043, 1045, 1047, 1048, 1050, 1051, 1053, 1054, 1056, 1057, 1059, 1061, 1062, 1064, 1065, 1067, 1068, 1070, 1071, 1073, 1075, 1076, 1078, 1079, 1081, 1082, 1084, 1085, 1087, 1088, 1090, 1091, 1093, 1094, 1096, 1097, 1098, 1100, 1101, 1103, 1104, 1106, 1107, 1109, 1110, 1111, 1113, 1114, 1116, 1117, 1119, 1120, 1121, 1123, 1124, 1126, 1127, 1128, 1130, 1131, 1133, 1134, 1135, 1137, 1138, 1140, 1141, 1142, 1144, 1145, 1147, 1148, 1149, 1151, 1152, 1154, 1155, 1156, 1158, 1159, 1161, 1162, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1177, 1179, 1180, 1181, 1183, 1184, 1185, 1187, 1188, 1189, 1190, 1192, 1193, 1194, 1195, 1197, 1198, 1199, 1200, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1216, 1217, 1218, 1219, 1219, 1220, 1221, 1221, 1222, 1222, 1223, 1223, 1223, 1224, 1224, 1224, 1224, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1224, 1224, 1224, 1224, 1223, 1223, 1222, 1222, 1221, 1221, 1220, 1220, 1219, 1218, 1217, 1217, 1216, 1215, 1214, 1213, 1212, 1211, 1210, 1209, 1208, 1207, 1205, 1204, 1203, 1202, 1200, 1199, 1198, 1196, 1195, 1193, 1192, 1190, 1189, 1187, 1186, 1184, 1182, 1181, 1179, 1177, 1176, 1174, 1172, 1170, 1169, 1167, 1165, 1163, 1161, 1159, 1158, 1156, 1154, 1152, 1150, 1148, 1146, 1144, 1142, 1140, 1138, 1136, 1134, 1132, 1130, 1128, 1126, 1124, 1122, 1120, 1118, 1116, 1114, 1112, 1110, 1108, 1106, 1104, 1102, 1100, 1098, 1096, 1094, 1092, 1090, 1088, 1086, 1084, 1082, 1080, 1078, 1076, 1074, 1072, 1070, 1068, 1066, 1064, 1062, 1060, 1058, 1056, 1055, 1053, 1051, 1049, 1047, 1046, 1044, 1042, 1040, 1039, 1037, 1035, 1034, 1032, 1030, 1029, 1027, 1026, 1024, 1023, 1021, 1020, 1019, 1017, 1016, 1015, 1013, 1012, 1011, 1010, 1009, 1008, 1007, 1006, 1005, 1004, 1003, 1002, 1001, 1000, 1000, 999, 998, 998, 997, 997, 996, 996, 995, 995, 995, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 995, 995, 995, 996, 996, 997, 997, 998, 998, 999, 1000, 1000, 1001, 1002, 1003, 1004};

// ----------------------------------------------------------------------------------
// GLOBAL VARIABLES
// ----------------------------------------------------------------------------------
Expand Down Expand Up @@ -612,23 +616,39 @@ void checkNightmode(){
logger.logString("Check nightmode");
int hours = ntp.getHours24();
int minutes = ntp.getMinutes();

int dayofyear = ntp.getDayOfYear();
bool summertime = ntp.updateSWChange();

dayofyear = limit(dayofyear, 1, 365);
nightMode = false; // Initial assumption

// Convert all times to minutes for easier comparison
int currentTimeInMinutes = hours * 60 + minutes;
int startInMinutes = nightModeStartHour * 60 + nightModeStartMin;
int endInMinutes = nightModeEndHour * 60 + nightModeEndMin;

//double poly[] = {1.0208E+3, -170.4552E-3, 30.0056E-3, -173.0480E-6, 251.6062E-9}; // a0+a1*x+a2*x^2+a3*x^3+a4*x^4
//int startInMinutes = poly_eval(poly, dayofyear);
//if (summertime == true) startInMinutes += 60;
//logger.logString("Sunset startInminutes (polynomial): " + String(startInMinutes));
int startInMinutes = sunsetMinutes[dayofyear - 1];
if (summertime == true) startInMinutes += 60;
logger.logString("Sunset startInminutes: " + String(startInMinutes));

loadBrightnessSettingsFromEEPROM();

if (startInMinutes < endInMinutes && nightModeActivated) { // Same day scenario
if (startInMinutes < currentTimeInMinutes && currentTimeInMinutes < endInMinutes) {
nightMode = true;
logger.logString("Nightmode active");
brightness = (uint8_t)(brightness * 0.5);
ledmatrix.setBrightness(brightness);
logger.logString("Darkmode Brightness: " + String(brightness));
logger.logString("Darkmode active");
}
} else if (startInMinutes > endInMinutes && nightModeActivated) { // Overnight scenario
if (currentTimeInMinutes >= startInMinutes || currentTimeInMinutes < endInMinutes) {
nightMode = true;
logger.logString("Nightmode active");
brightness = (uint8_t)(brightness * 0.5);
ledmatrix.setBrightness(brightness);
logger.logString("Darkmode Brightness: " + String(brightness));
logger.logString("Darkmode active");
}
}
}
Expand Down Expand Up @@ -1157,3 +1177,35 @@ String leadingZero2Digit(int value){
msg += String(value);
return msg;
}

/**
* @brief Polynomial evaluation (num_coeff = grade simplified)
*
* @param coeff
* @param x
* @return double
*/
double poly_eval(double coeff[num_coeff], double x) {
double result = coeff[num_coeff-1];
for (size_t i = num_coeff-1; i --> 0;)
result = coeff[i] + x * result;
return result;
}

/**
* @brief Limit value to min/max
*
* @param value
* @param min
* @param max
* @return int
*/
int limit(int value, int min, int max) {
if (value < min) {
return min;
} else if (value > max) {
return max;
} else {
return value;
}
}
Loading