Как сделать часы на arduino. Большие настенные часы с автояркостью на Arduino

Как сделать часы на arduino. Большие настенные часы с автояркостью на Arduino

11.05.2019

Понадобилось как-то сделать большие настенные часы с автоматической яркостью.

Такие часы отлично подойдут для больших помещений, например холл офиса или большая квартира.

Сделать такие большие настенные часы не представляет серьёзных сложностей при помощи данной инструкции.


Для оценки размера часов можно принять тот факт, что один сегмент часов будет размером с бумагу формата А4, что позволит легко использовать рамки для фотографий соответствующего размера.

Шаг 1. Составные части больших настенных часов.

Провода, припой, паяльник, лента светодиодная Arduino Nano DC-DC преобразователь LM2596
4 метра светодиодной ленты WS2811 датчик света часы реального времени DS3231
микропереключатели

Что я использовал для этого проекта:

Шаг 8. Программируем часы.

Немного повозившись, мне удалось получить часы, полностью удовлетворяющие моим потребностям. Я уверен что вам удастся сделать лучше моего.

Код хорошо прокоментирован и вам не составит труда в нём разобраться, сообщения отладки так-же прокоментированы очень хорошо.

Если вам нужно поменять используемый цвет настенных часов вам необходимо поменять переменную на строчке 22 (int ledColor = 0x0000FF; // Color used (in hex) ). Вы можете найти список цветов и их коды в hex на странице: https://github.com/FastLED/FastLED/wiki/Pixel-refe…

Если у вас возникли проблемы при загрузке, используйте зеркало:http://bit.ly/1Qjtgg0

Мой итоговый скетч можно скачать .

Шаг 9. Делаем цифры используя полистирол.

Основание резака Рабочий орган резака Общий вид резака
Результат работы резака

Разрежьте каждый сегмент в шаблоне, напечатаетанного в начале.
Полистирол можно разрезать острым ножом, что довольно трудно, либо нехитрым приспособлением из нихромовой проволоки или гитарной струны и нескольких отрезков ОСБ-плиты.

Вы можете видеть, как это сделал я в изображениях выше.

Для того, чтобы запитать резак я использовал 12v блок питания.

В результате отрезаний должны получиться четыре сегмента для больших часов, один из которых показан на фото.

Шаг 10. Приклеиваем цифры и закрываем всё рассеивателем. Итоговые большие настенные часы.

Свечение днем Свечение ночью

После вырезания всех четырех цифр и точек настенных часов приклеиваем их всех на картон вместе со светодиодными лентами (для упрощения процесса я использовал двустороннюю клейкую ленту)

Для того, чтобы рассеять жесткий светодиодный свет я использовал два листа бумаги поверх полистироловых цифр. Для удобства и эстетичности я использовал бумагу размера А2, сложенную вдвое.

После завершения всех этих шагов я поместил получившуюся сборку больших настенных часов в соответствующую им большую фоторамку.

Эти часы получились очень эффектными и притягивающими взгляд. Я думаю что такие большие настенные часы отлично украсят множество помещений.

Вконтакте

Началось все с того, что волею случая я оказался владельцем текстового ЖК экрана BTHQ 22005VSS (2 строки по 20 знаков в каждой) и платы электронных часов DS1302. По правде говоря, в «Ардуиностроении» я делаю первые шаги, по этому, в приобретении данных деталей решающую роль сыграла демократичная цена и возможность быстрой доставки. Ведь, зачастую ждать, когда «девайс» прибудет из Поднебесной, обогнув почти «пол мира» некогда, да и просто не хочется.

Почему именно часы? В то время, когда вокруг продается масса разнообразных часов, цена самых простых из которых сравнима с пакетом сока. А дело все в том, что зачастую необходимо не просто знать точное время (и дату, что тоже иногда нужно) но еще и оперировать этим временем. Например - вести логи изменения температуры (влажности, давления, освещенности и т.п.) с указанием точного времени, когда эти изменения произошли. Вот тут-то ARDUINO оснащенный часами и окажет замечательную услугу. Да и кроме того, приятно, когда прибор ко всему прочему показывает еще и время. Ведь, даже работая на персональном компьютере мы изредка, да поглядываем в правый нижний угол, а вдруг уже пора на обед, или наступил конец рабочего дня, а может быть уже скоро рассвет?

Сердцем данного проекта послужил ARDUINO UNO, приобрести который довольно просто - это, конечно, если хочется купить что-то качественное и быстро. Можно, конечно найти и дешевле, но опять-же ждать, а ждать не хотелось. «Ардуинка» бодро моргала светодиодиком, выполняла все, что от неё требовалось давая простенькие сообщения через последовательный порт, в общем радовала. Но вернемся к часам. Проблемы начались, как всегда, неожиданно. Толковых статей и всего остального ни на экранчик, ни на часы «слёту» найти не удалось. На другие экраны - есть, на другие часы - сколько угодно, а вот на то, что в руках - почти ничего. Но, когда нет ничего - «почти» это тоже очень много.

Начнем с экрана. BTHQ 22005VSS оказался банальным ЖК экраном 20х2 (т.е. имеет 2 строки по 20 символов в каждой) вместо него вполне можно использовать, например экран - правда в нем «всего» 16 символов в каждой из строк, но для большинства проектов этого более, чем достаточно. Данный экран имеет 16-пиновый разъем, правда не однорядный, а двухрядный (2х8), если держать устройство экраном от себя, а разъемом справа, то первый пин будет нижним левым, второй нижним правым, третий над первым, четвертый над вторым, и т.д. Верхний левый (15) будет анод, верхний правый (16) - катод. Если есть знания английского и любознательность - можно почитать техническое описание . Если первого крайне мало, а любознательность гораздо слабее желания поэкспериментировать - вот, как подключал я:

Контакт экрана Контакт Ардуино Примечание
1 GND Это «минус», или «земля».
2 +5V
3 GND Если нужны яркие знаки.
4 4
5 GND Если только «писать».
6 5
7 -- Не использовал
8 -- Не использовал
9 -- Не использовал
10 -- Не использовал
11 10
12 11
13 12
14 13
А(15) +5V Я подключил через резистор 500 Ом
К(16) GND

В некоторых источниках «распиновка» со стороны Ардуино отличается, но ведь мне было удобнее так. Подключение часов также не вызвало проблем:

Часы DS1302 Ардуино Примечание
VCC +5V
GND GND Тут я подключал через резистор 10кОм.
CLK 0 Не путать с GND!!! Контакт также называется SCLK
DAT 1 Контакт также называется IO
RST 3 Контакт также называется СЕ

Подключать можно проводками, шлейфом, лично я собрал на макетной плате.

Проблемы начались, когда был загружен демоскетч и часы заработали. Правда показали они 2165 год, 45 месяц, 85 неделю... Наверное это по «уранскому» или «нептунскому» календарю… Но жить мне на Земле, а на Уран с Нептуном я пока не собираюсь. В общем надо что-то делать. Пайка в цепь GND->GND резистора 10кОм не помогла. Проблема оказалась в некорректной библиотеке. Сразу скажу, что корректную библиотеку можно взять . Это для часов. Экранчик успешно пользуется библиотекой из стандартного набора, которая зовется LiquidCrystal.h .

Проблема №2. Часы при каждом запуске начинают отсчет с того времени, которое «прошито» в программе. Есть сложное решение этой проблемы. Создать хеш, записать его в память часов, потом, при запуске считать его оттуда, сравнить… В общем для новичка в «Ардуиностроении» как то сложновато. Как оказалось есть и простое решение. точнее очень простое. А именно - прошить 2 раза. Первый раз - прошить с установкой даты и времени, второй раз прошить, предварительно «закомментировав» (поставив знак // в самом начале строки) строки с установкой этой самой даты.

Собственно говоря скетч:

// DS1302_LCD (C)2010 Henning Karlsen
// web: http://www.henningkarlsen.com/electronics
// A quick demo of how to use my DS1302-library to make a quick
// clock using a DS1302 and a 20x2 LCD.
// Соответствие пинов часов и экрана пинпм Ардуино.
// DS1302: CE pin -> Arduino Digital 3
// I/O pin -> Arduino Digital 1
// SCLK pin -> Arduino Digital 0
// LCD: DB7 -> Arduino Digital 13
// DB6 -> Arduino Digital 12
// DB5 -> Arduino Digital 11
// DB4 -> Arduino Digital 10
// E -> Arduino Digital 5
// RS -> Arduino Digital 4

#include // Подключение библиотеки экрана.
#include // Подключение библиотеки часов.

// Инициализация пинов часов
DS1302 rtc(3, 1, 0);
// Инициализация пинов экрана
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);

void setup()
{
// Запуск часов
rtc.halt(false);
rtc.writeProtect(false);

// Запуск экрана с указанием количества символов и строк
lcd.begin(20, 2);

// Три нижние строчки в первый раз раскомментированы, в них указываем текущую дату и время. Второй раз - закомментруем.
//rtc.setDOW(THURSDAY); // День недели, если пятница, то FRIDAY на русском не писать!
//rtc.setTime(11, 41, 0); // Часы, минуты, секунды 24-часовой формат.
//rtc.setDate(13, 6, 2013); // Дата. ЦИФРАМИ!!! Ноль перед одиночной цифрой можно не ставить!
}

void loop()
{
// Display time centered on the upper line
lcd.setCursor(6, 0); // Устанавливаем курсор для печати времени в верхней строчке
lcd.print(rtc.getTimeStr()); // Печатаем время

// Display abbreviated Day-of-Week in the lower left corner
lcd.setCursor(0, 1); // Устанавливаем курсор слева внизу для печати дня недели
lcd.print(rtc.getDOWStr(FORMAT_LONG)); // Печатаем день недели полностью, благо экран позволяет.

// Display date in the lower right corner
lcd.setCursor(9, 1); // Устанавливаем курсор для печати даты
lcd.print(rtc.getDateStr()); // Печатаем дату

// Wait one second before repeating
delay (1000); // Пауза 1 секунда и все по новой!
}

В данной статье мы рассмотрим, как сделать точные часы на базе Arduino или AVR-микроконтроллера микросхемы часов реального времени DS1307. Время будет выводиться на LCD дисплей.

Что необходимо

  • компьютер с установленной Arduino IDE;
  • микросхема DS1307 или модуль RTC на ее основе ;
  • комплектующие из списка элементов.

Вы можете заменить плату Arduino на контроллер Atmel, но убедитесь, что у него достаточно входных и выходных выводов и есть аппаратная реализация интерфейса I2C. Я использую ATMega168A-PU. Если вы будете использовать отдельный микроконтроллер, то вам понадобится программатор, например, AVR MKII ISP.

Предполагается, что читатель знаком с макетированием, программированием в Arduino IDE и имеет некоторые знания языка программирования C. Обе программы, приведенные ниже, не нуждаются в дополнительном разъяснении.

Введение

Как микроконтроллеры отслеживают время и дату? Обычный микроконтроллер обладает функцией таймера, который стартует от нуля при подаче напряжения питания, а затем начинает считать. В мире Arduino мы можем использовать функцию millis() , чтобы узнать, сколько прошло миллисекунд с того времени, когда было подано напряжение питания. Когда вы снимете и снова подадите питания, она начнет отсчет с самого начала. Это не очень удобно, когда дело доходит до работы с часами и датами.

Вот здесь и будет удобно использование микросхемы RTC (Real Time Clock, часов реального времени). Эта микросхема с батарейкой 3В или каким-либо другим источником питания следит за временем и датой. Часы/календарь обеспечивают информацию о секундах, минутах, часах, дне недели, дате, месяце и годе. Микросхема корректно работает с месяцами продолжительностью 30/31 день и с високосными годами. Связь осуществляется через шину I2C (шина I2C в данной статье не обсуждается).

Если напряжение на главной шине питания Vcc падает ниже напряжения на батарее Vbat, RTC автоматически переключается в режим низкого энергопотребления от резервной батареи. Резервная батарея - это обычно миниатюрная батарея (в виде «монетки», «таблетки») напряжением 3 вольта, подключенная между выводом 3 и корпусом. Таким образом, микросхема по-прежнему будет следить за временем и датой, и когда на основную схему будет подано питание, микроконтроллер получит текущие время и дату.

В этом проекте мы будем использовать DS1307. У этой микросхемы вывод 7 является выводом SQW/OUT (выходом прямоугольных импульсов). Вы можете использовать этот вывод для мигания светодиодом и оповещения микроконтроллера о необходимости фиксации времени. Мы будем делать и то, и другое. Ниже приведено объяснение работы с выводом SQW/OUT.

Для управления работой вывода SQW/OUT используется регистр управления DS1307.

Бит 7: управление выходом (OUT) Этот бит управляет выходным уровнем вывода SQW/OUT, когда выход прямоугольных импульсов выключен. Если SQWE = 0, логический уровень на выводе SQW/OUT равен 1, если OUT = 1, и 0, если OUT = 0. Первоначально обычно этот бит равен 0. Бит 4: включение прямоугольных импульсов (SQWE) Этот бит, когда установлен в логическую 1, включает выходной генератор. Частота прямоугольных импульсов зависит от значений битов RS0 и RS1. Когда частота прямоугольных импульсов настроена на значение 1 Гц, часовые регистры обновляются во время спада прямоугольного импульса. Первоначально обычно этот бит равен 0. Биты 1 и 0: выбор частоты (RS) Эти биты управляют частотой выходных прямоугольных импульсов, когда выход прямоугольных импульсов включен. Следующая таблица перечисляет частоты прямоугольных импульсов, которые могут быть выбраны с помощью данных битов. Первоначально обычно эти биты равны 1.

Данная таблица поможет вам с частотой:

Выбор частоты прямоугольных импульсов DS1307
Частота импульсов Бит 7 Бит 6 Бит 5 Бит 4 Бит 3 Бит 2 Бит 1 Бит 0
1 Гц 0 0 0 1 0 0 0 0
4,096 кГц 0 0 0 1 0 0 0 1
8,192 кГц 0 0 0 1 0 0 1 0
32,768 кГц 0 0 0 1 0 0 1 1

Если вы подключили светодиод и резистор к выводу 7 и хотите, чтобы светодиод мигал с частотой 1 Гц, то должны записать в регистр управления значение 0b00010000. Если вам нужны импульсы 4,096 кГц, то вы должны записать 0b000100001. В этом случае, чтобы увидеть импульсы вам понадобится осциллограф, так как светодиод будет мигать так быстро, что будет казаться, что он светится постоянно. Мы будем использовать импульсы с частотой 1 Гц.

Аппаратная часть

Ниже показана структурная схема того, что нам необходимо.

Мы нужны:

  • разъем ISP (In System Programming, внутрисхемное программирование) для прошивки микроконтроллера;
  • кнопки для установки времени и даты;
  • микроконтроллер для связи с RTC через шину I2C;
  • дисплей для отображения даты и времени.

Принципиальная схема:


Перечень элементов

Ниже приведен скриншот из Eagle:


Программное обеспечение

В этом руководстве мы будем использовать два различных скетча: один, который записывает время и дату в RTC, и один, который считывает время и дату из RTC. Мы сделали так потому, что так вы сможете получить более полное представление о том, что происходит. Мы будем использовать одну и ту же схему для обеих программ.

Сперва мы запишем время и дату в RTC, что аналогично установке времени на часах.

Мы используем две кнопки. Одну для увеличения часов, минут, даты, месяца, года и дня недели, а вторую для выбора между ними. Приложение не считывает состояния каких-либо критически важных датчиков, поэтому мы будем использовать прерывания для проверки, нажата ли кнопка, и обработки дребезга контактов.

Следующий код устанавливает значения и записывает их в RTC:

#include // Определение выводов LCD #define RS 9 #define E 10 #define D4 8 #define D5 7 #define D6 6 #define D7 5 LiquidCrystal lcd(RS, E, D4, D5, D6, D7); // Прерывание 0 – это вывод 4 микроконтроллера (цифровой вывод 2 Arduino) int btnSet = 0; // Прерывание 1 – это вывод 5 микроконтроллера (цифровой вывод 3 Arduino) int btnSel = 1; // Флаги прерываний volatile int togBtnSet = false; volatile int togBtnSel = false; volatile int counterVal = 0; // Переменные для отслеживания, где в "меню" мы находимся volatile int menuCounter = 0; // Массив значений volatile int menuValues; // 0=часы, 1=минуты, 2=день месяца, 3=месяц, 4=год, 5=день недели // Заголовки меню char* menuTitles = { "Set hour. ", "Set minute. ", "Set date. ", "Set month. ", "Set year. ", "Set day (1=mon)." }; // Массив дней недели char* days = { "NA", "Mon", "Tue", "Wed", "Thu", "Fre", "Sat", "Sun" }; void setup() { // Объявление прерываний, выполнение функций increaseValue/nextItem // по переднему фронту на btnXXX attachInterrupt(btnSet, increaseValue, RISING); attachInterrupt(btnSel, nextItem, RISING); Wire.begin(); lcd.begin(16,2); showWelcome(); } // Функция прерывания void increaseValue() { // Переменные static unsigned long lastInterruptTime = 0; // Создание метки времени unsigned long interruptTime = millis(); // Если timestamp - lastInterruptTime больше, чем 200 if (interruptTime - lastInterruptTime > 200) { togBtnSet = true; // Увеличить counterVal на 1 counterVal++; } // Установка lastInterruptTime равным метке времени // так мы знаем, что прошли дальше lastInterruptTime = interruptTime; } // Функция прерывания для следующего пункта меню void nextItem() { static unsigned long lastInterruptTime = 0; unsigned long interruptTime = millis(); if (interruptTime - lastInterruptTime > 200) { togBtnSel = true; // Увеличить счетчик меню, так мы переходим к следующему пункту меню menuCounter++; if (menuCounter > 6) menuCounter = 0; // Поместить counterVal в элемент массива счетчиков меню menuValues = counterVal; // Сбросить counterVal, сейчас мы начинаем с 0 для следующего пункта меню counterVal = 0; } lastInterruptTime = interruptTime; } // Функция преобразования десятичных чисел в двоично-десятичный код byte decToBCD(byte val) { return ((val/10*16) + (val%10)); } // Функция проверки, была ли нажата кнопки листания меню, // и обновления заголовка на дисплее. void checkCurrentMenuItem() { if (togBtnSel) { togBtnSel = false; lcd.setCursor(0,0); lcd.print(menuTitles); } } // Функция проверки, была ли нажата кнопка увеличения значения, // и обновления переменной в соответствующем элементе массива, // плюс вывод нового значения на дисплей. void checkAndUpdateValue() { // Проверить, если прерывание сработало = кнопка нажата if (togBtnSet) { // Обновить значение элемента массива с counterVal menuValues = counterVal; // Сбросить флаг прерывания togBtnSet = false; lcd.setCursor(7,1); // Напечатать новое значение lcd.print(menuValues); lcd.print(" "); } } // Короткое приветственное сообщение, теперь мы знаем, что всё нормально void showWelcome() { lcd.setCursor(2,0); lcd.print("Hello world."); lcd.setCursor(3,1); lcd.print("I"m alive."); delay(500); lcd.clear(); } // Запись данных в RTC void writeRTC() { Wire.beginTransmission(0x68); Wire.write(0); // начальный адрес Wire.write(0x00); // секунды Wire.write(decToBCD(menuValues)); // преобразовать минуты в BCD-код и записать Wire.write(decToBCD(menuValues)); // преобразовать часы в BCD-код и записать Wire.write(decToBCD(menuValues)); // преобразовать день недели в BCD-код и записать Wire.write(decToBCD(menuValues)); // преобразовать день месяца в BCD-код и записать Wire.write(decToBCD(menuValues)); // преобразовать месяц в BCD-код и записать Wire.write(decToBCD(menuValues)); // преобразовать год в BCD-код и записать Wire.write(0b00010000); // включить прямоугольные импульсы 1 Гц на выводе 7 Wire.endTransmission(); // закрыть передачу } // Показать время // Чтобы посмотреть, что RTC работает, вам необходимо посмотреть другую программу void showTime() { lcd.setCursor(0,0); lcd.print(" "); lcd.print(menuValues); lcd.print(":"); // часы lcd.print(menuValues); lcd.print(":"); lcd.print("00 "); // минуты lcd.setCursor(3,1); lcd.print(days); lcd.print(" "); // день недели lcd.print(menuValues); lcd.print("."); // дата lcd.print(menuValues); lcd.print("."); // месяц lcd.print(menuValues); lcd.print(" "); // год // вызов функции writeRTC writeRTC(); } void loop() { if (menuCounter < 6) { checkCurrentMenuItem(); checkAndUpdateValue(); } else { showTime(); } }

Эта программа начинается с короткого приветственного сообщения. Это сообщение говорит нам, что подано питание, LCD работает, и что программа запустилась. Так как скетч служит лишь для того, чтобы показать, как записать данные из Arduino в RTC DS1307, то в нем отсутствует вспомогательный функционал (проверка, попадают ли значения в допустимые диапазоны; зацикливание при нажимании на кнопку увеличения значения, то есть сброс на 0, когда значение, например, минут превысит 60, и т.д.)

// Включение заголовочных файлов #include #include // Определение выводов LCD #define RS 9 #define E 10 #define D4 8 #define D5 7 #define D6 6 #define D7 5 LiquidCrystal lcd(RS, E, D4, D5, D6, D7); // Вывод, который будет принимать импульсы от RTC volatile int clockPin = 0; // Переменные времени и даты byte second; byte minute; byte hour; byte day; byte date; byte month; byte year; // Массив дней недели char* days = { "NA", "Mon", "Tue", "Wed", "Thu", "Fre", "Sat", "Sun" }; // Функция, которая выполняется только при запуске void setup() { pinMode(clockPin, INPUT); pinMode(clockPin, LOW); Wire.begin(); lcd.begin(16,2); showWelcome(); } // Короткое приветственное сообщение, теперь мы знаем, что всё нормально void showWelcome() { lcd.setCursor(2,0); lcd.print("Hello world."); lcd.setCursor(3,1); lcd.print("I"m alive."); delay(500); lcd.clear(); } byte bcdToDec(byte val) { return ((val/16*10) + (val%16)); } // Это выполняется постоянно void loop() { // Если уровень на выводе clockPin высокий if (digitalRead(clockPin)) { // Начать передачу I2C, адрес 0x68 Wire.beginTransmission(0x68); // Начать с адреса 0 Wire.write(0); // Закрыть передачу Wire.endTransmission(); // Начать чтение 7 двоичных данных от 0x68 Wire.requestFrom(0x68, 7); second = bcdToDec(Wire.read()); minute = bcdToDec(Wire.read()); hour = bcdToDec(Wire.read()); day = bcdToDec(Wire.read()); date = bcdToDec(Wire.read()); month = bcdToDec(Wire.read()); year = bcdToDec(Wire.read()); // Форматирование и отображение времени lcd.setCursor(4,0); if (hour < 10) lcd.print("0"); lcd.print(hour); lcd.print(":"); if (minute < 10) lcd.print("0"); lcd.print(minute); lcd.print(":"); if (second < 10) lcd.print("0"); lcd.print(second); lcd.setCursor(2,1); // Форматирование и отображение даты lcd.print(days); lcd.print(" "); if (date < 10) lcd.print("0"); lcd.print(date); lcd.print("."); if (month < 10) lcd.print("0"); lcd.print(month); lcd.print("."); lcd.print(year); } }

Заключение

В данной статье мы рассмотрели микросхему DS1307 от Maxim Integrated и написали две демонстрационные программы: одну для установки времени и даты и вторую для чтения времени и даты. Для проверки нажатия кнопок мы использовали прерывания, в которых также избавлялись от влияния дребезга контактов.

Фото и видео

Установка времени

Считывание времени

В данной статье рассматривается пример создания часов рального времени. На индикатор будет выводиться точное время, а двоеточие на нем будет моргать раз в секунду. Точное время будет автоматически устанавливаться во вермя компиляции прошивки.

Описание компонентов

Часы реального времени

Мы используем модуль с часами реального времени от Seeed Studio. Они построены на базе микросхемы DS1307 от Maxim Integrated. Из элементов обвязки она требует три резистора, часовой кварц и батарейку, которые уже имеются на данном модуле. Модуль обладает следующими свойствами:

    Подсчет времени (секунды, минуты, часы), даты (год, месяц, число), дня недели

    Двухпроводной интерфейс I²C

Суть часов реального времени в том, что при наличии батарейки, они могут идти даже если основное устройство обесточено. Мы с такими часами сталкиваемся постоянно в ноутбуках или цифровых фотоаппаратах. Если достать из этих устройств аккумулятор, а через некоторое время вернуть их обратно, то время не сбросится. В этом заслуга часов реального времени, Real Time Clock (RTC).

Все необходимые библиотеки можно скачать с официального сайта .

Индикатор

Мы используем четырёхразрядный индикатор от Seeed Studio. Основное в индикаторе - микросхема TM1637, представляющая собой драйвер для отдельных 7-сегментных разрядов. В данном модуле используется 4 разряда. Модуль обладает следующими свойствами:

    8 градаций яркости

    Двухпроводной интерфейс работы (CLK, DIO)

Данный модуль мы используем для показа времени: часов и минут. Удобство модуля в том, что подключается он всего по двум проводам и не требует программной реализации динамической индикации, поскольку все уже реализовано внутри модуля.

Динамическая индикация - это процесс, при котором индикаторы в нашем модуле загораются последовательно. Но мерцания мы не видим, поскольку человеческой глаз обладает большой инертностью. Данный метод позволяет очень хорошо экономить количество соединений между индикаторами и контроллером:

    Статическая индикация: 4 цифры × 7 сегментов = 28 соединений.

    Динамическая индикация: 7 сегментов + 4 общих анода или катода = 11 соединений.

    Микросхема TM1637: 2 соединения.

Выгода очевидна.

Подключение

Модуль часов реального времени необходимо подключить к выводам SCL/SDA, относящимся к шине I²C. Также необходимо подключить линии питания (Vcc) и земли (GND).

Линии SDA/SCL имеют собственные отдельные пины на Arduino, однако внутри они так или иначе подключены к пинам общего назначения. Если рассмотреть Arduino Uno, линии SDA соответствует пин A4, а SCL - A5.

В комплекте с модулем поставляется шлейф с мама-контактами, которые удобнее подключать к Troyka Shield. Однако отдельные пины SDA и SCL на ней не выведены, поэтому мы осуществили подключение прямо через пины A5 и A4.

В плане подключения индикатора - все гораздо проще. Выводы CLK и DIO можно подключить к любым цифровым выводам. В данном случае используются 12-й и 11-й выводы соответственно.

Написание прошивки

Функция setup должна инициализировать часы реального времени и индикатор, а также записывать время компиляции во внутреннюю память часов реального времени. Все действие, а точнее, чтение времени из RTC и вывод его на индикатор, будет производиться в функции loop .

Код для этого выглядит следующим образом:

rtc.ino #include #include //Классы TM1637 и DS1307 объявлены именно в них clock ; void setup() { clock .begin () ; clock clock .setTime () ; } void loop() { int8_t timeDisp[ 4 ] ; //Запрашиваем время с часов ] = clock .minute % 10 ; display.point (clock .second % 2 ? POINT_ON : POINT_OFF) ; } //Содержимое функции объяснено ниже char getInt(const char * string, int startIndex) { return int (string[ startIndex] - "0" ) * 10 + int (string[ startIndex+ 1 ] ) - "0" ; }

Теперь загружаем этот код в среду разработки, компилируем и заливаем. Смотрим на дисплей - бинго! Время на дисплее - время компиляции.

Объяснение функции getInt

Для начала необходимо понять, откуда же в массиве compileTime появляется время. Оно появляется в этой строчке:

unsigned char compileTime = __TIME__;

Компилятор вместо __TIME__ подставляет строку, содержащую время компиляции в виде __TIME__ = "hh:mm:ss" , где hh - часы, mm - минуты, ss - секунды.

Вернемся к коду, который необходимо объяснить:

char getInt(const char * string, int startIndex) { return int (string[ startIndex] - "0" ) * 10 + int (string[ startIndex+ 1 ] ) - "0" ; }

В массиве string , передаваемом в качестве параметра в функцию getInt , мы получаем символ с индексом startIndex и следующий за ним, чтобы в итоге получить двухзначное целое число. Однако, изначально это не число, а пара символов . Чтобы получить число по символу, нам необходимо вычесть из этого символа символ нуля ("0 "): ведь в таблице ASCII все символы цифр идут одна за другой, начиная с символа нуля. Поэтому код int(string) - "0") , дословно, делает следующее: «Берем символ номер startIndex , вычитаем из него символ нуля и переводим в целочисленный тип».

Проблемы

Да, этот код рабочий, и часы будут идти. Однако, если отключить питание, а через несколько минут включить, то после включения время время вновь станет тем, которое было при компиляции.

Это происходит потому что после включения питания, вновь исполняется код, находящийся в функции setup . А он записывает в часы реального времени старое значение времени.

Чтобы этого избежать, нам необходимо еще чуть-чуть модифицировать код. Каждый раз в функции setup будет происходить подсчет «хэша» времени компиляции - будет рассчитываться количество секунд, прошедшее с 00:00:00 до времени компиляции. И этот хэш будет сравниваться с хэшем в EEPROM. Напомним EEPROM - память, которая не обнуляется при отключении питания.

Если значения посчитанного и сохранённого ранее хэша совпадают, то это значит, что перезаписывать время в модуль часов нет необходимости: это уже было сделано. А вот если эта проверка не проходит, то происходит перезапись времени в RTC.

Для записи/чтения числа типа unsigned int в/из EEPROM написаны две дополнительные функции EEPROMWriteInt и EEPROMReadInt . Они добавлены потому что функции EEPROM.read и EEPROM.write могуть читать и писать только данные типа char .

rtc-eeprom.ino #include #include #include "TM1637.h" #include "DS1307.h" //Массив, содержащий время компиляции char compileTime = __TIME__; //Номера пинов Arduino, к которым подключается индикатор #define DISPLAY_CLK_PIN 12 #define DISPLAY_DIO_PIN 13 //Для работы с микросхемой часов и индикатором мы используем библиотеки TM1637 display(DISPLAY_CLK_PIN, DISPLAY_DIO_PIN) ; DS1307 clock ; void setup() { //Включаем и настраиваем индикатор display.set () ; display.init () ; //Запускаем часы реального времени clock .begin () ; //Получаем число из строки, зная номер первого символа byte hour = getInt(compileTime, 0 ) ; byte minute = getInt(compileTime, 3 ) ; byte second = getInt(compileTime, 6 ) ; //Импровизированный хэш времени //Содержит в себе количество секунд с начала дня unsigned int hash = hour * 60 * 60 + minute * 60 + second; //Проверяем несовпадение нового хэша с хэшем в EEPROM if (EEPROMReadInt(0 ) != hash) { //Сохраняем новый хэш EEPROMWriteInt(0 , hash) ; //Готовим для записи в RTC часы, минуты, секунды clock .fillByHMS (hour, minute, second) ; //Записываем эти данные во внутреннюю память часов. //С этого момента они начинают считать нужное для нас время clock .setTime () ; } } void loop() { //Значения для отображения на каждом из 4 разрядов int8_t timeDisp[ 4 ] ; //Запрашиваем время с часов ] = clock .minute % 10 ; //... а затем выводим его на экран display.display (timeDisp) ; //у нас нет отдельных разрядов для секунд, поэтому //будем включать и выключать двоеточие каждую секунду display.point (clock .second % 2 ? POINT_ON : POINT_OFF) ; } char getInt(const char * string, int startIndex) { return int (string[ startIndex] - "0" ) * 10 + int (string[ startIndex+ 1 ] ) - "0" ; } //Запись двухбайтового числа в память void EEPROMWriteInt(int address, int value) { EEPROM.write (address, lowByte(value) ) ; EEPROM.write (address + 1 , highByte(value) ) ; } //Чтение числа из памяти unsigned int EEPROMReadInt(int address) { byte lowByte = EEPROM.read (address) ; byte highByte = EEPROM.read (address + 1 ) ; return (highByte << 8 ) | lowByte; }

Заключение

В данной статье был показан пример работы с микросхемой часов реального времени RTC DS1307 и микросхемой-драйвером индикатора TM1637, также мы научились получать дату и время на этапе компиляции. Теперь, если выставить нужное время на часах, а потом отключить питание хоть на несколько часов, то после включения время вновь будет точным. Проверено!

«. Знакомимся с модулем часов реального времени DS3231. В статье видео-инструкция, листинги программ, назначение и способы подключения к Arduino модулей из семейства DS.

Модуль часов реального времени DS3231

Что такое модуль часов реального времени DS3231?

Модуль часов реального времени - это электронная схема, предназначенная для учета хронометрических данных (текущее время, дата, день недели и др.), представляет собой систему из автономного источника питания и учитывающего устройства.

Модуль DS3231 по сути представляет из себя обыкновенные часы. В платах Arduino уже есть встроенный датчик времени Millis , однако он работает только при поданном питании на плату. При отключении и дальнейшем включении Arduino отсчет времени Millis сбросится до нуля. А DS3231 имеет на борту батарейку, которая даже при отключенной плате Arduino продолжает «питать» модуль, позволяя ему измерять время.

Модуль можно использовать в качестве часов или будильника, построенных на базе плат Arduino. Или же в качестве оповещения для различных систем, к примеру в «Умном доме».

Технические характеристики DS3231:

  • модуль производит подсчет часов, минут, секунд, дат, месяцев, лет (високосные года учитываются до 2100 года);
  • для подключения к различным устройствам, часы подключаются по I2C интерфейсу.

32К — Выход, предназначенный для подачи внешнего питания >12В.

SQW — Программируемый выход Square-Wave сигнала.

SCL – Через этот пин по интерфейсу I2C происходит обмен данными с часами.

SDA – Через этот пин передаются данные с часов.

VCC – Питание часов реального времени, нужно 5 вольт. Если на этот пин не поступает напряжение, часы переходят в спящий режим.

GND — Земля.

Схема подключения часов реального времени DS3231 и простейшая программа

Пины SDA и SCL на разных платах Arduino:

SDA SCL
UNO A4 A5
Mini A4 A5
Nano A4 A5
Mega2560 20 21
Leonardo 2 3

Подключим модуль часов реального времени к Arduino UNO. SDA — пин A4, SCL — пин A5.

Для работы модели подойдет следующая программа (программу вы можете просто скопировать в Arduino IDE):

#include

void setup() {
delay(300);
Serial.begin(9600);
time.begin();
}
void loop(){



}
}

В данном скетче просто идет отсчет времени.

В первую очередь в сктече подключение библиотеки iarduino_RTC.h.

Там же укажите точное название своего модуля для корректной работы с ним.

В итоге получаем вывод времени с модуля DS3231 в монитор порта. Идет вывод часов, минут, секунд.

В следующем скетче добавим функцию settime , позволяющую установить начальное время отсчета.

#include
iarduino_RTC time(RTC_DS3231);
void setup() {
delay(300);
Serial.begin(9600);
time.begin();
time.settime(0,0,18,24,04,17,1); // 0 сек, 0 мин, 18 час, 24, апреля, 2017 года, понедельник
}
void loop(){
if(millis()%1000==0){ // если прошла 1 секунда
Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время
delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
}
}

В примере время начинает отсчитываться с 0 сек, 0 мин, 18 час, 24, апреля, 2017 года, понедельник.

Посты по урокам:

  1. Первый урок: .
  2. Второй урок: .
  3. Третий урок: .
  4. Четвертый урок: .
  5. Пятый урок: .
  6. Шестой урок: .
  7. Седьмой урок: .
  8. Восьмой урок: .
  9. Девятый урок:


© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows