Цифровые часы на Arduino с конечным автоматом (YAKINDU Statechart Tools)
Компоненты и материалы
| Arduino UNO (или Mega — совместим с LCD Shield) | × | 1 |
| LCD Keypad Shield (16×2, 5 кнопок + Reset) | × | 1 |
Инструменты разработки
- YAKINDU Statechart Tools (бесплатно для некоммерческого использования) — графическое моделирование автоматов и генерация C++ кода
- Eclipse C++ IDE for Arduino
О проекте
Покажу, как создать цифровые часы с YAKINDU Statechart Tools и запустить на Arduino с LCD Keypad Shield.
Модель взята из работы Дэвида Харела о «расширении формализма конечных автоматов». Он использовал цифровые часы как пример. Я восстановил их в YAKINDU и перенёс на Arduino.
Как работают часы
Вспомните цифровые часы 90-х: время, будильники, секундомер, писк каждый час. Кнопки: on/off, mode, set, подсветка light on/off.
Кнопка Mode переключает режимы:
- Время (Clock)
- Дата (Date)
- Будильник 1, Будильник 2 (Alarm)
- Часовые сигналы (Chime)
- Секундомер (Stop Watch)
В меню: On/Off — настройка режима, Set — установка времени. Секундомер: Light On/Off — старт/стоп, есть круговые замеры.
Есть часовые сигналы (chime) и управляемая подсветка (в первой версии не подключены к железу).
Конечный автомат (State Machine)
Модель разделена на графическую (state diagram) и текстовую (определения событий, переменных) части.
Входные события: onoff, set, mode, light, light_r.
Внутреннее событие каждые 100 мс: every 100 ms / time += 1
Расчёт времени (формат HH:MM:SS):
display.first = (time / 36000) % 24; // часы
display.second = (time / 600) % 60; // минуты
display.third = (time / 10) % 60; // секунды
Обновление LCD: display.updateLCD(display.first, display.second, display.third, display.text) — вызывается каждый цикл.
Используются составные состояния (CompositeState), история (History), поддиаграммы (Sub-Diagrams), выходные узлы (ExitNodes) — для читаемости.
LCD Keypad Shield
5 кнопок подключены к А0 через делитель напряжения. Определение нажатой кнопки по АЦП:
#define NONE 0
#define SELECT 1
#define LEFT 2
#define DOWN 3
#define UP 4
#define RIGHT 5
static int readButton() {
int result = analogRead(0);
if (result < 50) return RIGHT;
if (result < 150) return UP;
if (result < 300) return DOWN;
if (result < 550) return LEFT;
if (result < 850) return SELECT;
return NONE;
}
Мои измерения: None=1023, Select=640, Left=411, Down=257, Up=100, Right=0.
Интерфейс автомата с железом
Сгенерированный C++ код требует реализацию интерфейсов. Кнопки подключаем к входам автомата с антидребезгом (falling edge — отпускание кнопки).
Алгоритм: читаем кнопку, ждём 80 мс, читаем снова. Если было не NONE, стало NONE — поднимаем соответствующее событие автомата.
int oldState = NONE;
static void raiseEvents() {
int buttonPressed = readButton();
delay(80);
oldState = buttonPressed;
if (oldState != NONE && readButton() == NONE) {
switch (oldState) {
case SELECT: stateMachine->getSCI_Button()->raise_mode(); break;
case LEFT: stateMachine->getSCI_Button()->raise_set(); break;
case DOWN: stateMachine->getSCI_Button()->raise_light(); break;
case UP: stateMachine->getSCI_Button()->raise_light_r(); break;
case RIGHT: stateMachine->getSCI_Button()->raise_onoff(); break;
}
}
}
Сборка главной программы
Три компонента: State Machine, Timer, Display Handler.
DigitalWatch* stateMachine = new DigitalWatch();
CPPTimerInterface* timer_sct = new CPPTimerInterface();
DisplayHandler* displayHandler = new DisplayHandler();
void setup() {
stateMachine->setSCI_Display_OCB(displayHandler);
stateMachine->setTimer(timer_sct);
stateMachine->init();
stateMachine->enter();
}
long current_time = 0, last_cycle_time = 0;
void loop() {
raiseEvents();
last_cycle_time = current_time;
current_time = millis();
timer_sct->updateActiveTimer(stateMachine, current_time - last_cycle_time);
stateMachine->runCycle();
}
Получение примера
В YAKINDU IDE: File → New → Example → YAKINDU Statechart Examples → Next → Arduino - Digital Watch (C++).
IDE скачать здесь. 30 дней триал, потом лицензия — бесплатно для некоммерческого использования.
Производственный процесс
- Проектирование конечных автоматов: от концепции к реализации
- Создание потрясающей системы Ambilight для монитора на Arduino
- Цифровые кости на Arduino: генератор случайных чисел с LCD-дисплеем и кнопкой
- Создание ультразвукового левитатора на Arduino: пошаговое руководство
- Умный вольтметр на Arduino и смартфоне — простое DIY-проект
- IoT-монитор пульса в реальном времени на Arduino и MAX30100
- Веб-сервер на Arduino Uno WiFi: управление LED через браузер
- Собираем свой Tamagotchi на Arduino: цифровой питомец своими руками
- DIY Arduino Smartwatch: самодельные умные часы в стиле Apple Watch
- Автоматизация игры «Динозавр» в Chrome на Arduino и LDR с Python