В данной статье обсудим план действий при созданий часов на плате Arduino и создадим свои собственные часы, используя модифицированный стандартный код-заготовку. Отметим, что проект реализовывался с использованием микроконтроллера, основанного на Arduino UNO. Данный проект реализовывался с использованием семисегментного индикатора ТМ1637, модулем часов реального времени DS3231 и возможностью установки времени кнопками.
Программная часть
#include <Wire.h>
#include «TM1637.h» // в гугл введите запрос DigitalTube library
/*
* В файл TM1637.h требуется добавить следующее:
static int8_t TubeTab[] = {0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71, 0x63, 0x00};//0~9,A,b,C,d,E,F
*/
// дефайны отвечают за кнопки
#define keyP 4
#define keySET 3
#define keyM 2
TM1637 tm1637(6, 7);
#define DS3231_I2C_ADDRESS 0x68
int8_t decToBcd(byte val){
return ( (val/10*16) + (val%10) );
}
int8_t bcdToDec(byte val){
return ( (val/16*10) + (val%16) );
}
void setDateDs3231(int8_t second, // 0-59 секунд
int8_t minute, // 0-59 минут
int8_t hour, // 1-23 час
int8_t dayOfWeek, // 1-7 день // в перспективе можно доделать и подключить экран для показа даты
int8_t dayOfMonth, // 1-28/29/30/31 месяц
int8_t month, // 1-12
int8_t year) // 0-99
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs3231(byte *second,
int8_t *minute,
int8_t *hour,
int8_t *dayOfWeek,
int8_t *dayOfMonth,
int8_t *month,
int8_t *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
//////
void setup() {
// Serial.begin(9600);
Wire.begin();
pinMode(keyP, INPUT_PULLUP);
pinMode(keySET, INPUT_PULLUP);
pinMode(keyM, INPUT_PULLUP);
tm1637.init();
tm1637.set(0);
tm1637.point(1);
analogReference(INTERNAL);
}
void loop(){
// читаем время из модуля
int8_t second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
int8_t TimeDisp[4]; // отправленный на экран массив
TimeDisp[0] = hour / 10; // текущее время в массив
TimeDisp[1] = hour % 10;
TimeDisp[2] = minute / 10;
TimeDisp[3] = minute % 10;
// обработка кнопок
/// Установка времени
if (!digitalRead(keySET)){ // Если надавили сет
delay(200); // противодребезговая защита
second = 0; // сброс секундомера
tm1637.point(1); // включаем двоеточие между часами и минутами
do{ /// Крутим цикл! /// часы
if (!digitalRead(keyP)){ // если в цикле надавили на «+»
hour++; // прибавляем единицу к часу
if (hour > 23) hour = 0; // если вылезли за границы присваиваем 0
setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль
delay(200);
}
if (!digitalRead(keyM)){ // если на «-«
hour—; // убавляем единицу
if (hour < 0) hour = 23; // если вылезли за границы
setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль
delay(200);
}
TimeDisp[0] = hour / 10; // в цикле также показываем что получилось
TimeDisp[1] = hour % 10;
TimeDisp[2] = 17; // 17 это 0xff, выключение
TimeDisp[3] = 17;
tm1637.display(TimeDisp); // отправляем массив на экран
}while(digitalRead(keySET)); // крутимся пока не надавили сет
delay(500); // антидребезг
do{ // снова крутимся, но уже для минут.
if (!digitalRead(keyP)){ // также смотрим не нажато ли «+»
minute++; // прибавляем минуту
if (minute > 59) minute = 0; // проверяем
setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
delay(200);
}
if (!digitalRead(keyM)){ // также смотрим на «-«
minute—;
if (minute < 0) minute = 59;
setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
delay(200);
}
TimeDisp[0] = 17;
TimeDisp[1] = 17;
TimeDisp[2] = minute / 10;
TimeDisp[3] = minute % 10;
tm1637.display(TimeDisp); // отправляем массив на экран
}while(digitalRead(keySET)); // крутимся пока не надавили сет
delay(200); // задумываемся перед выходом
}
// таймер на RTC )
static byte oldSec;
if (oldSec != second){ // true каждую секунду.
oldSec = second; // сохраняем прошедшую
// мигание точкой
static bool point;
point = !point;
tm1637.point(point);
// Устанавливаем яркость LED
byte brightness = map(analogRead(A1), 0, 1023, 0, 7); // Читаем вход и мапим, приделы подкорректировать !!!
tm1637.set(brightness); // Пишем в дисплей
} ///
// Отображение температуры
// if (second == 15 || second == 16 || second == 17 || !digitalRead(keyP)){ // Отображаем каждые 3 секунды или кнопкой
if (!digitalRead(keyP)){ // Отображаем при нажатой кнопки «+»
tm1637.point(0); // Выключаем двоеточие
/// Получение температуры !!!
// int8_t tempC = (analogRead(A0) / 9.31; // Для LM35 и атмеги328 (опорное 1,1)
int8_t tempC = (((analogRead(A0) * 2.54) / 1024.0) — 0.5) * 100; // для TMP36 и атмеги8 (опорное 2,56)
// int8_t tempC = (((analogRead(A0) * 1.1) / 1024.0) — 0.5) * 100; // для TMP36 и атмеги328 (опорное 1,1)
// int8_t tempC = (analogRead(A0)/1024.0)*5.0*1000/10; // для 5 вольт LM35.
TimeDisp[0] = tempC / 10; // Заполняем массив
TimeDisp[1] = tempC % 10;
TimeDisp[2] = 16; // градус (нужно добавить «0x63» в «TubeTab[]» в «TM1637.h»)
TimeDisp[3] = 12; // C
delay(200);
}
// отправляем массив на экран
tm1637.display(TimeDisp);
}
Отметим, что программа предполагает создание часов со временем, а не с датой, но при добавлении второго экрана можно реализовать вывод даты.
Установка времени осуществляется кнопками, притянутые к массе. Первая кнопка переключает нас на настройку чаcов, вторая-на минуты, а третьей осуществляем непосредственно настройку по единице .
Модуль часов подключаем непосредственно к Ардуино, однако нога SQW подключается на прерывание. Принцип работы:
На выходе SCL генерируется сигнал с периодом в одну секунду, после чего дергает прерывание и мигает двоеточие. Если его отключить, точка остановиться.
К 6 и 7 ноге подключен индикатор, к 3, 4, 5-кнопки. Кнопки можно менять так, как вам хочется. Не советую экспериментировать с дальнейшей частью кода, поскольку есть риск не восстановить работоспособность из-за сложности программы.
Однако есть и более простой способ реализовать часы
Синхронизация часов происходит при подключении их к ПК, ПК передает время на контроллер во время перепрошивки.
Для данного способа советуем использовать Shot Shield похожий на этот:
Вставьте Quad Display в разъёмы E и F. Пин CS подключите к пину номер 10 Arduino. Прошейте плату следующим программным кодом:
#include <QuadDisplay2.h>
// создаём объект класса QuadDisplay и передаём номер пина CS
QuadDisplay qd(10);
// создаем объекты класса bute для хранения текущего значения Часов, Минут, Секунд
int hours = 0;
int minutes = 0;
int seconds = 0;
// создаем объект класса long для хранения счетчика
long lastTime = 0;
void setup() {
// инициализация дисплея
qd.begin();
// инициализируем время
setTime(__TIMESTAMP__);
}
void loop() {
// как только разница между текущим временем и временем записанным в lastTime становится больше 1000 миллисекунд…
while(millis()-lastTime > 1000) {
//…обновляем lastTime и добавляем к счетчику Секунд +1
lastTime = millis();
seconds++;
// как только счетчик секунд достигнет 60, обнуляем его и добавляем к счетчику Минут +1…
if (seconds >= 60) {
seconds = 0;
minutes++;
}
// …тоже самое для Часов…
if (minutes >= 60) {
minutes = 0;
hours++;
}
// … и обнуляем счетчик Часов в конце дня
if (hours >= 24) {
hours = 0;
}
}
// выводим время на дисплей
qd.displayScore(hours, minutes, true);
}
// функция записи текущего времени в переменные
void setTime(const char* compileTimeStamp)
{
hours = ((compileTimeStamp[11] — ‘0’) * 10
+ (compileTimeStamp[12] — ‘0’));
minutes = ((compileTimeStamp[14] — ‘0’) * 10
+ (compileTimeStamp[15] — ‘0’));
seconds = ((compileTimeStamp[17] — ‘0’) * 10
+ (compileTimeStamp[18] — ‘0’));
}
В данной статье мы разобрали способы реализации часов с возможностью управления и без возможности управлять и изменять время, однако обладающим синхронизацией.