Часы на Arduino без использования модуля RTC. Большие настенные часы с автояркостью на Arduino

Итак, часы реального времени. Эта полезная штучка решает большинство полезных задач, связанных со временем. Допустим управление поливом в 5 часов утра на даче. Или включение и выключение освещения в определённый момент. По дате можно запускать отопление в каком-нибудь доме. Вещь достаточно интересная и полезная. А конкретно? Мы с вами рассмотрим часы реального времени DS1302 для популярной платформы Arduino.

Из этой статьи вы узнаете:

Доброго времени суток, уважаемые читатели блока kip-world! Как ваши дела? Напишите в комментариях, вы увлекаетесь робототехникой? Что значит для вас эта тема?

У меня ни на минуту не покидает мысль об этом. Я сплю и вижу, когда мы наконец — то придём к тому, что каждый сможет позволить себе купить персонального робота — помощника. Не важно, чем он будет заниматься, уборкой мусора, стрижкой газонов, мойкой автомобиля.

Я просто представляю себе, насколько сложные алгоритмы они должны содержать в своих «мозгах».

Ведь мы придём к тому, что мы будем так же прошивать ПО, как на персональных компах. Так же скачивать прикладные программы. Пришивать руки, ноги, менять клешни, манипуляторы.

Посмотрите фильмы «Я-робот», «Искусственный интеллект», «Звёздных воинов».

Японцы уже давно внедряют свои разработки. Чем мы хуже?? У нас очень слабая популярность. Я знаю немногих разработчиков. По пальцам пересчитать. Мы занимаемся другим. Мы перекупщики. Просто покупаем готовые наборчики, роботов — игрушек и всякую дребедень.

Почему не разрабатываем вот это:

Или вот это:

Я закончил свои размышления вслух. Давайте мы с вами поговорим о подключении Таймера часов реального времени DS1302 к Arduino.

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

Контроллер Arduino не имеет своих собственных часов. Поэтому в случае необходимости нужно дополнять специальной микросхемой DS1302.

По питанию эти платы могут использовать свой элемент питания, или запитываться непосредственно с платы Arduino.

Таблица распиновки:

Схема подключения c Arduino UNO:


Способ программирования Arduino для работы с DS1302

Обязательно нужно скачать действующую библиотеку из надёжных источников.

Библиотека позволяет считывать и записывать параметры реального времени. Небольшое описание я привожу ниже:

#include // Подключаем библиотеку.
iarduino_RTC ОБЪЕКТ (НАЗВАНИЕ [, ВЫВОД_RST [, ВЫВОД_CLK [, ВЫВОД_DAT ]]]); // Создаём объект.

Функция begin (); // Инициализация работы RTC модуля.

Функция settime (СЕК [, МИН [, ЧАС [, ДЕНЬ [, МЕС [, ГОД [, ДН ]]]]]]); // Установка времени.

Функция gettime ([ СТРОКА ]); // Чтение времени.

функция blinktime (ПАРАМЕТР [ ЧАСТОТА ] ); // Заставляет функцию gettime «мигать» указанным параметром времени.

функция period (МИНУТЫ ); // Указывает минимальный период обращения к модулю в минутах.

Переменная seconds // Возвращает секунды от 0 до 59.

Переменная minutes // Возвращает минуты от 0 до 59.

Переменная hours // Возвращает часы от 1 до 12.

Переменная Hours // Возвращает часы от 0 до 23.

Переменная midday // Возвращает полдень 0 или 1 (0-am, 1-pm).

Переменная day // Возвращает день месяца от 1 до 31.

Переменная weekday // Возвращает день недели от 0 до 6 (0-воскресенье, 6-суббота).

Переменная month // Возвращает месяц от 1 до 12.

Переменная year // Возвращает год от 0 до 99.

Пишем простенькую программу. Установка текущего времени в RTC модуль (DS1302):

Arduino

#include iarduino_RTC time(RTC_DS1302,6,7,8); void setup() { delay(300); Serial.begin(9600); time.begin(); time.settime(0,51,21,27,10,15,2); // 0 сек, 51 мин, 21 час, 27, октября, 2015 года, вторник } void loop(){ if(millis()%1000==0){ // если прошла 1 секунда Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс } }

#include

iarduino _ RTCtime (RTC_DS1302 , 6 , 7 , 8 ) ;

void setup () {

delay (300 ) ;

Serial . begin (9600 ) ;

time . begin () ;

time . settime (0 , 51 , 21 , 27 , 10 , 15 , 2 ) ; // 0 сек, 51 мин, 21 час, 27, октября, 2015 года, вторник

void loop () {

if (millis () % 1000 == 0 ) { // если прошла 1 секунда

Serial . println (time . gettime ("d-m-Y, H:i:s, D" ) ) ; // выводим время

delay (1 ) ; // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс

Считываем текущее время с RTC модуля (DS1302) и выводим в "Последовательный порт" :

#include iarduino_RTC time(RTC_DS1302,6,7,8); void setup() { delay(300); Serial.begin(9600); time.begin(); } void loop(){ if(millis()%1000==0){ // если прошла 1 секунда Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 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 и написали две демонстрационные программы: одну для установки времени и даты и вторую для чтения времени и даты. Для проверки нажатия кнопок мы использовали прерывания, в которых также избавлялись от влияния дребезга контактов.

Фото и видео

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

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

Во многих проектах Ардуино требуется отслеживать и фиксировать время наступления тех или иных событий. Модуль часов реального времени, оснащенный дополнительной батарей, позволяет хранить текущую дату, не завися от наличия питания на самом устройстве. В этой статье мы поговорим о наиболее часто встречающихся модулях RTC DS1307, DS1302, DS3231, которые можно использовать с платой Arduino.

Модуль часов представляет собой небольшую плату, содержащей, как правило, одну из микросхем DS1307, DS1302, DS3231.Кроме этого, на плате практически можно найти механизм установки батарейки питания. Такие платы часто применяется для учета времени, даты, дня недели и других хронометрических параметров. Модули работают от автономного питания – батареек, аккумуляторов, и продолжают проводить отсчет, даже если на Ардуино отключилось питание. Наиболее распространенными моделями часов являются DS1302, DS1307, DS3231. Они основаны на подключаемом к Arduino модуле RTC (часы реального времени).

Часы ведут отсчет в единицах, которые удобны обычному человеку – минуты, часы, дни недели и другие, в отличие от обычных счетчиков и тактовых генераторов, которые считывают «тики». В Ардуино имеется специальная функция millis(), которая также может считывать различные временные интервалы. Но основным недостатком этой функции является сбрасывание в ноль при включении таймера. С ее помощью можно считать только время, установить дату или день недели невозможно. Для решения этой проблемы и используются модули часов реального времени.

Электронная схема включает в себя микросхему, источник питания, кварцевый резонатор и резисторы. Кварцевый резонатор работает на частоте 32768 Гц, которая является удобной для обычного двоичного счетчика. В схеме DS3231 имеется встроенный кварц и термостабилизация, которые позволяют получить значения высокой точности.

Сравнение популярных модулей RTC DS1302, DS1307, DS3231

В этой таблице мы привели список наиболее популярных модулей и их основные характеристики.

Название Частота Точность Поддерживаемые протоколы
DS1307 1 Гц, 4.096 кГц, 8.192 кГц, 32.768 кГц Зависит от кварца – обычно значение достигает 2,5 секунды в сутки, добиться точности выше 1 секунды в сутки невозможно. Также точность зависит от температуры. I2C
DS1302 32.768 кГц 5 секунд в сутки I2C, SPI
DS3231 Два выхода – первый на 32.768 кГц, второй – программируемый от 1 Гц до 8.192 кГц ±2 ppm при температурах от 0С до 40С.

±3,5 ppm при температурах от -40С до 85С.

Точность измерения температуры – ±3С

I2C

Модуль DS1307

DS1307 – это модуль, который используется для отсчета времени. Он собран на основе микросхемы DS1307ZN, питание поступает от литиевой батарейки для реализации автономной работы в течение длительного промежутка времени. Батарея на плате крепится на обратной стороне. На модуле имеется микросхема AT24C32 – это энергонезависимая память EEPROM на 32 Кбайт. Обе микросхемы связаны между собой шиной I2C. DS1307 обладает низким энергопотреблением и содержит часы и календарь по 2100 год.

Модуль обладает следующими параметрами:

  • Питание – 5В;
  • Диапазон рабочих температур от -40С до 85С;
  • 56 байт памяти;
  • Литиевая батарейка LIR2032;
  • Реализует 12-ти и 24-х часовые режимы;
  • Поддержка интерфейса I2C.

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

Взаимодействие с другими устройствами и обмен с ними информацией производится с помощью интерфейса I2C с контактов SCL и SDA. В схеме установлены резисторы, которые позволяют обеспечивать необходимый уровень сигнала. Также на плате имеется специальное место для крепления датчика температуры DS18B20.Контакты распределены в 2 группы, шаг 2,54 мм. В первой группе контактов находятся следующие выводы:

  • DS – вывод для датчика DS18B20;
  • SCL – линия тактирования;
  • SDA – линия данных;
  • VCC – 5В;

Во второй группе контактов находятся:

  • SQ – 1 МГц;
  • BAT – вход для литиевой батареи.

Для подключения к плате Ардуино нужны сама плата (в данном случае рассматривается Arduino Uno), модуль часов реального времени RTC DS1307, провода и USB кабель.

Чтобы подключить контроллер к Ардуино, используются 4 пина – VCC, земля, SCL, SDA.. VCC с часов подключается к 5В на Ардуино, земля с часов – к земле с Ардуино, SDA – А4, SCL – А5.

Для начала работы с модулем часов нужно установить библиотеки DS1307RTC, TimeLib и Wire. Можно использовать для работы и RTCLib.

Проверка RTC модуля

При запуске первого кода программа будет считывать данные с модуля раз в секунду. Сначала можно посмотреть, как поведет себя программа, если достать из модуля батарейку и заменить на другую, пока плата Ардуино не присоединена к компьютеру. Нужно подождать несколько секунд и вытащить батарею, в итоге часы перезагрузятся. Затем нужно выбрать пример в меню Examples→RTClib→ds1307. Важно правильно поставить скорость передачи на 57600 bps.

При открытии окна серийного монитора должны появиться следующие строки:

Будет показывать время 0:0:0. Это связано с тем, что в часах пропадает питание, и отсчет времени прекратится. По этой причине нельзя вытаскивать батарею во время работы модуля.

Чтобы провести настройку времени на модуле, нужно в скетче найти строку

RTC.adjust(DateTime(__DATE__, __TIME__));

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

Настройка произведена корректно и дополнительно перенастраивать часы реального времени не придется.

Считывание времени. Как только модуль настроен, можно отправлять запросы на получение времени. Для этого используется функция now(), возвращающая объект DateTime, который содержит информацию о времени и дате. Существует ряд библиотек, которые используются для считывания времени. Например, RTC.year() и RTC.hour() – они отдельно получают информацию о годе и часе. При работе с ними может возникнуть проблема: например, запрос на вывод времени будет сделан в 1:19:59. Прежде чем показать время 1:20:00, часы выведут время 1:19:00, то есть, по сути, будет потеряна одна минута. Поэтому эти библиотеки целесообразно использовать в случаях, когда считывание происходит нечасто – раз в несколько дней. Существуют и другие функции для вызова времени, но если нужно уменьшить или избежать погрешностей, лучше использовать now() и из нее уже вытаскивать необходимые показания.

Пример проекта с i2C модулем часов и дисплеем

Проект представляет собой обычные часы, на индикатор будет выведено точное время, а двоеточие между цифрами будет мигать с интервалом раз в одну секунду. Для реализации проекта потребуются плата Arduino Uno, цифровой индикатор, часы реального времени (в данном случае вышеописанный модуль ds1307), шилд для подключения (в данном случае используется Troyka Shield), батарейка для часов и провода.

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

Модуль часов подключается к контактам SCL/SDA, которые относятся к шине I2C. Также нужно подключить землю и питание. К Ардуино подключается так же, как описан выше: SDA – A4, SCL – A5, земля с модуля к земле с Ардуино, VCC -5V.

Индикатор подключается просто – выводы с него CLK и DIO подключаются к любым цифровым пинам на плате.

Скетч. Для написания кода используется функция setup, которая позволяет инициализировать часы и индикатор, записать время компиляции. Вывод времени на экран будет выполнен с помощью loop.

#include #include "TM1637.h" #include "DS1307.h" //нужно включить все необходимые библиотеки для работы с часами и дисплеем. char compileTime = __TIME__; //время компиляции. #define DISPLAY_CLK_PIN 10 #define DISPLAY_DIO_PIN 11 //номера с выходов Ардуино, к которым присоединяется экран; void setup() { display.set(); display.init(); //подключение и настройка экрана. clock.begin(); //включение часов. byte hour = getInt(compileTime, 0); byte minute = getInt(compileTime, 2); byte second = getInt(compileTime, 4); //получение времени. clock.fillByHMS(hour, minute, second); //подготовка для записывания в модуль времени. clock.setTime(); //происходит запись полученной информации во внутреннюю память, начало считывания времени. } void loop() { int8_t timeDisp; //отображение на каждом из четырех разрядов. clock.getTime();//запрос на получение времени. timeDisp = clock.hour / 10; timeDisp = clock.hour % 10; timeDisp = clock.minute / 10; timeDisp = 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 - "0") * 10 + int(string) - "0"; //действия для корректной записи времени в двухзначное целое число. В ином случае на экране будет отображена просто пара символов. }

После этого скетч нужно загрузить и на мониторе будет показано время.

Программу можно немного модернизировать. При отключении питания выше написанный скетч приведет к тому, что после включения на дисплее будет указано время, которое было установлено при компиляции. В функции setup каждый раз будет рассчитываться время, которое прошло с 00:00:00 до начала компиляции. Этот хэш будет сравниваться с тем, что хранятся в EEPROM, которые сохраняются при отключении питания.

Для записи и чтения времени в энергонезависимую память или из нее нужно добавить функции EEPROMWriteInt и EEPROMReadInt. Они нужны для проверки совпадения/несовпадения хэша с хэшем, записанным в EEPROM.

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

В результате в коде нужно будет указать новую библиотеку (для жидкокристаллических экранов это LiquidCrystal), и добавить в функцию loop() строки для получения даты.

Алгоритм работы следующий:

  • Подключение всех компонентов;
  • Проверка – на экране монитора должны меняться ежесекундно время и дата. Если на экране указано неправильное время, нужно добавить в скетч функцию RTC.write (tmElements_t tm). Проблемы с неправильно указанным временем связаны с тем, что модуль часов сбрасывает дату и время на 00:00:00 01/01/2000 при выключении.
  • Функция write позволяет получить дату и время с компьютера, после чего на экране будут указаны верные параметры.

Заключение

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

Часы реального времени - модуль, который хранит текущую дату и не сбрасывает её при отключении питания благодаря встроенной батарейке. Вы могли слышать о часах на основе чипа DS1307. Этот чип отличается крайне низкой точностью хода часов. Отставание на один час в сутки - это слишком. Рекомендую использовать модуль на основе высокоточного чипа DS3231, который снабжён термометром для корректирования хода часов в зависимости от температуры. Точность хода часов этого чипа находится на уровне хороших наручных часов и составляет 2ppm при температуре окружающей среды 0°-40°. При этом, модуль совместим со всеми библиотеками, написанными для модуля на основе чипа DS1307. Статья рассказывает о подключении модуля к Arduino и взаимодействии с ними с помощью библиотеки Time. Купить такой модуль у проверенного мной продавца вы можете .

Подключение часов реального времени

Часы подключаются по протоколу I2C всего двумя проводами. Необходимо дополнительно подтянуть выводы, к которым подключаются часы к рельсе питания с помощью резисторов 2 КОм. Выводы часов выглядят так:

Выводы 32К и SQW можно игнорировать. Их назначение не рассматривается в этой статье. SCL и SDA - это выводы интерфейса I2C. Их и нужно подключать к контроллеру. VCC и GND - +5 В и земля соответственно.

SCL и SDA на разных платах расположены на разных выводах:

Uno, Nano A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)

Вывод SDA часов подключается к выводу SDA контроллера. SDL часов, соответственно, к SDL контроллера. После подключения проводов, должна получиться такая картина:

Работать с модулем часов реального времени удобней всего с помощью библиотеки. Наиболее удобная в этом плане, так и называется: Time (англ. время ).
Библиотека является «обёрткой» для другой популярной библиотеки для работы с модулем часов: DS1307RTC. Несмотря на то, что библиотека разработана для чипа DS1307, она прекрасно работает и с DS3231, так как протоколы взаимодействия совместимы.

Скачайте обе библиотеки.

После скачивания, поместите содержимое архивов в папку libraries, которая находится в папке со средой разработки Arduino. Запустите среду Arduino IDE и откройте стандартный пример библиотеки: Примеры->Time->TimeRTC
Или просто скопируйте этот код:

#include #include #include void setup() { Serial.begin(9600); while (!Serial) ; // wait until Arduino Serial Monitor opens setSyncProvider(RTC.get); // the function to get the time from the RTC if(timeStatus()!= timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time"); } void loop() { if (timeStatus() == timeSet) { digitalClockDisplay(); } else { Serial.println("The time has not been set. Please run the Time"); Serial.println("TimeRTCSet example, or DS1307RTC SetTime example."); Serial.println(); delay(4000); } delay(1000); } void digitalClockDisplay(){ // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print("0"); Serial.print(digits); }

#include

#include

#include

void setup () {

Serial . begin (9600 ) ;

while (! Serial ) ; // wait until Arduino Serial Monitor opens

setSyncProvider (RTC . get ) ; // the function to get the time from the RTC

if (timeStatus () != timeSet )

Serial . println ("Unable to sync with the RTC" ) ;

else

Serial . println ("RTC has set the system time" ) ;

void loop ()

if (timeStatus () == timeSet ) {

digitalClockDisplay () ;

} else {

Serial . println ("The time has not been set. Please run the Time" ) ;

Serial . println ("TimeRTCSet example, or DS1307RTC SetTime example." ) ;

Serial . println () ;

delay (4000 ) ;

delay (1000 ) ;

void digitalClockDisplay () {

// digital clock display of the time

Serial . print (hour () ) ;

printDigits (minute () ) ;

printDigits (second () ) ;

Serial . print (" " ) ;

Serial . print (day () ) ;

Serial . print (" " ) ;

Serial . print (month () ) ;

Serial . print (" " ) ;

Serial . print (year () ) ;

Serial . println () ;

void printDigits (int digits ) {

// utility function for digital clock display: prints preceding colon and leading 0

Serial . print (":" ) ;

if (digits < 10 )

Serial . print ("0" ) ;

Serial . print (digits ) ;

После загрузки скетча в плату запустите монитор порта (Сервис->монитор порта). Вы увидите сообщения от библиотеки. Отображаемое время будет неверным, либо библиотека вовсе пожалуется на не настроенные часы. Для настройки часов загрузите в плату пример из библиотеки DS1307RTC «SetTime» (Примеры->DS1307RTC->SetTime). Загрузите этот пример в плату. После загрузки часы окажутся настроенными на время компиляции скетча . Задержка между компиляцией и полной загрузкой составит совсем немного, чего окажется достаточно для точно настроенных часов. Но если вы отключите и заново подключите питание платы, даже через несколько часов, время в часах всё равно будет заново установлено на время компиляции и окажется неверным. Поэтому, используйте этот пример только для настройки, после настройки отключите часы или загрузите в плату другой скетч.

Добрый день, сегодня я поделюсь инструкцией по изготовлению часов с комнатным термометром(Часы на ардуино своими руками ). Часы работают на Arduino UNO, для отображения времени и температуры служит графический экран WG12864B. В качестве датчика температуры - ds18b20. В отличие от большинства других часов я не буду использовать RTS (Real Time Clock), а попробую обойтись без этого дополнительного модуля.

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

Приступим.

Для создания данных часов нам понадобится:

Arduino UNO (Или любая другая Arduino совместимая плата)
- Графический экран WG12864B
- Датчик температуры ds18b20
- Резистор 4.7 Ком 0.25 Вт
- Резистор 100 ом 0.25 Вт
- Батарейный отсек для 4 батареек типа АА «пальчиковых»
- Подходящая коробка
- Мелкий напильник
- Лак для ногтей (черный или под цвет корпуса)
- Немного тонкого пластика или картона
- Изолента
- Соединительные провода
- Монтажная плата
- Кнопки
- Паяльник
- Припой, канифоль
- Двусторонний скотч

Подготовка графического экрана.
С подключение экрана, на первый взгляд, возникает много проблем и сложностей. Но если вначале разобраться с их видами, станет намного легче и понятнее. Существует много разновидностей и типов экранов на контролере ks0107/ks0108. Все экраны принято делить на 4 типа:
Вариант A: HDM64GS12L-4, Crystalfontz CFAG12864B, Sparkfun LCD-00710CM, NKC Electronics LCD-0022, WinStar WG12864B-TML-T
Вариант B: HDM64GS12L-5, Lumex LCM-S12864GSF, Futurlec BLUE128X64LCD, AZ Displays AGM1264F, Displaytech 64128A BC, Adafruit GLCD, DataVision DG12864-88, Topway LM12864LDW, Digitron SG12864J4, QY-12864F, TM12864L-2, 12864J-1
Вариант C: Shenzhen Jinghua Displays Co Ltd. JM12864
Вариант D: Wintek- Cascades WD-G1906G, Wintek - GEN/WD-G1906G/KS0108B, Wintek/WD-G1906G/S6B0108A, TECDIS/Y19061/HD61202, Varitronix/MGLS19264/HD61202

Список не полный, их очень много. Самый распространённый и, на мой взгляд, удобный WG12864B3 V2.0. Дисплей можно подключить к Arduino по последовательному или параллельному порту. При использовании с Arduino UNO лучше выбрать подключение по последовательному порту – тогда нам потребуется всего 3 выхода микроконтроллера, вместо минимум 13 линий при подключении по параллельному порту. Подключается все довольно просто. Есть еще один нюанс, в продаже можно встретить два варианта дисплеев, со встроенным потенциометром (для регулировки контраста) и без него. Я выбрал, и советую тоже сделать вам, со встроенным.


Это уменьшает количество деталей и время пайки. Также стоит поставить токоограничительный резистор номиналом 100 Ом для подсветки. Подключая напрямую 5 вольт, существует риск сжечь подсветку.
WG12864B – Arduino UNO
1 (GND) - GND
2 (VCC) - +5V
4 (RS) – 10
5 (R/W) – 11
6 (E) – 13
15 (PSB) – GND
19 (BLA) – через резистор - +5V
20 (BLK) – GND

Удобнее всего это все собрать сзади экрана и вывести от него 5 проводов подключения к Arduino UNO. В итоге должно получится примерно так:


Для тех кто все-таки выберет параллельное подключение приведу таблицу подключения.

И схема для экранов варианта B:



На одну линию связи может быть включено несколько датчиков. Для наших часов достаточно одного. Подключаем провод от контакта «DQ» ds18b20 к «pin 5» Arduino UNO.

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


Подключаем следующим образом: общий для всех трех кнопок провод подключаем к «GND» Arduino. Первую кнопку, она служит для входа в режим установки времени и переключения по времени и дате, подключаем к «Pin 2». Вторая, кнопка увеличения значения, - к «Pin 3», а третья, кнопка уменьшения значения, - к «Pin 4».

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


Спереди экрана по краю клеим двусторонний скотч на вспененной основе, желательно черный.


Подключаем экран к Arduino:


Плюс от батарейного отсека подключаем к «VIN» Arduino, минус к «GND». Размещаем его сзади Arduino. Перед установкой в корпус, не забудьте подключить датчик температуры и плату с кнопками.


Подготовка и заливка скетча.
Для датчика температуры нужна библиотека OneWire.

Вывод на экран осуществляется через библиотеку U8glib:

Для редактирования и заливки скетча надо установите эти две библиотеки. Сделать это можно двумя способами. Просто распаковать эти архивы и поместить распакованные файлы в папку «libraries», находящуюся в папке с установленной Arduino IDE. Или второй вариант установить библиотеки прямо в среде программирования. Не распаковывая скачанные архивы, в среде Arduino IDE выберите меню Скетч – Подключить библиотеку. В самом верху выпадающего списка выберите пункт «Добавить.Zip библиотеку». В появившемся диалоговом окне выберете библиотеку, которую вы хотите добавить. Снова откройте меню Скетч – Подключить библиотеку. В самом низу выпадающего списка вы должны увидеть новую библиотеку. Теперь библиотеку можно использовать в программах. Не забудьте после всего этого перезагрузить Arduino IDE.

Датчик температуры работает по протоколу One Wire и имеет уникальный адрес для каждого устройства - 64-разрядный код. Каждый раз искать этот код нецелесообразно. Поэтому необходимо вначале подключить датчик к Arduino, залить в нее скетч находящийся в меню Файл – Примеры – Dallas Temperature – OneWireSearch. Далее запускаем Инструменты - Монитор порта. Arduino должна найти наш датчик, написать его адрес и текущие показания температуры. Копируем или просто записываем адрес нашего датчика. Открываем скетч Arduino_WG12864B_Term, ищем строку:

Byte addr={0x28, 0xFF, 0xDD, 0x14, 0xB4, 0x16, 0x5, 0x97};//адрес моего датчика

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

Стока:

//u8g.setPrintPos(44, 64); u8g.print(sek); // Выводим секунды для контроля правильности хода

Служит для вывода секунд рядом с надписью «Data». Это необходимо для точной установки хода времени.
Если часы спешат или отстаю следует поменять значение в строке:

If (micros() - prevmicros >494000) { // поменять на другое для корректировки было 500000

Я опытным путем определил число, при котором часы идут достаточно точно. Если ваши часы спешат следует увеличить это число, если отстаю – уменьшить. Для определения точности хода и нужен вывод секунд. После точной калибровки числа, секунды можно закомментировать и таким образом убрать с экрана.