Часы с LED-индикаторами на Arduino. Часы с LED-индикаторами на Arduino Led часы на arduino nano

Часы реального времени - модуль, который хранит текущую дату и не сбрасывает её при отключении питания благодаря встроенной батарейке. Вы могли слышать о часах на основе чипа 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). Загрузите этот пример в плату. После загрузки часы окажутся настроенными на время компиляции скетча . Задержка между компиляцией и полной загрузкой составит совсем немного, чего окажется достаточно для точно настроенных часов. Но если вы отключите и заново подключите питание платы, даже через несколько часов, время в часах всё равно будет заново установлено на время компиляции и окажется неверным. Поэтому, используйте этот пример только для настройки, после настройки отключите часы или загрузите в плату другой скетч.

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

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

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


Для оценки размера часов можно принять тот факт, что один сегмент часов будет размером с бумагу формата А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, сложенную вдвое.

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

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

Вконтакте

Добрый день, сегодня я поделюсь инструкцией по изготовлению часов с комнатным термометром(Часы на ардуино своими руками ). Часы работают на 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

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

  • Отличительные особенности:
  • Подсчет реального времени в секундах, минутах, часах, датах месяца, месяцах, днях недели и годах с учетом высокосности текущего года вплоть до 2100 г.
  • Дополнительное ОЗУ 31 x 8 для хранения данных
  • Последовательный ввод – вывод информации для сокращения выводов микросхемы
  • Выполнение всех функций при напряжении питания 2.0-5.5 В
    - выполнение всех функций при напряжении 2.0-5.5 В на дополнительном выводе питания
  • Потребление не более 300 нA при 2.5 В питания
  • Чтение и запись информации по одному байту или потоком
  • Исполнение в 8-ми выводном корпусе DIP, а также по заказу в 8-ми выводном SOIC корпусе для поверхностного монтажа
  • Простой 3-проводной интерфейс
  • Совместимость с TTL-микросхемами (Vcc= 5V)
  • Возможность поставки в промышленном диапазоне температур: от -40°C до+85°C
  • Совместимость с DS1202
  • Отличия от DS1202:
    возможность подключения встроенной цепи подзарядки к выводу Vcc1
    два вывода питания для подключения основного и резервного источника питания
    увеличено ОЗУ на 7 байт

Описание выводов:

X1, X2 подключение кварцевого резонатора 32.768 кГц
GND общий
RST сброс
I/O ввод - вывод данных
SCLK синхронизация последовательной связи
VCC1, VCC2 выводы питания

Структурная схема DS1302:

Общее описание:

Микросхема DS1302 содержит часы реального времени с календарем и 31 байт статического ОЗУ. Она общается с микропроцессором через простой последовательный интерфейс. Информация о реальном времени и календаре представляется в секундах минутах, часах, дне, дате, месяце и годе. Если текущий месяц содержит менее 31 дня, то микросхема автоматически определит количество дней в месяце с учетом высокосности текущего года. Часы работают или в 24-часовом или 12-часовом формате с индикатором AM/PM (до полудня/ после полудня). Подключение DS1302 к микропроцессу упрощено за счет синхронной последовательной связи. Для этого требуется только 3 провода: (1) RST (сброс), (2) I/O (линия данных) и (3) SCLK (синхронизация последовательной связи). Данные могут передаваться по одному байту или последовательностью байтов до 31. DS1302 разработан, чтобы потреблять малую мощность и сохранять данные и информацию часов при потреблении менее 1 мкВт. DS1302 - преемник DS1202. В дополнение к основным функциям хранения времени DS1202, DS1302 имеет два вывода питания для подключения основного и резервного источника питания, возможность подключения программируемой цепи заряда к выводу VCC1 и семь дополнительных байтов ОЗУ.

Подключение:

Подключение DS1307 к Arduino:

RTC DS1307 Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Подключение DS1302 к Arduino:

RTC DS1302 Arduino UNO
GND GND
VCC +5V
RST 6 (Можно изменить на другие в скетче)
CLK 7 (Можно изменить на другие в скетче)
DAT

(Можно изменить на другие в скетче)

Подключение DS3231 к Arduino:

RTC DS3231 Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Модуль DS1302 часы реального времени на Алиэкспресс http://ali.pub/1br52w

Код программы для модуля 1302 и дисплей 1602 I2C

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

Для DS1302 :

time . begin (RTC_DS1302 , 10 , 13 , 12 );

#include

virtuabotixRTC myRTC(6, 7, 8); //CLK, DAT, RST

Программа

#include

#include

LiquidCrystal_I2C lcd(0x3F ,2,1,0,4,5,6,7,3, POSITIVE);

void setup() {

lcd.begin(16,2);

//myRTC.setDS1302Time(00,04, 12, 06, 18, 04, 2017);

void loop() {

myRTC.updateTime();

lcd.setCursor(0, 0);

lcd.print("date: ");

lcd.print(myRTC.dayofmonth);

lcd.print("/");

lcd.print(myRTC.month);

lcd.print("/");

lcd.print(myRTC.year);

lcd.print(" ");

lcd.setCursor(0, 1);

lcd.print("time: ");

lcd.print(myRTC.hours);

lcd.print(":");

lcd.print(myRTC.minutes);

lcd.print(":");

lcd.print(myRTC.seconds);

lcd.println(" ");

Так же не забываем о экономии при покупке товаров на Алиєкспресс с помощью кэшбэка

Преимущества библиотеки:

Библиотека имеет внутренние функции аппаратной обработки протоколов передачи данных I2C и SPI, а следовательно не требует подключения дополнительных библиотек, но и не конфликтует с ними, если таковые всё же подключены.

Библиотека имеет внутренние функции программой обработки протокола передачи данных 3-Wire

Для инициализации модуля необходимо вызвать функцию begin с названием модуля.

Подключение модулей осуществляется к аппаратным выводам arduino используемой шины (за исключением 3-Wire)

Простота установки и чтения времени функциями settime и gettime

функция settime может устанавливать дату и время, как полностью, так и частично (например только минуты, или только день, и т.д.)

функция gettime работает как функция date в php, возвращая строку со временем, но если её вызвать без параметра, то функция ничего не вернёт, а время можно прочитать из переменных в виде чисел.

Библиотека расширяемая, то есть для того, чтоб она работала с новым модулем, нужно указать параметры этого модуля в уже существующих массивах файла RTC.h (тип шины, частота шины в кГц, режимы работы, адреса регистров и т.д.), как всё это сделать, описано в файле extension.txt

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

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

При работе с модулем DS1302 не нужны никакие резисторы на выводе GND (которые нужны для его работы с другими библиотеками этого модуля), это достигнуто тем, что для шины 3-Wire указана конкретная частота 10кГц, не зависимо от частоты CPU arduino.

В библиотеке реализована еще одна не обязательная функция period, принимающая в качестве единственного аргумента - количество минут (от 1 до 255)

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

Функцию period достаточно вызвать один раз.

Подробное описание:

} // ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: // // Подключение библиотеки: // #include // iarduino_RTC time(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); // если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC time(RTC_DS3231); // если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC time(RTC_DS1305,22); // если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC time(RTC_DS1302, 1, 2, 3); // RST, CLK, DAT // // Для работы с модулями, в библиотеке реализованы 5 функции: // инициировать модуль begin(); // указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); // получить время gettime("строка с параметрами"); // мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень) // разгрузить шину period (минуты); // // Функция begin(): // функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. // // Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): // записывает время в модуль // год указывается без учёта века, в формате 0-99 // часы указываются в 24-часовом формате, от 0 до 23 // день недели указывается в виде числа от 0-воскресенье до 6-суббота // если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение // пример: settime(-1, 10); установит 10 минут, а секунды, часы и дату, оставит без изменений // пример: settime(0, 5, 13); установит 13 часов, 5 минут, 0 секунд, а дату оставит без изменений // пример: settime(-1, -1, -1, 1, 10, 15); установит дату 01.10.2015 , а время и день недели оставит без изменений // // Функция gettime("строка с параметрами"): // функция получает и выводит строку заменяя описанные ниже символы на текущее время // пример: gettime("d-m-Y, H:i:s, D"); ответит строкой "01-10-2015, 14:00:05, Thu" // пример: gettime("s"); ответит строкой "05" // указанные символы идентичны символам для функции date() в PHP // s секунды от 00 до 59 (два знака) // i минуты от 00 до 59 (два знака) // h часы в 12-часовом формате от 01 до 12 (два знака) // H часы в 24-часовом формате от 00 до 23 (два знака) // d день месяца от 01 до 31 (два знака) // w день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота) // D день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun) // m месяц от 01 до 12 (два знака) // M месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) // Y год от 2000 до 2099 (четыре знака) // y год от 00 до 99 (два знака) // a полдень am или pm (два знака, в нижнем регистре) // A полдень AM или PM (два знака, в верхнем регистре) // строка не должна превышать 50 символов // // если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных // seconds секунды 0-59 // minutes минуты 0-59 // hours часы 1-12 // Hours часы 0-23

Итак, после небольшого технического перерыва, продолжаем наше знакомство с семейством МК ARDUINO. В этом уроке мы попробуем сделать часы работающие от внутреннего генератора МК (с внешним генератором будет один из следующих уроков) и выводящего информацию на ЖК индикатор типа 1602 (что означает 16 символов в 2 строки, есть еще тип 1604- 16 символов в 4 строки, вы уже поняли что первые 2 цифры указывают на количество символов индикатора а вторые- на количество строк). Не будем затягивать вступление, переходим к работе.

Для проекта нам понадобится:

  1. Arduino Uno
  2. ЖК индикатор 1602
  3. Макетная плата
  4. Провода
  5. Подстроечный резистор на 10 кОм

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

  1. Секунды, работают в пределе от 0 до 59 по циклу с секундным интервалом (это понятно).
  2. Минуты, работают в пределе от 0 до 59 по циклу, переключение происходит при достижении значения секундами значения 0.
  3. Часы, работают в пределе от 0 до 24 (здесь вы можете выбрать отображение как в зарубежном стиле от 0 до 12 со значениями AM и PM, это как вам больше нравится) по циклу, переключение происходит по достижении значения минутами 0.
  4. Вывести всю необходимую информацию на дисплей (например вы можете решить не выводить секунды а сделать просто мигающую точку между часами и минутами)

Собираем наши часы по вот такой схеме:

Подключение ЖК индикатора 1602 к ARDUINO

Советы по сборке. Индикатор 1602 обычно приходит из Китая в «голом» виде, т.е. никаких выводов не подпаяно, советую для этих целей использовать двухрядные компьютерные гнезда от материнских плат, один вывод гнезда вставляется в 1602, второй вывод оказывается за краем платы, запаиваете оба вывода на один контакт- так повышается механическая и электрическая прочность. На данной схеме не указана схема подключения подсветки, это следующие 2 вывода справа от D7. Вы можете их подключить к питанию 3,3В на ARDUINO, можете сделать плавное загорание/затухание если подключите плюсовой вывод (он подписан как А- анод) к выходу ARDUINO и будете управлять питание через этот вывод, это уже второстепенная задача, пока просто подключите вывод А на 1602 к 3,3V на ARDUINO, а вывод К 1602 к GND ARDUINO.

Теперь приступаем собственно к разработке часов. Запускаем оболочку ARDUINO на компьютере. Попробуем поиграться с 1602 для проверки правильности соединений схемы. Заходим Файл-Примеры-LiqidCrystal и выбираем любой из файлов. Заливаем скетч в ARDUINO и наблюдаем что происходит. Если вместо символов вы видите черные квадратики- подкрутите подстроечный резистор, это регулятор контрастности (так же поступите если вообще ничего не отображается). Информация должна отображаться корректно и никаких «кракозябров» быть просто не должно. Если они появились- проверьте схему соединений, где то собрали неправильно. Можете сразу посмотреть в скетчах как обращаться к ЖК- индикатору и поразится простоте работы с ним! Если все у вас заработало правильно переходим непосредственно к программированию.

Определимся что таймер у нас будет работать без оператора delay как написано . Поэтому вводим такой код:




#include

// Variables will change:


void setup () {
lcd.begin(16, 2);

void loop ()
{

if (currentMillis — previousMillis >= interval) {


Данный код уже будет работать но ничего отображать не будет. К переменной s каждую секунду будет добавляться 1. Т.е. мы уже получили точный интервал в 1 секунду! Теперь, следуя алгоритму, нам необходим предел переменной между 0 и 59. Делаем.

if (s>
{


}

Добавляем этот код к программе. По описанию все понятно- если значение s больше 59 то присваиваем ей 0 и прибавляем 1 минуту в переменной m. На данный момент имеем полностью работающий секундный таймер и бесконечный (до 32768- максимальное значение типа integer) счетчик минут. Теперь нужно таким же образом рассчитать минуты. Пишем следующее:

if (m>59) // если значения m больше 59
{


}

Добавляем строки к программе. Она уже должна выглядеть так:

int h,m,s; // переменные для часов, минут, секунд
boolean z; // переменная для отображения точки
// подключаем библиотеку индикатора
#include

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Variables will change:
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)

void setup () {
lcd.begin(16, 2);

void loop ()
{

Unsigned long currentMillis = millis();

if (currentMillis — previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
s++; // добавляем единицу, равносильно записи s=s+1;

// секция подсчета секунд

if (s>59) // если значение s больше 59
{
s=0; // присваиваем значение 0 переменной s
m++; // добавляем 1 к переменной m отвечающей за минуты
}

// секция подсчета минут

if (m>
{
m=0; // присваиваем значение 0 переменной m
h++; // добавляем 1 к переменной h отвечающей за часы
}

В принципе все понятно. Осталось сделать обработку часов. Делаем. Дописываем после секции подсчета минут:

if (h>
{

}

Все, часы готовы! Заливаем скетч и часы будут ходить как надо! Хочу обратить ваше внимание что считать они будут в 24- часовом формате. Попробуйте сами сделать 12- часовой формат. Осталось вывести информацию на ЖК- индикатор. Существует 2 пути по написания кода на вывод информации.

  1. Посчитать одни данные и сразу вывести
  2. Посчитать все данные и вывести все сразу.

Тут уж вы сами определитесь по какому пути вы пойдете. Если пойдете по первому пути то писать отображение информации надо сразу в секциях подсчета, если по второму- пишется блок после всех вычислений. Давайте пойдем по второму пути т.к. он более предпочтителен и более логичен (хотя, если честно сказать, мой тестовый скетч написан по первому пути). Итак, для передачи данных на индикатор 1602 применяются всего 2 команды:

lcd.setCursor (3, 0); // устанавливает курсор на 3 символ 0 строки (счет строк и символов идет от 0)
lcd.print (0); // печатаем (print- печать, учите аглицкий) 0

Есть еще команда lcd.clear ; означающая очистку экрана но здесь мы ее можем не использовать.

Начинаем выводить информацию. Начнем с секунд (можете начать с любого значения, делайте как вам будет удобно). Устанавливаем курсор на 0 строку в 6 позицию и выводим значение секунд. Почему в 6 позицию спросите вы? Давайте представим следующее: формат отображения часов- 2 символа(часы), разделитель (допустим:), 2 символа (минуты), разделитель (:) и, наконец, секунды. Считаем с нулевой позиции: 0+2+1+2+1=6. Так как счет начинается с 0 то вычитаем из данных единицу (ноль тоже является числом), выходит 6-1=5. Столько занимает отображение часов и минут с разделителями, следующая позиция- секундная и она равна 5+1=6. Немного запутано но напишу следующее hh:mm:ss и посчитаем координаты сначала начиная от 0. Вот так и высчитываются координаты на индикаторах семейства 16хх. При данных условиях часы будут отображаться в верхнем левом углу, вы можете сменить расположение как вам удобно, можете даже ввести переменную и подбирая её подбирать нужное вам положение индикации. Ладно, пишем такие строки:

lcd.setCursor (6, 0); // устанавливает курсор на 6 символ 0 строки (счет строк идет от 0)

Программа будет выглядеть так:

int h,m,s; // переменные для часов, минут, секунд
boolean z; // переменная для отображения точки
// подключаем библиотеку индикатора
#include

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Variables will change:
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)

void setup () {
lcd.begin(16, 2);

void loop ()
{

Unsigned long currentMillis = millis();

if (currentMillis — previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
s++; // добавляем единицу, равносильно записи s=s+1;

// секция подсчета секунд

if (s>59) // если значение s больше 59
{
s=0; // присваиваем значение 0 переменной s
m++; // добавляем 1 к переменной m отвечающей за минуты
}

// секция подсчета минут

if (m>59) // если значение m больше 59
{
m=0; // присваиваем значение 0 переменной m
h++; // добавляем 1 к переменной h отвечающей за часы
}

// секция подсчета часов

if (h>23) // если значение h больше 23
{
h=0; // присваиваем значение 0 переменной h
}

// секция вывода информации

lcd.setCursor (6, 0);
lcd.print (s); // печатаем данные из переменной s

Заливаем скетч и…. секунды начали отображаться!!! Только обратите внимание, при счете от 0 до 59- все нормально, но как только начинается следующая минута- начинают меняться десятки секунд вместо единиц секунд, т.е. время отображается некорректно. Давайте разберемся с этим. Мы указали программе жестко позицию 6,0 , и она выводит данные точно в этой позиции не затирая то что находится после этой позиции. Выхода 2. Применить lcd.clear или описать отображение корректно, тем более при первом варианте будет довольно трудно привыкнуть к прыгающим разрядам секунд (далее минут и часов). Напишем обработчик корректного отображения. Какие условия будут в этой обработке? Давайте подумаем. Если секунд меньше 10 то пишем их значение в 7 позиции (6+1=7) и в 6 позиции пишем 0, если больше или равно 10- пишем в 6 позиции. Все довольно просто. Условие будет иметь следующий вид:

if (s<10) //если секунд меньше 10
{

lcd.print (0); //печатаем 0


}
else
{


}

Вставляем данный код вместо

lcd.setCursor (6, 0); // устанавливает курсор на 7 символ 0 строки (счет строк идет от 0)
lcd.print (s); // печатаем данные из переменной s

и радуемся уже полученному результату! Все отображается корректно! Кроме того перед секундами появился разделитель «:»! Таким же образом пишем обработчик для минут и часов с соответствующими координатами курсора. Это может выглядеть так для минут:

If (m<10)
{
lcd.setCursor (3, 0);
lcd.print (0);
lcd.setCursor (4, 0);
lcd.print (m);
}
else
{
lcd.setCursor (3, 0);
lcd.print (m);
}

и так для часов:

If (h<10)
{
lcd.setCursor (0, 0);
lcd.print (0);
lcd.setCursor (1, 0);
lcd.print (h);
}
else
{
lcd.setCursor (0, 0);
lcd.print (h);
}

Наша программа примет следующий вид:

int h,m,s; // переменные для часов, минут, секунд
boolean z; // переменная для отображения точки
// подключаем библиотеку индикатора
#include

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Variables will change:
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)

void setup () {
lcd.begin(16, 2);

void loop ()
{

Unsigned long currentMillis = millis();

if (currentMillis — previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
s++; // добавляем единицу, равносильно записи s=s+1;

// секция подсчета секунд

if (s>59) // если значение s больше 59
{
s=0; // присваиваем значение 0 переменной s
m++; // добавляем 1 к переменной m отвечающей за минуты
}

// секция подсчета минут

if (m>59) // если значение m больше 59
{
m=0; // присваиваем значение 0 переменной m
h++; // добавляем 1 к переменной h отвечающей за часы
}

// секция подсчета часов

if (h>23) // если значение h больше 23
{
h=0; // присваиваем значение 0 переменной h
}

// секция вывода информации

// вывод секунд

if (s<10) //если секунд меньше 10
{
lcd.setCursor (6, 0); // курсор в 6 позицию 0 строки
lcd.print (0); //печатаем 0
lcd.setCursor (7, 0); //курсор в 7 позицию 0 строки
lcd.print (s); //печатаем значение переменной s
}
else
{
lcd.setCursor (6, 0); //иначе курсор в 6 позицию 0 строки
lcd.print (s); // печатаем значение переменной s
}
lcd.setCursor (5, 0); // курсор в 5 позицию 0 строки
lcd.print (‘:’); // печатаем разделитель между секундами и минутами

// вывод минут

if (m<10)
{
lcd.setCursor (3, 0);
lcd.print (0);
lcd.setCursor (4, 0);
lcd.print (m);
}
else
{
lcd.setCursor (3, 0);
lcd.print (m);
}
lcd.setCursor (2, 0); // курсор в 2 позицию 0 строки
lcd.print (‘:’); // печатаем разделитель между минутами и часами

// вывод часов

if (h<10)
{
lcd.setCursor (0, 0);
lcd.print (0);
lcd.setCursor (1, 0);
lcd.print (h);
}
else
{
lcd.setCursor (0, 0);
lcd.print (h);
}

Весь код уместился в каких то 3 с небольшим килоБайта! Из них бОльшую часть съела библиотека для ЖК индикатора. Сразу хочу заметить что этот код- только тело программы, нужно еще дописать функцию установки времени. Кроме того можно добавить фоторезистор и яркостью подсветки дисплея. Можно дописать функцию ввода будильника и работать со звуком. Так же можно выводить температуру в помещении, дату и т.д… Вобщем данный индикатор с соответствующими датчиками может превратить данные часы в уникальное устройство! Единственный минус данного аппарата- при отключении электричества настраивать часы придется заново. Поэтому в ближайшее время опишу работу с модулем RTC, при работе с ним, даже если электричество отключится, при подаче напряжения часы будут работать как будто ничего и не произошло. Для более дешевой версии часов можно использовать arduino pro mini, это такой же контроллер только не имеет USB разъема но стоит в несколько раз дешевле и имеет очень маленькие размеры. Можно также применить и arduino nano, тот же про но с USB разъемом. До следующего урока. Всем спасибо за внимание.

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