В предверии Нового года решил сделать что-нибудь «электронно-микроконтроллерное» под елку. Порылся в своих закромах… На глаза попался матричный светодиодный модуль на MAX7219 и модуль часов реального времени на микросхеме DS3231. Так родилась идея сделать простенькие часы с бегущей строкой, которые бы отсчитывали оставшиеся деньки до «боя курантов»:)
В основу моего скетча легли два проекта из интернета: сам скетч для работы с матричным LED модулем на микросхеме MAX7219 и русификатор популярной библиотеки для дисплеев Adafruit_GFX.
В итоге получился такой скетч:
#include <DS3232RTC.h>
#include <EEPROM.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
//============== глобальные переменные ===========================================================
String LastD;
String StrHour;
String StrMinute;
String StrTime;
int LastDays=0;
//============= переменные для настройки режимов светодиодной матрицы ============================
int pinCS = 9;
int numberOfHorizontalDisplays = 4; // теперь у нас по-горизонтали 4 матрицы
int numberOfVerticalDisplays = 1; // а по-вертикали, по-прежнему, одна
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
int wait = 45; // время между крайними перемещениями букв
int spacer = 1; // расстояние между буквами
int width = 5 + spacer; // размер шрифта
void setup()
{
//============ инициализация модуля часов реального времени ====================================
Serial.begin(9600); //настраиваем COM-порт для отладки
setSyncProvider(RTC.get); //устанавливаем режим считывания текущего времени с модуля RTC
if(timeStatus() != timeSet) //проверяем статус работы модуля RTC
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
//============ окончание инициализация модуля часов реального времени =========================
//============ инициализация MAX7219 ==========================================================
matrix.setIntensity(3); //яркость
matrix.setRotation( 0, 1 ); //в моём случае потребовалось "развернуть" каждую матрицу
matrix.setRotation( 1, 1 );
matrix.setRotation( 2, 1 );
matrix.setRotation( 3, 1 );
//=========== окончание инициализация MAX7219 ===============================================
}
void loop()
{
LastDaysNY(); //формирование строки с остатком дней до Нового года
TickerLEDs (LastD); //отображение бегущей строки с остатком дней до Нового года
printsClockOnLED(); //формирование строки текущего времени
StringLEDs (StrTime); //отображение статичной строки текущего времени на LED матрице
delay (1200); //задержка для отображения времени
}
//============== ФУНКЦИИ =========================================================================
//функция вывода текущего времени и даты в COM-порт
void digitalClockDisplay()
{
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(' ');
Serial.print(day());
Serial.print(' ');
Serial.print(month());
Serial.print(' ');
Serial.print(year());
Serial.println();
Serial.println(StrTime);
}
//функция добавления "0" перед однозначными числами
void printDigits(int digits)
{
Serial.print(':');
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
//функция отображения бегущей строки на LED матрице
void TickerLEDs (String tape) {
for ( int i = 0 ; i < width * tape.length() + matrix.width() - 1 - spacer; i++ ) {
matrix.fillScreen(LOW);
int letter = i / width;
int x = (matrix.width() - 1) - i % width;
int y = (matrix.height() - 8) / 2; // center the text vertically
while ( x + width - spacer >= 0 && letter >= 0 ) {
if ( letter < tape.length() ) {
matrix.drawChar(x, y, tape[letter], HIGH, LOW, 1);
}
letter--;
x -= width;
}
matrix.write();
delay(wait);
}
}
//функция отображения статичной строки на LED матрице
void StringLEDs (String tape) {
matrix.fillScreen(LOW);
int letter = width;
int x = matrix.width()+6;
int y = (matrix.height() - 8) / 2; // center the text vertically
while ( x + width - spacer >= 0 && letter >= 0 ) {
if ( letter < tape.length() ) {
matrix.drawChar(x, y, tape[letter], HIGH, LOW, 1);
}
letter--;
x -= width;
}
matrix.write();
}
//функция перевода времени в строчный формат
void printsClockOnLED() {
if (hour()<10) {
StrHour = String(0) + String(hour());
} else {
StrHour = String(hour());
}
if (minute()<10) {
StrMinute = String(0) + String(minute());
} else {
StrMinute = String(minute());
}
StrTime = StrHour + String(":") + StrMinute;
}
//функция отчёта обратного отсчёта до Нового года
void LastDaysNY(){
LastDays = 31 - day();
LastD = String(LastDays) + String(utf8rus(" дня до Нового года!"))+(char)0x06;
}
//функция перекодирования кириллицы из UTF-8 в формат Windows-1251
String utf8rus(String source)
{
int i,k;
String target;
unsigned char n;
char m[2] = { '0', '\0' };
k = source.length(); i = 0;
while (i < k) {
n = source[i]; i++;
if (n >= 0xBF){
switch (n) {
case 0xD0: {
n = source[i]; i++;
if (n == 0x81) { n = 0xA8; break; }
if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
break;
}
case 0xD1: {
n = source[i]; i++;
if (n == 0x91) { n = 0xB7; break; }
if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
break;
}
}
}
m[0] = n; target = target + String(m);
}
return target;
}
Подробно расписывать работу часов не вижу смысла, ибо достаточно разжёванного материала в Интернете. К тому же, мой скетч пестрит комментариями. Данные часы прекрасно могут подойти для своего рода информатора на рабочем месте. Можно прикрутить всё тот же модуль Wi-Fi на ESP8266 и посылать на него напоминалки со смартфона😉
Хочется поздравить Всех с наступающим 2020 годом, пожелать здоровья и творческих успехов!
Архив для скачивания скетча и использованных мною библиотек: