Всем здраствуйте! Меня зовут Николай и я хожу в кружок робототехнки и програмирования в школе. У нас скоро региональная выставка проектов, и я хочу показать на ней часы, но у меня возникают с ними проблемы, а мой учитель кружка говорит лучше сделай светофор. Мне не нравится светофор это глупо. Помогите с проектом пожалуйста.
Что я хочу от часов.
Часы отображают время, точка номер 2 мигает. При нажатии кнопки энкодера, переходит в режим настройки времени, где поворот ручки меняет текущее время - по одной минуте за поворот, вперед или назад. Еще один клик переводит в режим будильника, где настраивается будильник таким же образом. Во время настройки будильника мигает так же 4 точка в углу правом. Точка сохраняется при отображении времени вне режима настройки, если будильник установлен. что бы отключить или включить будильник, нужно задержать кнопку энкодера в нормальном режиме и точка пропадет, выключив будильник. Так же будильник активируется, зажав кнопку. Третий режим - это почасовой сигнал. Поворотом энокдера меняется значение On и Off. Почасовой сигнал пищит каждый раз когда начинается новый час. Его режим активности отображается горящей точкой в левом углу.
Какие проблемы.
Будильник не работает
Почасовой сигнал не работает
Я использую дисплей 4401as-1 (0.40-inch Emitting color: Red Mode: Common-Cathode (CC) Digit: 4-Digit Category: LED 7-Segment Display) потому что он был самый дешовый, энкодер я выпаял из сломоного блока питания (без резьбы крепежнной) без платы просто голый, и модуль RTC Ds1302 тоже самый дешевый.
Вот мой код
#include <GyverSegment.h>
#include <Ds1302.h>
#include <EncButton.h>
// ------------------ Настройка дисплея ------------------
uint8_t segPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
uint8_t digPins[] = {10, 11, 12, 13};
DispBare<4, true, false> disp(digPins, segPins);
// ------------------ Настройка DS1302 ------------------
#define DS1302_CE A2
#define DS1302_CLK A0
#define DS1302_IO A1
Ds1302 rtc(DS1302_CE, DS1302_CLK, DS1302_IO);
// ------------------ Настройка энкодера и кнопки ------------------
EncButton eb(A3, A4, A5, INPUT_PULLUP, INPUT_PULLUP, LOW);
// ------------------ Настройка буззера ------------------
#define BUZZER_PIN A6
// ------------------ Режимы работы ------------------
enum Mode {
MODE_NORMAL,
MODE_SET_TIME,
MODE_SET_ALARM,
MODE_SET_HOURLY
};
Mode currentMode = MODE_NORMAL;
// Флаги и параметры
bool alarmEnabled = false;
bool hourlyChimeEnabled = false;
int alarmHour = 7;
int alarmMinute = 0;
// Переменные для настройки времени
int tempHour = 0;
int tempMinute = 0;
// ------------------ Переменные для мигания ------------------
unsigned long blinkTimer = 0;
bool blinkState = false;
const unsigned long BLINK_INTERVAL = 500;
// Для почасового сигнала
int lastDisplayedHour = -1;
// ------------------ Прототипы функций ------------------
void updateBlink();
void updateDisplay(int dispHour, int dispMinute);
void playBeep();
// ------------------ setup() ------------------
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
rtc.init();
if (rtc.isHalted()) {
Ds1302::DateTime dt = {22, 1, 1, 12, 0, 0, 6};
rtc.setDateTime(&dt);
}
disp.clear();
disp.update();
eb.setBtnLevel(LOW);
eb.counter = 0;
blinkTimer = millis();
}
// ------------------ loop() ------------------
void loop() {
disp.tick(); // Обновление дисплея
eb.tick(); // Обновление энкодера и кнопки
updateBlink();
static Ds1302::DateTime now;
if (currentMode == MODE_NORMAL) rtc.getDateTime(&now);
switch (currentMode) {
case MODE_NORMAL:
updateDisplay(now.hour, now.minute);
// Проверка будильника
if (alarmEnabled && now.hour == alarmHour && now.minute == alarmMinute && now.second == 0) {
playBeep();
}
// Проверка почасового сигнала
if (hourlyChimeEnabled && now.minute == 0 && now.second == 0 && now.hour != lastDisplayedHour) {
playBeep();
lastDisplayedHour = now.hour;
}
if (now.minute != 0) lastDisplayedHour = -1;
break;
case MODE_SET_TIME:
if (eb.counter != 0) {
int totalMinutes = tempHour * 60 + tempMinute + eb.counter;
totalMinutes = (totalMinutes + 1440) % 1440;
tempHour = totalMinutes / 60;
tempMinute = totalMinutes % 60;
eb.counter = 0;
}
updateDisplay(tempHour, tempMinute);
break;
case MODE_SET_ALARM:
if (eb.counter != 0) {
int totalMinutes = tempHour * 60 + tempMinute + eb.counter;
totalMinutes = (totalMinutes + 1440) % 1440;
tempHour = totalMinutes / 60;
tempMinute = totalMinutes % 60;
eb.counter = 0;
}
updateDisplay(tempHour, tempMinute);
break;
case MODE_SET_HOURLY:
if (eb.turn()) {
// Переключение между ON и OFF при повороте энкодера
hourlyChimeEnabled = !hourlyChimeEnabled;
}
// Отображение ON или OFF на дисплее
updateDisplay(hourlyChimeEnabled ? 1 : 0, 0);
break;
}
// Долгое нажатие для включения/выключения будильника
if (currentMode == MODE_NORMAL && eb.hold()) {
alarmEnabled = !alarmEnabled;
tone(BUZZER_PIN, 1000, 200);
}
// Короткое нажатие для переключения режимов
if (eb.click()) {
switch (currentMode) {
case MODE_NORMAL:
rtc.getDateTime(&now);
tempHour = now.hour;
tempMinute = now.minute;
currentMode = MODE_SET_TIME;
break;
case MODE_SET_TIME: {
Ds1302::DateTime now;
rtc.getDateTime(&now);
Ds1302::DateTime newTime = {now.year, now.month, now.day, tempHour, tempMinute, now.second, now.dow};
rtc.setDateTime(&newTime);
tempHour = alarmHour;
tempMinute = alarmMinute;
currentMode = MODE_SET_ALARM;
break;
}
case MODE_SET_ALARM:
alarmHour = tempHour;
alarmMinute = tempMinute;
currentMode = MODE_SET_HOURLY;
break;
case MODE_SET_HOURLY:
currentMode = MODE_NORMAL;
break;
}
}
disp.delay(10); // Задержка для обновления дисплея
}
void updateBlink() {
if (millis() - blinkTimer >= BLINK_INTERVAL) {
blinkTimer = millis();
blinkState = !blinkState;
}
}
void updateDisplay(int dispHour, int dispMinute) {
disp.clear();
if (currentMode == MODE_SET_HOURLY) {
// В режиме настройки почасового сигнала отображаем ON или OFF
if (hourlyChimeEnabled) {
disp.print("ON");
disp.setCursor(0);
} else {
disp.print("OFF");
disp.setCursor(0);
}
} else {
// В остальных режимах отображаем время
char buf[5];
sprintf(buf, "%02d%02d", dispHour, dispMinute);
disp.setCursor(0);
disp.print(buf);
if (currentMode == MODE_NORMAL) {
disp.buffer[1] = blinkState ? (disp.buffer[1] | 0x80) : (disp.buffer[1] & 0x7F);
if (alarmEnabled) disp.buffer[3] |= 0x80;
if (hourlyChimeEnabled) disp.buffer[0] |= 0x80;
}
}
disp.update(); // Обновление дисплея
}
void playBeep() {
tone(BUZZER_PIN, 1000, 200); // Воспроизведение звукового сигнала
}