Last active
July 19, 2019 07:54
-
-
Save terryspitz/071d01c8aa18b21ca6e702b238476f01 to your computer and use it in GitHub Desktop.
added seconds toggle by closing pins D0/RX briefly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Terry Spitz, 2019 | |
// Hardware: | |
// DS3231 Real Time Clock board | |
// 4x MAX7219 8x8 LED Matrix with controller | |
#include "LedControl.h" | |
#include <Wire.h> | |
#include <RtcDS3231.h> | |
TwoWire wire; | |
RtcDS3231<TwoWire> rtc(wire); | |
const int RTC_GND_PIN = D8; | |
const int RTC_VCC_PIN = D7; | |
const int RTC_SDA_PIN = D6; | |
const int RTC_SCL_PIN = D5; | |
//To switch between hh:mm and hh:mm:ss, briefly connect these pins | |
const int SEC_GND_PIN = D1; | |
const int SEC_TEST_PIN = RX; | |
const int DEVICE_COUNT = 4; | |
LedControl led = LedControl(D4, D2, D3, DEVICE_COUNT); | |
void setup() { | |
Serial.begin(115200); | |
Serial.println("\nStarted\n"); | |
//Serial.swap(); //Free RX,TX pins | |
pinMode(SEC_GND_PIN, OUTPUT); digitalWrite(SEC_GND_PIN, LOW); | |
pinMode(SEC_TEST_PIN, INPUT_PULLUP); | |
pinMode(RTC_GND_PIN, OUTPUT); digitalWrite(RTC_GND_PIN, LOW); | |
pinMode(RTC_VCC_PIN, OUTPUT); digitalWrite(RTC_VCC_PIN, HIGH); | |
wire.begin(RTC_SDA_PIN, RTC_SCL_PIN); | |
rtc.Begin(); | |
RtcDateTime now = rtc.GetDateTime(); | |
if (rtc.LastError() != 0) | |
{ | |
// we have a communications error | |
// see https://www.arduino.cc/en/Reference/WireEndTransmission for | |
// what the number means | |
Serial.print("RTC communications error = "); | |
Serial.println(rtc.LastError()); | |
Serial.println("Restarting in 5s"); | |
delay(5000); | |
ESP.reset(); | |
} | |
if (!rtc.IsDateTimeValid()) | |
{ | |
// Common Causes: | |
// 1) the battery on the device is low or even missing and the power line was disconnected | |
Serial.println("Warning: RTC lost confidence in the DateTime!"); | |
} | |
char datestring[9]; | |
snprintf_P(datestring, 9, PSTR("%02u:%02u:%02u"), | |
now.Hour(), now.Minute(), now.Second() ); | |
Serial.println(datestring); | |
for (char device = 0; device < DEVICE_COUNT; ++device) { | |
led.shutdown(device, false); //wake up led device | |
led.setIntensity(device, 3); | |
led.clearDisplay(device); | |
} | |
} | |
// My little 5x3 set of digits, from https://docs.google.com/spreadsheets/d/18fk7YnEaq9ArqHn4P15a8HQxXN0mI4ds9AppET3lukI/edit?usp=sharing | |
const char N_DIGITS = 15; | |
const char ROWS_PER_DIGIT = 6; | |
const int COLON = 11; | |
const byte DIGITS[N_DIGITS][ROWS_PER_DIGIT] = { | |
{0x2, 0x5, 0x5, 0x5, 0x2, 0}, // 0 | |
{0x2, 0x6, 0x2, 0x2, 0x7, 0}, // 1 | |
{0x6, 0x1, 0x2, 0x4, 0x7, 0}, // 2 | |
{0x6, 0x1, 0x7, 0x1, 0x6, 0}, // 3 | |
{0x1, 0x3, 0x5, 0x7, 0x1, 0}, // 4 | |
{0x7, 0x4, 0x7, 0x1, 0x6, 0}, // 5 | |
{0x3, 0x4, 0x7, 0x5, 0x7, 0}, // 6 | |
{0x7, 0x1, 0x1, 0x1, 0x1, 0}, // 7 | |
{0x7, 0x5, 0x7, 0x5, 0x7, 0}, // 8 | |
{0x7, 0x5, 0x7, 0x1, 0x1, 0}, // 9 | |
{0x2, 0x5, 0x5, 0x5, 0x2, 0}, // 0 repeated | |
{0x0, 0x1, 0x0, 0x1, 0x0, 0}, // : | |
{0x0, 0x0, 0x0, 0x0, 0x0, 0}, // blank | |
{0x1, 0x3, 0x1, 0x1, 0x3, 0}, // 1, 2-pixel wide | |
{0x0, 0x0, 0x0, 0x0, 0x0, 0}, // blank | |
}; | |
unsigned long delaytime_scroll = 100; | |
const int PARTS_HHMMSS = 8; //6 digits + 2 colons | |
const int PARTS_HHMM = 5; //4 digits + 1 colon | |
int SHIFTS_HHMMSS[PARTS_HHMMSS] = {26, 22, 20, 16, 12, 10, 6, 2}; | |
int SHIFTS_HHMM[PARTS_HHMM] = {22, 18, 16, 12, 8}; | |
int prev_digits[PARTS_HHMMSS]; | |
bool showSeconds = false; | |
void loop() | |
{ | |
//Serial.println("loop"); | |
RtcDateTime now = rtc.GetDateTime(); | |
if(now.Second()%10==prev_digits[7]) | |
return; | |
int digits[PARTS_HHMMSS] = {now.Hour() / 10, now.Hour() % 10, COLON, | |
now.Minute() / 10, now.Minute() % 10, COLON, | |
now.Second() / 10, now.Second() % 10 | |
}; | |
int parts = showSeconds ? PARTS_HHMMSS : PARTS_HHMM; | |
int* shifts = showSeconds ? SHIFTS_HHMMSS : SHIFTS_HHMM; | |
bool scrolls[PARTS_HHMMSS]; | |
for (char part = 0; part < parts; ++part) { | |
scrolls[part] = digits[part] != prev_digits[part]; | |
prev_digits[part] = digits[part]; | |
} | |
for (char scroll = 0; scroll <= ROWS_PER_DIGIT; ++scroll) | |
{ | |
uint32_t rows[8]; | |
for (char row = 0; row < 8; ++row) | |
rows[row] = 0; | |
for (char part = 0; part < parts; ++part) | |
{ | |
if (digits[part] != COLON) | |
rows[0] |= uint32_t(digits[part]) << shifts[part]; | |
for (char row = 0; row < 5; ++row) | |
{ | |
char rowdigit = digits[part]; | |
if (scrolls[part] && (scroll + row) < ROWS_PER_DIGIT) { | |
if (digits[part] == 0) { | |
if (part == 0 || part == 3 || part == 5) | |
rowdigit = 5; | |
else | |
rowdigit = 9; | |
} | |
else | |
rowdigit--; | |
} | |
char rowindex = (row + (scrolls[part] ? scroll : 0)) % ROWS_PER_DIGIT; | |
rows[row + 2] |= uint32_t(DIGITS[rowdigit][rowindex]) << shifts[part]; | |
} | |
} | |
int brightness = (now.Hour()<10 || now.Hour()>18) ? 0 : 5; | |
for (char row = 0; row < 8; ++row) { | |
//Serial.println(String(int(row)) + "," + String(rows[row])); | |
for (char device = 0; device < DEVICE_COUNT; ++device) { | |
led.setIntensity(device, brightness); | |
led.setRow((DEVICE_COUNT - 1 - device), row, (rows[row] >> (8 * device)) & 0xff); | |
} | |
} | |
delay(delaytime_scroll); | |
} | |
if(digitalRead(SEC_TEST_PIN)==LOW) | |
showSeconds = !showSeconds; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment