Содержание
Введение
Как микроконтроллеры отслеживают время и дату? Обычный микроконтроллер обладает функцией таймера, который стартует от нуля при подаче напряжения питания, а затем начинает считать. В мире Arduino мы можем использовать функцию , чтобы узнать, сколько прошло миллисекунд с того времени, когда было подано напряжение питания. Когда вы снимете и снова подадите питания, она начнет отсчет с самого начала. Это не очень удобно, когда дело доходит до работы с часами и датами.
Вот здесь и будет удобно использование микросхемы RTC (Real Time Clock, часов реального времени). Эта микросхема с батарейкой 3В или каким-либо другим источником питания следит за временем и датой. Часы/календарь обеспечивают информацию о секундах, минутах, часах, дне недели, дате, месяце и годе. Микросхема корректно работает с месяцами продолжительностью 30/31 день и с високосными годами. Связь осуществляется через шину I2C (шина I2C в данной статье не обсуждается).
Если напряжение на главной шине питания Vcc падает ниже напряжения на батарее Vbat, RTC автоматически переключается в режим низкого энергопотребления от резервной батареи. Резервная батарея – это обычно миниатюрная батарея (в виде «монетки», «таблетки») напряжением 3 вольта, подключенная между выводом 3 и корпусом. Таким образом, микросхема по-прежнему будет следить за временем и датой, и когда на основную схему будет подано питание, микроконтроллер получит текущие время и дату.
В этом проекте мы будем использовать DS1307. У этой микросхемы вывод 7 является выводом SQW/OUT (выходом прямоугольных импульсов). Вы можете использовать этот вывод для мигания светодиодом и оповещения микроконтроллера о необходимости фиксации времени. Мы будем делать и то, и другое. Ниже приведено объяснение работы с выводом SQW/OUT.
Для управления работой вывода SQW/OUT используется регистр управления DS1307.
Бит 7 | Бит 6 | Бит 5 | Бит 4 | Бит 3 | Бит 2 | Бит 1 | Бит 0 |
---|---|---|---|---|---|---|---|
OUT | SQWE | RS1 | RS0 |
- Бит 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.
RS1 | RS0 | Частота импульсов и уровень на выходе SQW/OUT | SQWE | OUT |
---|---|---|---|---|
1 Гц | 1 | x | ||
1 | 4,096 кГц | 1 | x | |
1 | 8,192 кГц | 1 | x | |
1 | 1 | 32,768 кГц | 1 | x |
x | x | |||
x | x | 1 | 1 |
Данная таблица поможет вам с частотой:
Частота импульсов | Бит 7 | Бит 6 | Бит 5 | Бит 4 | Бит 3 | Бит 2 | Бит 1 | Бит 0 |
---|---|---|---|---|---|---|---|---|
1 Гц | 1 | |||||||
4,096 кГц | 1 | 1 | ||||||
8,192 кГц | 1 | 1 | ||||||
32,768 кГц | 1 | 1 | 1 |
Если вы подключили светодиод и резистор к выводу 7 и хотите, чтобы светодиод мигал с частотой 1 Гц, то должны записать в регистр управления значение 0b00010000. Если вам нужны импульсы 4,096 кГц, то вы должны записать 0b000100001. В этом случае, чтобы увидеть импульсы вам понадобится осциллограф, так как светодиод будет мигать так быстро, что будет казаться, что он светится постоянно. Мы будем использовать импульсы с частотой 1 Гц.
Способ 1: чтение показаний DS18B20 по индексу
В этом методе библиотека Dallas Temperature при инициализации обнаруживает все датчики, использующие одну шину. Она рассматривает всю шину как массив датчиков и присваивает им индексы. Поэтому мы можем точно выбрать каждый датчик по его индексу и прочитать показания температуры.
Вывод вышеприведенного скетча выглядит так:
Рисунок 5 – Вывод показаний нескольких датчиков DS18B20 индексным методом
Объяснение кода
Скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки .
В настроечной части кода мы сначала вызываем функцию . Она инициализирует шину и обнаруживает все DS18B20, присутствующие на ней. Затем каждому датчику присваивается индекс и устанавливается разрешение в 12 бит.
Затем мы вызываем функцию , чтобы получить количество устройств, найденных на шине.
В циклической части кода мы используем функцию , чтобы отправить команду всем датчикам для преобразования температуры.
Теперь, используя простой цикл , мы можем перебирать массив датчиков и считывать температуру DS18B20 по индексу , просто вызывая .
Проблемы
Да, этот код рабочий, и часы будут идти. Однако, если отключить питание, а через несколько минут включить, то после включения время время вновь станет тем, которое было при компиляции.
Это происходит потому что после включения питания, вновь исполняется код, находящийся в функции . А он записывает в часы реального времени старое значение времени.
Чтобы этого избежать, нам необходимо еще чуть-чуть модифицировать код. Каждый раз в функции будет происходить подсчет «хэша» времени компиляции — будет рассчитываться количество секунд, прошедшее с 00:00:00 до времени компиляции. И этот хэш будет сравниваться с хэшем в EEPROM. Напомним EEPROM — память, которая не обнуляется при отключении питания.
Если значения посчитанного и сохранённого ранее хэша совпадают, то это значит, что перезаписывать время в модуль часов нет необходимости: это уже было сделано. А вот если эта проверка не проходит, то происходит перезапись времени в RTC.
Для записи/чтения числа типа в/из EEPROM написаны две дополнительные функции и . Они добавлены потому что функции и могуть читать и писать только данные типа .
- rtc-eeprom.ino
-
#include <Wire.h> #include <EEPROM.h> #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, ); byte minute = getInt(compileTime, 3); byte second = getInt(compileTime, 6); //Импровизированный хэш времени //Содержит в себе количество секунд с начала дня unsigned int hash = hour * 60 * 60 + minute * 60 + second; //Проверяем несовпадение нового хэша с хэшем в EEPROM if (EEPROMReadInt() != hash) { //Сохраняем новый хэш EEPROMWriteInt(, hash); //Готовим для записи в RTC часы, минуты, секунды clock.fillByHMS(hour, minute, second); //Записываем эти данные во внутреннюю память часов. //С этого момента они начинают считать нужное для нас время clock.setTime(); } } void loop() { //Значения для отображения на каждом из 4 разрядов int8_t timeDisp4; //Запрашиваем время с часов clock.getTime(); //Получаем десятки часов с помощью целочисленного деления timeDisp = clock.hour 10; //Получаем единицы часов с помощью остатка от деления timeDisp1 = clock.hour % 10; //Проделываем то же самое с минутами timeDisp2 = clock.minute 10; timeDisp3 = clock.minute % 10; //... а затем выводим его на экран display.display(timeDisp); //у нас нет отдельных разрядов для секунд, поэтому //будем включать и выключать двоеточие каждую секунду display.point(clock.second % 2 ? POINT_ON POINT_OFF); } char getInt(const char* string, int startIndex) { return int(stringstartIndex - '0') * 10 + int(stringstartIndex+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; }
Описание регистров DS3231
Ниже в таблице представлен перечень регистров часов реального времени:
Адрес | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Функция | Пределы |
---|---|---|---|---|---|---|---|---|---|---|
0x00 | 10 секунд | Секунды | Секунды | 00-59 | ||||||
0x01 | 10 минут | Минуты | Минуты | 00-59 | ||||||
0x02 | 12/24 | AM/PM | 10 часов | Час | Часы | 1-12 + AM/PM или 00-23 | ||||
10 часов | ||||||||||
0x03 | День | День недели | 1-7 | |||||||
0x04 | 10 число | Число | Дата | 01-31 | ||||||
0x05 | Century | 10 месяц | Месяц | Месяцы/век | 01-12 + Век | |||||
0x06 | 10 лет | Год | Годы | 00-99 | ||||||
0x07 | A1M1 | 10 секунд | Секунды | Секунды, 1-й будильник | 00-59 | |||||
0x08 | A1M2 | 10 минут | Минуты | Минуты, 1-й будильник | 00-59 | |||||
0x09 | A1M3 | 12/24 | AM/PM | 10 часов | Час | Часы, 1-й будильник | 1-12 + AM/PM или 00-23 | |||
10 часов | ||||||||||
0x0A | A1M4 | DY/DT | 10 число | День | День недели, 1-й будильник | 1-7 | ||||
Число | Дата, 1-й будильник | 01-31 | ||||||||
0x0B | A2M2 | 10 минут | Минуты | Минуты, 2-й будильник | 00-59 | |||||
0x0C | A2M3 | 12/24 | AM/PM | 10 часов | Час | Часы, 2-й будильник | 1-12 + AM/PM или 00-23 | |||
10 часов | ||||||||||
0x0D | A2M4 | DY/DT | 10 число | День | День недели, 2-й будильник | 1-7 | ||||
Число | Дата, 2-й будильник | 01-31 | ||||||||
0x0E | EOSC | BBSQW | CONV | RS2 | RS1 | INTCN | A2IE | A1IE | Регистр настроек (Control) | |
0x0F | OSF | EN32kHz | BSY | A2F | A1F | Регистр статуса (Status) | ||||
0x10 | SIGN | DATA | DATA | DATA | DATA | DATA | DATA | DATA | Регистр подстройки частоты (Aging Offset) | |
0x11 | SIGN | DATA | DATA | DATA | DATA | DATA | DATA | DATA | Регистр температуры, старший байт | |
0x12 | DATA | DATA | Регистр температуры, младший байт |
Информация о времени хранится в двоично-десятичном формате, то есть каждый разряд десятичного числа (от 0 до 9) представляется группой из 4-х бит. В случае одного байта, младший полубайт отсчитывает единицы, старший десятки и т. д. Счет времени осуществляется в регистрах с адресами 0x00-0x06, для отсчета часов можно выбрать режим 12-ти или 24-х часов. Установка 6-го бита регистра часов (адрес 0x02), задает 12-ти часовой режим, в котором 5-й бит указывает на время суток, значению 1 соответствует время после полудня (PM), значению 0 до полудня (AM). Нулевое значение 6-го бита соответствует 24-х часовому режиму, здесь 5-й бит участвует в счете часов (значения 20-23).
Регистр дня недели увеличивается в полночь, счет идет от 1 до 7, регистр месяцев (адрес 0x05) содержит бит века Century (7-й бит), который переключается при переполнении регистра счета лет (адрес 0x06), от 99 к 00.
В микросхеме DS3231 реализовано два будильника, 1-й будильник настраивается с помощью регистров с адресами 0x07-0x0A, 2-й будильник регистрами 0x0B-0x0D. Битами A1Mx и A2Mx можно настроить различные режимы для будильников, установка бита исключает соответствующий регистр из операции сравнения.
4-х разрядный семисегментный дисплей (4-Digit 7 Segment Display)
4-х разрядный семисегментный дисплей состоит из четырех семисегментных дисплеев, объединенных в единое устройство. Иногда говорят, что эти дисплеи “мультиплексированы вместе”, поэтому для управления ими можно использовать технологию мультиплексирования. Этот дисплей можно использовать для отображения цифр, а также некоторых букв. Дисплей можно использовать в обоих направлениях. 4 символа удобно использовать для изготовления электронных часов или счетчика от 0 до 9999.
На следующем рисунке показана внутренняя схема соединений 4-х разрядного семисегментного дисплея.
Каждый сегмент дисплея имеет собственный светодиод и им можно индивидуально управлять. Светодиоды таким образом скомпонованы в составе дисплея, что каждый из них освещает только свой сегмент (к которому он относится). Семисегментные дисплеи могут быть с общим катодом и общим анодом, как показано на следующем рисунке.
В семисегментном дисплее с общим катодом (ОК) отрицательные выводы всех светодиодов соединены вместе и образую общую землю. В схеме с общим анодом (ОА) положительные выводы всех светодиодов соединены вместе и они образуют общий вывод напряжения постоянного тока (VCC).
На нашем сайте есть достаточно подробные статьи про устройство семисегментных дисплеев и их программированию – они написаны для микроконтроллеров семейства AVR, но я думаю провести аналогию с Arduino вам будет не трудно:
- семисегментный светодиодный индикатор: описание, подключение к микроконтроллеру;
- перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор;
- многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации.
Также можно посмотреть статью о подключении семисегментного дисплея к микроконтроллеру AVR ATmega32.
Использование технологии мультиплексирования
Так каким образом мы можем на подобном 4-х символьном семисегментном дисплее отобразить, к примеру, число 1234? Это возможно сделать с использованием технологии мультиплексирования. Смысл этой технологии достаточно прост – в каждый момент времени мы отображаем только один символ (из 4-х возможных) на данном дисплее. Переключение между отображением всех 4-х символов происходит достаточно быстро – поэтому человеческий глаз воспринимает их непрерывно горящими.
Обзор программ для работы с GPS на компьютере
U-Center
Ссылка на скачивание – https://www.u-blox.com/en/product/u-center-windows
Программа u-center используется для работы с GNSS-проемниками от фирмы U-Blox. С помощью этого программного обеспечения можно тестировать точность позиционирования, изменять конфигурацию ресивера и проводить общую диагностику, обрабатывать полученные данные и отображать их в режиме реального времени. Координаты приемник получает с помощью GPS, ГЛОНАСС. Полученную информацию можно экспортировать и показывать в картах Google Maps, Google Earth. Программа позволяет создавать двухмерные диаграммы, гистограммы и другие виды графиков. u-center можно использовать при работе с несколькими приемниками.
Возможности программного обеспечения U-Center:
- Работа с Windows;
- Чтение NMEA , SiRF данных, UBX;
- Вывод полученных данных в виде текста и графиков;
- Запись данных, и воспроизведение;
- Полное управление модулем GPS;
- Возможность изменения конфигурации GPS-модуля;
- Запись новой конфигурации в модуль;
- Запись конфигурации в файл формата .txt;
- Обновление прошивки модуля;
- Возможность холодного, теплого и горячего старта модуля.
Программа позволяет оценивать работоспособность приемника, анализировать его быстродействие и устанавливать его настройки. Помимо U-Center могут использоваться и другие программы, например, Visual GPS, Time Tools GPS Clock и другие.
Visual GPS
Ссылка на скачивание http://www.visualgps.net/VisualGPS/download.htm
Эта программа используется для отображения GPS данных по протоколу NMEA 0183 в графическом виде. Программа позволяет записывать лог GPS данных в файл. Существует два режима работы в программе – в первом Visual GPS связывается с приемником GPS, а во втором Visual GPS считывает показания NMEA из файла. Программа имеет 4 основных окна – Signal Quality (качество сигнала), Navigation (навигация), Survey (исследование), Azimuth and Elevation (азимут и высота).
Time Tools GPS Clock
Ссылка на скачивание https://softadvice.informer.com/Time_Tools_Gps_Clock.html
Эта программа работает на Windows и любых рабочих станциях, она проверяет время со стандартного приемника времени NMEA GPS, который подключен к компьютеру, и позволяет синхронизировать время на ПК. Отображается информация о времени, дате, состоянии GPS, полученная от приемника. Недостатком программы является невозможность высокоточного определения времени, так как GPS-устройства не имеют секундного импульса для последовательного порта компьютера.
GPS TrimbleStudio
Ссылка на скачивание http://softwaretopic.informer.com/trimble-gps-studio/
Программное обеспечение используется для работы с приемником Copernicus в Windows. Программа отображает принимаемые навигационные данные. Полученные координаты можно отобрать на картах Google Maps, Microsoft Visual Earth. Все установленные настройки приемника можно сохранить в конфигурационном файле
Fugawi
Ссылка на скачивание http://www.fugawi.com/web/products/fugawi_global_navigator.htm
Программа используется для планирования маршрута, GPS навигации в реальном времени. Программа позволяет записывать и сохранять маршруты и путевые точки на картах. Навигация производится как на суше, так и на воде и в воздухе. В программе используются различные виды цифровых карт – топографические карты, стандарты NOAA RNC, отсканированные копии бумажных карт, Fugawi Street Maps.
3D World Map
Ссылка на скачивание www.3dwamp.com
В этой программе можно увидеть землю в трехмерном виде. Используется как удобный географический справочник, в котором можно узнать информацию 269 странах и тридцати тысячах населенных пунктов, производить измерение между двумя точками, воспроизводить аудиозаписи.
Принципы работы устройства
GPS модуль передает данные в NMEA формате, пример этих данных можно посмотреть на рисунке ниже. NMEA формат состоит из нескольких строк (предложений), из которых нам нужно будет извлечь только время и дату. Эти данные содержатся в строке $GPRMC, которая содержит время, дату, координаты и другую полезную информацию. Длина строки $GPRMC составляет примерно 70 символов. Мы уже рассматривали пример извлечения нужных нам GPS данных из строки $GPGGA в проекте определения местоположения автомобиля, здесь же мы будем извлекать данные из строки $GPRMC.
Строка $GPRMC, в основном, содержит скорость, время, дату и местоположение:
$GPRMC,123519.000,A, 7791.0381,N, 06727.4434,E,022.4,084.4,230394,003.1,W*6A
$GPRMC,HHMMSS.SSS,A,latitude,N,longitude,E,speed,angle,date,MV,W,CMD
В следующей таблице представлен перевод (описание) данных GPS из строки $GPRMC.
Идентификатор | Описание |
RMC | Recommended Minimum sentence C |
HHMMSS.SSS | Время в формате: час минута секунда и миллисекунда |
A | Статус // A=active (активный) and V= void (пустой, недействительный) |
Latitude | Широта (координата) |
N | Направление: N=North (север), S=South (юг) |
Longitude | Долгота (координата) |
E | Направление: E= East (восток), W=West (запад) |
Speed | Скорость в узлах (1 узел= 1,87 км в час) |
Angle | Угол места в градусах |
Date | Временная отметка (дата в UTC, Universal Time Coordinated — всеобщее скоординированное время) |
MV | Магнитное возмущение |
W | Direction of variation E/W (направление изменения E/W) |
CMD (*6A) | Данные контрольной суммы |
В большинстве случаев эта строка ($GPRMC) используется для извлечения данных времени, даты и скорости.
Мы можем извлечь время и дату из строки $GPRMC при помощи подсчета запятых в этой строке. Таким образом, с помощью Arduino мы будем находить в GPS данных строку $GPRMC и сохранять ее в массиве, в котором время (в 24-часовом формате) может быть найдено после одной запятой, а дата – после 9 запятых. Время и дата потом сохраняются в соответствующих строках.
GPS спутники передают время и дату в формате UTC (Universal Time Coordinated — всеобщее скоординированное время), поэтому мы должны конвертировать его в местное время. В нашем проекте мы добавили к этому времени 5:30 чтобы получить время, соответствующее времени в Индии, вы для своего региона можете легко узнать соответствующую поправку.
Код
Код проекта вы можете скачать или скопировать ниже. Код содержит комментарии. Обычно мы рекомендуем копировать код из скачанного файла, т.к. при копировании могут выявляться некоторые ошибки.
Также не забываем, что мы в самом начале подключаем библиотеку LiquidCrystal, которую вы можете скачать в разделе Библиотеки на нашем сайте.
/* ### Самые простые часы на Arduino UNO ### Для проекта часов нужны только жк-дисплей 16х2 LCD и 2 кнопки Никаких потенциометров для контраса, никаких резисторов Функции кнопок: - короткое нажатие одной из кнопок включает подсветку на 30 с Настройка времени - Нажмите H для увеличения Часов - Нажмите M для увеличения Минут и сброса секунд */ #include "LiquidCrystal.h" // Определяем соединение ЖК-дисплея с цифровыми контактами const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // Настройка контрастности ЖК int cs=9;// пин 9 для контраста ШИМ const int contrast = 100;// контраст по умолчанию // Начальное отображение времени 12:59:45 PM int h=12; int m=59; int s=45; int flag=1; //PM // Кнопки установки времени int button1; int button2; // Определение пинов для Кнопок установки времени int hs=0;// pin 0 для настройки Часов int ms=1;// pin 1 для настройки Минут // Тайм-аут подсветки const int Time_light=150; int bl_TO=Time_light;// Тайм-аут подсветки int bl=10; // Пин подсветки const int backlight=120; // НЕ БОЛЕЕ 7mA !!! // Для точного считывания времени используйте часы реального времени Arduino, а не только задержку delay() static uint32_t last_time, now = 0; // RTC void setup() { lcd.begin(16,2); pinMode(hs,INPUT_PULLUP);// избегать внешних Pullup резисторов для кнопки 1 pinMode(ms,INPUT_PULLUP);// и кнопки 2 analogWrite(cs,contrast);// Настроить контрастность VO analogWrite(bl,backlight);// Включить подсветку now=millis(); // читать начальное значение RTC } void loop() { lcd.begin(16,2);// каждую секунду // Обновить ЖК-дисплей // Вывести время TIME в Hour, Min, Sec + AM/PM (часы, минуты, секунды) lcd.setCursor(0,0); lcd.print("Time "); if(h<10)lcd.print("0");// всегда 2 цифры lcd.print(h); lcd.print(":"); if(m<10)lcd.print("0"); lcd.print(m); lcd.print(":"); if(s<10)lcd.print("0"); lcd.print(s); if(flag==0) lcd.print(" AM"); if(flag==1) lcd.print(" PM"); lcd.setCursor(0,1);// для Line 2 lcd.print("Precision clock"); // улучшенная замена delay(1000) // гораздо лучшая точность, менее зависимая от времени выполнения цикла for ( int i=0 ;i<5 ;i++)// сделать 5-кратный цикл 200 мс, для более быстрого ответа кнопок { while ((now-last_time)<200) //задержка delay 200ms { now=millis(); } // внутренний цикл 200ms last_time=now; // готовим следующий цикл // read Setting Buttons (читаем кнопки настройки) button1=digitalRead(hs);// Read Buttons button2=digitalRead(ms); //Время подсветки bl_TO--; if(bl_TO==0) { analogWrite(bl,0);// ВЫКЛ подсветки bl_TO++; } // Нажмите что-либо, чтобы активировать подсветку if( ((button1==0)|(button2==0)) & (bl_TO==1) ) { bl_TO=Time_light; analogWrite(bl,backlight); // дождитесь отпускания кнопки while ((button1==0)|(button2==0)) { button1=digitalRead(hs);// Read Buttons button2=digitalRead(ms); } } else // Поведение Кнопки 1 или Кнопки 2 пока подсветка ВКЛ { if(button1==0){ h=h+1; bl_TO=Time_light; analogWrite(bl,backlight); } if(button2==0){ s=0; m=m+1; bl_TO=Time_light; analogWrite(bl,backlight); } /* ---- управлять секундами, минутами, часами am / pm ----*/ if(s==60){ s=0; m=m+1; } if(m==60) { m=0; h=h+1; } if(h==13) { h=1; flag=flag+1; if(flag==2)flag=0; } if((button1==0)|(button2==0))// Обновить дисплей, если нажата кнопка { // Обновить ЖК // Вывести время TIME в часах, минутах, секундах + AM/PM lcd.setCursor(0,0); lcd.print("Time "); if(h<10)lcd.print("0");// всегда 2 цифры lcd.print(h); lcd.print(":"); if(m<10)lcd.print("0"); lcd.print(m); lcd.print(":"); if(s<10)lcd.print("0"); lcd.print(s); if(flag==0) lcd.print(" AM"); if(flag==1) lcd.print(" PM"); lcd.setCursor(0,1);// для Line 2 lcd.print("Precision clock"); } } // end if else }// end for // outer 1000ms loop (завершение цикла) s=s+1; //увеличение секунд // ---- управлять секундами, минутами, часами + am/pm ---- if(s==60){ s=0; m=m+1; } if(m==60) { m=0; h=h+1; } if(h==13) { h=1; flag=flag+1; if(flag==2)flag=0; } // Loop end (конец цикла) }
Подключение к плате Arduino
Модуль DS3231 подключается к плате Arduino по интерфейсу I2C, используются выводы SDA и SCL. Схема подключения показана на рис. 2.
Для программирования будем использовать библиотеки DS1307 и Time. Скетч получения данных с DS3231 и вывода в последовательный порт показан в листинге 1.
Открываем монитор последовательного порта (рис. 3).
Результат работы – правильный отсчет, но неверное значение времени и даты. При отсутствии питания значение времени в микросхеме DS3231 сбрасывается на 00:00:00 01/01/2000.
Добавим функционал скетчу – установка времени отправкой строки вида «dd/mm/ YYYY hh:mm:ss» в последовательный порт.
После загрузки скетча на плату Arduino, открываем монитор последовательного порта и отправляем в Arduino строку «dd/mm/ YYYY hh:mm:ss» для установки текущей даты и точного времени (рис. 4,5).
Теперь DS3231 будет отсчитывать точное время. И если установлена батарейка, время не собъется после отключения питания.
Режимы электропитания
Напряжение питания микросхемы может находиться в пределах 2,3…5,5В, имеются две линии питания, для внешнего источника (линия Vcc), а также для батареи (Vbat). Напряжение внешнего источника постоянно отслеживается, при падении ниже порога Vpf=2,5В, происходит переключение на линию батареи. В следующей таблице представлены условия переключения между линиями питания:
Комбинации уровней напряжения | Активная линия питания |
Vcc < Vpf, Vcc < Vbat | Vbat |
Vcc < Vpf, Vcc > Vbat | Vcc |
Vcc > Vpf, Vcc < Vbat | Vcc |
Vcc > Vpf, Vcc > Vbat | Vcc |
Точность хода часов поддерживается за счет отслеживания температуры окружающей среды. В микросхеме запускается внутренняя процедура корректировки частоты тактового генератора, величина корректировки определяется по специальному графику зависимости частоты от температуры. Процедура запускается после подачи питания, а затем выполняется каждые 64 секунды.
В целях сохранения заряда, при подключении батареи (подача напряжения на линию Vbat), тактовый генератор не запускается до тех пор, пока напряжение на линии Vcc не превысит пороговое значение Vpf, или не будет передан корректный адрес микросхемы по интерфейсу I2C. Время запуска тактового генератора составляет менее одной секунды. Примерно через 2 секунды после подачи питания (Vcc), или получения адреса по интерфейсу I2C, запускается процедура коррекции частоты. После того как тактовый генератор запустился, он продолжает функционировать до тех пор, пока присутствует напряжение Vcc или Vbat. При первом включении регистры даты и времени сброшены, и имеют следующие значения 01/01/ 00 – 01 – 00/00/00 (день/месяц/год/ – день недели – час/минуты/секунды).
Ток потребления при питании от батареи напряжением 3,63В, составляет 3 мкА, при отсутствии передачи данных по интерфейсу I2C. Максимальный ток потребления может достигать 300 мкА, в случае использования внешнего источника питания напряжением 5,5В, и высокой скорости передачи данных I2C.
Способ 2: чтение датчика DS18B20 по адресу
Мы знаем, что каждому DS18B20 назначен уникальный 64-битный адрес, чтобы отличать их друг от друга. В этом методе мы найдем этот адрес для соответствующей маркировки каждого датчика. Затем этот адрес можно использовать для считывания каждого датчика в отдельности.
Поиск адресов датчиков DS18B20s на шине
Следующий скетч обнаруживает все DS18B20, присутствующие на шине, и печатает их адреса на 1-Wire в монитор последовательного порта.
Вы можете подключать только один датчик за раз, чтобы определить его адрес (или последовательно добавлять по одному новому датчику, чтобы вы могли идентифицировать каждый из них по его адресу). Затем вы можете пометить каждый датчик.
Теперь откройте монитор последовательного порта. Вы должны получить что-то подобное:
Рисунок 6 – Нахождение адресов 1-Wire всех датчиков DS18B20 на шине
Скопируйте все адреса, так как они нам понадобятся в следующем скетче.
Чтение показаний датчиков DS18B20 по адресу
Следующий скетч считывает температуру датчиков DS18B20 по их адресам. Прежде чем приступить к загрузке скетча, вам нужно изменить адреса датчиков DS18B20 на те, которые вы определили в предыдущем скетче.
Вывод вышеприведенного эскиза выглядит так
Рисунок 7 – Вывод показаний нескольких датчиков DS18B20 методом адреса
Объяснение кода
Как обычно, скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки .
Далее мы вводим адреса, которые были найдены ранее для каждого датчика температуры. В нашем случае имеем следующее.
Во фрагменте настройки мы инициализируем библиотеку путем вызова функции и инициализируем последовательную связь с ПК.
В цикле мы просто посылаем команду всем датчикам для преобразования температуры, используя функцию .
Затем, чтобы напечатать температуру датчика, мы вызываем пользовательскую функцию , для которой передается в качестве параметра.
Вышеприведенная функция просто вызывает библиотечные функции для отображения температуры в градусах Цельсия и для отображения температуры в градусах Фаренгейта.
Сравнение популярных модулей 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 |