/*
Часы матрица на Arduino v1.01
Страница проекта: https://arduino-tex.ru/news/30/chasy-matrica-na-arduino-i-adresnyh-svetodiodah-ws2812b.html
Сайт разработчика https://portal-pk.ru/
Проекты на Arduino https://portal-pk.ru/page-17/proekty-na-arduino.html
Проекты на ESP https://arduino-tex.ru/menu/10/11/proekty-na-esp8266-esp32.html
ЧПУ на Arduino и ESP32 https://cnc-tex.ru/
*/
#define FASTLED_ALLOW_INTERRUPTS 0
// uncomment following lines if using rtc (A4 = SDA, A5 = SCL)
#include <DS3232RTC.h>
#include <Wire.h>
#include <FastLED.h>
#include <TimeLib.h>
#include <EEPROM.h>
#define RESX 18 // 18 столбцов
#define RESY 6 // 6 строк
#define DIGITX 3 // ширена символа
#define DIGITY 6 // высота символа
#define LED_COUNT RESX * RESY // размер матрицы
#define LED_PIN 6 // Пин поключения ленты 6
time_t time;
CRGB leds[LED_COUNT];
byte brightness = 145;
byte saturation = 255;
byte startHue = 150;
byte k = 0;
byte digits[16][DIGITX * DIGITY] = {
{ 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }, // 0
{ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 }, // 1
{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1 }, // 2
{ 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1 }, // 3
{ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 }, // 4
{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1 }, // 5
{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }, // 6
{ 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 }, // 7
{ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }, // 8
{ 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1 }, // 9
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // .
{ 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 }, // t
{ 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // градус
};
/* переменные */
boolean lastButten = LOW; // предыдущее состояние кнопки
boolean currentButten = LOW; // текущее состояние кнопки
boolean lastButten1 = LOW; // предыдущее состояние кнопки
boolean currentButten1 = LOW; // текущее состояние кнопки
byte status = 0; // текущий статус
byte button_1 = 4; // кнопка
byte button_2 = 3; // кнопка
void setup() {
Serial.begin(9600);
Serial.println("GridClock v1...");
// uncomment following 3 lines if using rtc
// Wire.begin();
setSyncProvider(RTC.get);
// setSyncInterval(30);
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT);
FastLED.setMaxPowerInVoltsAndMilliamps(5, 750); // Limit power usage to 5V/500mA
FastLED.setBrightness(brightness);
// uncomment following 2 lines only to set time on rtc when uploading
// setTime(21, 51, 45, 26, 2, 2019); // set clock (24HH,MM,SS,Day,Month,Year)
// RTC.set(now());
clearDisplay();
FastLED.show();
brightness = EEPROM.read(1);
startHue = EEPROM.read(2);
pinMode(button_1, INPUT_PULLUP); // настроить пин кнопки
pinMode(button_2, INPUT_PULLUP); // настроить пин кнопки
}
void loop() {
displayTime(startHue);
FastLED.show();
delay(100);
clearDisplay();
// if (t % 10 == 0)
//startHue++;
currentButten = debvance (lastButten); // Передаем функции дребезга значение по умолчанию LOW
if (lastButten == LOW && currentButten == HIGH) // Проверяем отпускали мы кнопку или нет
{
status++; // инвертируем Статус
}
lastButten = currentButten; // Переприсваеваем прошлое состояние кнопки
currentButten1 = debvance1 (lastButten1); // Передаем функции дребезга значение по умолчанию LOW
if (lastButten1 == LOW && currentButten1 == HIGH) // Проверяем отпускали мы кнопку или нет
{
if (status == 1)
{
brightness = brightness + 10;
if (brightness > 130)
brightness = 50;
EEPROM.write(1, brightness); /// сохроняем в энерго независимую память яркоасть дисплеея
}
else if (status == 2)
{
sTime(1);
}
else if (status == 3)
{
sTime(2);
}
else if (status == 4)
{
sTime(3);
}
else if (status == 5)
{
sTime(4);
}
else if (status == 6)
{
sTime(5);
}
else if (status == 7)
{
sTime(6);
}
else
{
startHue = startHue + 10;
if (startHue > 250)
startHue = 10;
EEPROM.write(2, startHue); // сохроняеи в энерго независимую память настроику цвета
}
if (status > 7)
status = 0;
}
lastButten1 = currentButten1; // Переприсваеваем прошлое состояние кнопки
}
void sTime(int num) { // функция настройки часов
int h = hour();
int m = minute();
int d = day();
int mon = month();
int y = year();
if (num == 1)
{
h++;
if (h > 23)
h = 0;
}
if (num == 2)
{
m++;
if (m > 59)
m = 0;
}
if (num == 3)
{
d++;
if (d > 31)
d = 1;
}
if (num == 4)
{
mon++;
if (mon > 12)
mon = 1;
}
if (num == 5)
y++;
if (num == 6)
y--;
setTime(h, m, second(), d, mon, y); // set clock (24HH,MM,SS,Day,Month,Year)
setTime(h, m, second(), d, mon, y); /// обновляем 2 раз так так как увелчиваеться следующее значение.
RTC.set(now());
}
///// Конец функции настройки часов ///
void displayTime(byte color) { /// выводзначений при настройке часов
time_t t = now();
byte colorOffset = 16;
if (((second(t) > 20) and (second(t) < 30)) and (status < 2) )
{
int t = RTC.temperature();
int celsius = t / 4.0;
showDigit(11, 1, color);
showDigit(celsius / 10, 6, color);
showDigit(celsius % 10, 10, color);
showDigit(12, 14, color);
}
else if (((second(t) < 50) or (status == 2) or (status == 3)) and (status != 4) and (status != 5) and (status != 6) and (status != 7))
{
if (status == 2)
{
if (second(t) % 2 == 0)
{
showDigit((hour(t) / 10), 1, color);
showDigit((hour(t) % 10), 5, color);
}
}
else
{
showDigit((hour(t) / 10), 1, color);
showDigit((hour(t) % 10), 5, color);
}
if (status == 3)
{
if (second(t) % 2 == 0)
{
showDigit((minute(t) / 10), 11, color);
showDigit((minute(t) % 10), 15, color);
}
}
else
{
showDigit((minute(t) / 10), 11, color);
showDigit((minute(t) % 10), 15, color);
}
if ((second(t) % 2 == 0) and (status != 2) and (status != 3)) {
setPixel(9, 1, color);
setPixel(9, 4, color);
//startHue++;
}
}
else if (((status != 2) and (status != 3)) or (status == 4) or (status == 5) or (status == 6) or (status == 7))
{
if (status == 4 or status == 5)
k = 0; // сдвиг на экране
else if (status == 6 or status == 7)
k = 20; // сдвиг на экране
else
k++; // сдвиг на экране
if (status == 4)
{
if (second(t) % 2 == 0)
{
showDigit((day() / 10), (0 - k), color);
showDigit((day() % 10), (4 - k), color);
}
}
else
{
showDigit((day() / 10), (0 - k), color);
showDigit((day() % 10), (4 - k), color);
}
showDigit(10, (7 - k), color);
if (status == 5)
{
if (second(t) % 2 == 0)
{
showDigit((month() / 10), (9 - k), color);
showDigit((month() % 10), (13 - k), color);
}
}
else
{
showDigit((month() / 10), (10 - k), color);
showDigit((month() % 10), (14 - k), color);
}
showDigit(10, (17 - k), color);
if (status == 6 or status == 7)
{
if (second(t) % 2 == 0)
{
showDigit(2, (20 - k), color);
showDigit(0, (24 - k), color);
showDigit(((year() - 2000) / 10), (28 - k), color);
showDigit(((year() - 2000) % 10), (32 - k), color);
}
}
else
{
showDigit(2, (20 - k), color);
showDigit(0, (24 - k), color);
showDigit(((year() - 2000) / 10), (28 - k), color);
showDigit(((year() - 2000) % 10), (32 - k), color);
}
if (k == 33)
k = -16;
}
}
/// Конец функции - вывод значений при настройке часов
void showDigit(byte digit, byte x, byte color) { /// вывод символов на матрицу
for (byte i = 0; i < (DIGITX * DIGITY); i++) {
if (digits[digit][i] == 1) setPixel(x + (i - ((i / DIGITX) * DIGITX)), RESY - 1 - (i / DIGITX), color);
}
}
void setPixel(byte x, byte y, byte color) {
if (x < RESX && y < RESY) {
if ((y % 2) == 0) {
leds[(y * RESX) + x].setHSV(color, saturation, brightness);
} else {
leds[(y * RESX) + (RESX - (x + 1))].setHSV(color, saturation, brightness);
}
}
}
void clearDisplay() { /// чистка дисплеея
for (byte i = 0; i < LED_COUNT; i++) {
leds[i].setHSV(0, 0, 0);
}
}
boolean debvance (boolean last) //убираем дребизг
{
boolean current = digitalRead (button_1); // считываем данные с кнопки
if (last != current) // Если текущее состояни еотличететься от предыдущего
{
delay (5); // Ждем 5 милисек.
current = digitalRead (button_1); // Присваеваем текущее состояние кнопки
return current;
}
}
boolean debvance1 (boolean last) //убираем дребизг
{
boolean current = digitalRead (button_2); // считываем данные с кнопки
if (last != current) // Если текущее состояни еотличететься от предыдущего
{
delay (5); // Ждем 5 милисек.
current = digitalRead (button_2); // Присваеваем текущее состояние кнопки
return current;
}
}