Skip to content

Instantly share code, notes, and snippets.

@aambrozkiewicz
Created February 28, 2025 09:35
Show Gist options
  • Save aambrozkiewicz/06b0a0d89d7f0036ccc35870daf42600 to your computer and use it in GitHub Desktop.
Save aambrozkiewicz/06b0a0d89d7f0036ccc35870daf42600 to your computer and use it in GitHub Desktop.
Arduino MAX7219 display matrix with RTC showing current time/date and temperature using DS3231
#include <MD_MAX72xx.h>
#include <RTClib.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // Specify your hardware type
#define MAX_DEVICES 4 // Number of MAX7219 modules
#define CLK_PIN 13 // Clock pin
#define DATA_PIN 11 // Data pin
#define CS_PIN 10 // Chip select pin
RTC_DS3231 rtc;
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
const int ldrPin = A3;
unsigned long lastMillis;
unsigned int lastIntensity = 0;
unsigned int intensity = 0;
DateTime now;
char time[6], lastTime[6], date[7];
enum state_t {
INIT,
DISPLAY_TIME,
ANIMATE,
DISPLAY_TEMP,
DISPLAY_DATE,
NOOP,
};
state_t state = NOOP;
state_t animationNextStep = NOOP;
unsigned long timeMillis, tempMillis, dateMillis;
const char *daysOfTheWeek[] = { "nd", "pn", "wt", "sr", "cz", "pt", "so" };
const uint8_t symbol[2] = {
0b01101100,
0b01101100,
};
const uint8_t degreeSymbol[5] = {
0b00000110, // ** (flipped)
0b00001001, // * * (flipped)
0b00001001, // * * (flipped)
0b00000110, // ** (flipped)
0b00000000 // (empty row for spacing)
};
void setup() {
Serial.begin(9600);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC!");
while (1)
;
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting time...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set to compile time
}
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, 0);
setState(INIT);
}
void loop() {
if (!lastMillis || millis() - lastMillis >= 1000) {
int ldrValue = analogRead(ldrPin);
for (intensity = 0; intensity <= 5; intensity++) {
if (ldrValue > 550 - (intensity * 110)) {
break;
}
}
if (lastIntensity != intensity) {
mx.control(MD_MAX72XX::INTENSITY, intensity);
lastIntensity = intensity;
}
now = rtc.now();
sprintf(time, "%02d:%02d", now.hour(), now.minute());
sprintf(date, "%s. %d", daysOfTheWeek[now.dayOfTheWeek()], now.day());
lastMillis = millis();
}
switch (state) {
case INIT:
setState(DISPLAY_TEMP);
break;
case DISPLAY_TIME:
if (strcmp(lastTime, time)) {
mx.clear();
displayText(time);
strcpy(lastTime, time);
}
if (millis() - timeMillis >= 6000) {
animationNextStep = DISPLAY_TEMP;
setState(ANIMATE);
}
break;
case ANIMATE:
if (terminalLine()) {
setState(animationNextStep);
}
break;
case DISPLAY_TEMP:
if (millis() - tempMillis >= 6000) {
animationNextStep = DISPLAY_DATE;
setState(ANIMATE);
}
break;
case DISPLAY_DATE:
if (millis() - dateMillis >= 6000) {
animationNextStep = DISPLAY_TIME;
setState(ANIMATE);
}
}
// for (int row = 0; row < 8; row++) {
// for (int col = 0; col < 2; col++) {
// mx.setColumn(col, symbol[col] >> row | symbol[col] << (8 - row));
// }
// delay(500);
// }
}
void setState(state_t nextState) {
state = nextState;
switch (state) {
case DISPLAY_TIME:
mx.clear();
displayText(time);
timeMillis = millis();
break;
case DISPLAY_TEMP:
mx.clear();
displayTemp(rtc.getTemperature());
tempMillis = millis();
break;
case DISPLAY_DATE:
mx.clear();
displayText(date);
dateMillis = millis();
break;
}
}
bool terminalLine() {
static int8_t lastCol = 31;
static unsigned long lastMillis;
if (millis() - lastMillis < 100) {
return false;
}
for (uint8_t row = 0; row <= 7; row++) {
mx.setPoint(row, lastCol + 1, false);
mx.setPoint(row, lastCol, true);
}
lastMillis = millis();
lastCol--;
if (lastCol <= -2) {
lastCol = 31;
return true;
}
return false;
}
void displayTemp(float temp) {
String str_temp = String(temp, 1);
displayText(str_temp.c_str());
for (uint8_t col = 0; col <= 4; col++) {
mx.setColumn(col, degreeSymbol[col]);
}
}
uint8_t getCharWidth(char c) {
char buf[8];
return mx.getChar(c, sizeof(buf) / sizeof(buf[0]), buf);
}
// Returns number of column at which it left off
uint8_t displayText(const char *s) {
const char *pp = s;
uint8_t totalWidth = 0;
uint8_t len = 0;
while (*pp != '\0') {
totalWidth += getCharWidth(*pp);
pp++;
len++;
}
totalWidth += len - 2; // spacing?
int startingCol = (31 - totalWidth) / 2;
uint8_t nextCol = startingCol;
for (uint8_t i = 0; i < len; i++) {
nextCol += mx.setChar(31 - nextCol - i, *(s + i));
}
return nextCol;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment