Контакты

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

Итак, после небольшого технического перерыва, продолжаем наше знакомство с семейством МК 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*. Кстати процедуру отображения значений можно написать в виде отдельной функции и передавать необходимые значения в нее. Попробуйте так сделать и сравните объем занимаемой памяти. Всегда стремитесь к наименьшему объему.

Часы со светодиодной подсветкой и пульсирующей минутной стрелкой на микроконтроллере Arduino
Эти уникальные часы со светодиодной подсветкой и пульсирующей минутной стрелкой удалось изготовить благодаря использованию микросхемы ШИМ-контроллера TLC5940. Его главной задачей является расширить количество контактов с ШИМ-модуляцией. Еще одной особенностью данных часов является переделанный аналоговый вольтметр в прибор измеряющий минуты. Для этого на стандартном принтере была распечатана новая шкала и наклеена поверх старой. Как таковая, 5-я минута не отсчитывается, просто в течение пятой минуты счетчик времени показывает стрелку, упершуюся в конец шкалы (зашкаливает). Основное управление реализовано на микроконтроллере Arduino Uno.

Для того чтобы подсветка часов не светилась слишком ярко в темной комнате, была реализована схема автоматической подстройки яркости в зависимости от освещенности (использовался фоторезистор).

Шаг 1: Необходимые компоненты



Вот что потребуется:

  • Модуль аналогового вольтметра на 5V DC;
  • Микроконтроллер Arduino UNO или другой подходящий Arduino;
  • Монтажная плата Arduino (прото плата);
  • Модуль часов реального времени DS1307 (RTC);
  • Модуль с ШИМ-контроллером TLC5940;
  • Лепестковые светодиоды подсветки – 12 шт.;
  • Компоненты для сборки схемы автоматического регулирования яркости (LDR).

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

Шаг 2: Циферблат




Циферблат состоит из трех деталей (слоев) вырезанных на станке лазерной резки из 3 мм листа МДФ, которые скрепляются между собой с помощью болтов. Пластина без прорезей (внизу справа на картинке) помещается под другой пластиной для позиционирования светодиодов (внизу слева). Затем, отдельные светодиоды помещаются в соответствующие пазы, и сверху одевается лицевая панель (сверху на рисунке). По краю циферблата просверлены четыре отверстия, через которые все три детали скрепляются вместе с помощью болтов.

  • Для проверки работоспособности светодиодов на этом этапе, использовалась плоская батарейка CR2032;
  • Для фиксации светодиодов использовались небольшие полоски липкой ленты, которые приклеивались с задней стороны светодиодов;
  • Все ножки светодиодов были предварительно согнуты соответствующим образом;
  • Отверстия по краям были просверлены заново, через которые и выполнялось скрепление болтами. Оказалось, что это намного удобнее.

Технический чертеж деталей для циферблата доступен по :

Шаг 3: Разработка схемы



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

Шаг 4: Подключение монтажной платы Arduino





  1. Первым делом надо распаять все игольчатые контакты на монтажных и секционных платах;
  2. Далее, ввиду того, что питание 5V и GND используют очень много плат и периферийных устройств, для надежности, было припаяно по два провода на 5V и GND на монтажной плате;
  3. Далее был установлен ШИМ-контроллер TLC5940 рядом с используемыми контактами;
  4. После выполняется подключение контроллера TLC5940, согласно схеме подключения;
  5. Для того чтобы была возможность использовать батарею, был установлен модуль RTC на краю монтажной платы. Если припаять его посередине платы, то не будет видно обозначение контактов;
  6. Выполнено подключение модуля RTC, согласно схеме подключения;
  7. Собрана схема автоматического контроля яркости (LDR), ознакомиться можно по ссылке
  8. Выполнено подключение проводов для вольтметра, путем подключения проводов к выводу 6 и GND.
  9. В конце были припаяны 13 проводов для светодиодов (На практике оказалось, что это было лучше сделать до того, как приступать к шагу 3).

Шаг 5: Программный код

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

  • Перед прошивкой Arduino, нужно раскомментировать строку, которая устанавливает время:
    rtc.adjust(DateTime(__DATE__, __TIME__))
    После прошивки контроллера с этой строкой (время задано), нужно опять ее закомментировать и прошить контроллер заново. Это позволяет модулю RTC использовать батарею, для запоминания времени, если пропадет основное питание.
  • Каждый раз, когда вы используете "Tlc.set ()", вам нужно использовать "Tlc.update"

Шаг 6: Внешнее кольцо

Внешнее кольцо для часов было напечатано на 3D-принтере Replicator Z18. Оно прикрепляется к часам с помощью винтов на лицевой стороне часов. Ниже прилагается файл с 3D-моделью кольца для печати на 3D-принтере.

Шаг 7: Сборка часов


Микроконтроллер Arduino со всей остальной электроникой был закреплен на задней стороне часов с помощью саморезов и гаек в качестве распорок. Затем подключены все светодиоды, аналоговый вольтметр и LDR к проводам, которые ранее были подпаяны к монтажной плате. Все светодиоды соединены между собой одной ножкой и подключены к контакту VCC на контроллере TLC5940 (по кругу просто припаян кусок проволоки).

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

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

Использованы материалы:

  • - Диодная лента на микросхемах ws2811 (RGB, питание 12в) 5 метров - 700 рублей;
  • - ардуино нано - 200 рублей;
  • - датчик освещенности - 28 рублей;
  • - модуль реального времени RTC DS1307 AT24C32 - 37 рублей;
  • - преобразователь питания LM2596 - 41 рубль;
  • - блок питания 12 в 1А;
  • - датчик температуры DALLAS DS18B20 - 48 рублей;
  • - кусок макетной платы, две таковые кнопки, провода.
  • - картон жесткий.
  • - ватман (2 шт).
  • - двусторонний скотч (3М).
  • - обычный скотч.
  • - листы вспененного полиэтилена (взял из защитных упаковок оборудования).

1. Установка шрифта в MS Officce, и печать символа 8 на весь размер листа А4. Я сделал это в Visio. Внутренние полосы - границы для разметки под куски диодной ленты. Внешние границы - контуры цифр.

2. Нанесение границ кусков диодной ленты на картон

3. По следующему шаблону делаем разметку на вспененном полиэтилене, толщина 15 мм, и далее по разметке вырезаем.

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

4. По размеченным на картоне границам приклеиваем куски диодной ленты и соединяем пайкой по цепочке.

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

В итоге к часам подходит кабель, в котором:

  • +12В - на питание диодной ленты;
  • +5В - на питание модуля освещенности;
  • 0 - общий провод (минус);
  • выход данных с ардуино на диодную ленту;
  • выход сигнала с датчика освещенности на ардуино;

Схема подключения ардуино.

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

Плата коммутации с кнопками коррекции.

Алгоритм работы следующий:
Часы показывают время, дату и температуру в помещении: первые 15 секунд - время, затем 3 секунды - дату, еще 3 секунды - температуру, затем снова время. С 45-й секунды вновь дата 3 секунды, температура 3 секунды и снова время.
Когда в помещении светло - яркость отображения высокая, когда темно - снижается до минимального.

Итак, перед нашей командой из трех человек стояла задача: в очень сжатые сроки собрать небольшой аппаратный проект, желательно на платформе Arduino. Стоит оговориться, что до того момента со схемотехникой мы были знакомы, по большей части, в теории. А это значит - ни опыта работы с паяльником (практически), ни, тем более, опыта работы с Arduino.

Неожиданно мы наткнулись на , посвященную проекту Shadowplay Clock. Это настенные часы, разработанные командой венских дизайнеров, время по которым можно увидеть, дотронувшись пальцем до их центра. Светодиоды загораются в таком порядке, чтобы тень от пальца в центре показывала время. Было решено создать такие же (или очень похожие), но в домашних условиях. Вышеуказанная статья, как можно заметить, не содержит подробного описания проекта. Из всего этого следовало, что нам самим предстояло разобраться, как работает это устройство, и воплотить его в жизнь. Чем мы, собственно, и занялись.

Материалы

Для создания часов необходимы:
  • заготовки из ДВП
  • светодиодная лента на 60 диодов
  • Arduino Uno
  • модуль часов реального времени RTC DS1307
  • кнопка
  • макетная плата
  • сдвиговый регистр 74HC595 (x2)
  • 8-разрядный регистр-защелка 74HC573N (x8)
  • дешифратор 4-16 К155ИД3
  • инвертор с открытым стоком IN74HC05AN (x10)
  • блок питания

Приступим

Итак, алгоритм работы устройства:
  1. При подаче питания, светодиоды включаются в заданной комбинации. В оригинале Shadowplay загорались все светодиоды, но нам показалось, что интереснее будет запустить какую-нибудь комбинацию в качестве заставки.
  2. При нажатии кнопки (да, мы также отошли от оригинала и вставили в центр маленькую кнопку) считывается время из модуля RTC.
  3. Считанное время преобразуется в двоичный код (маску) и заносится в регистры.
  4. В зависимости от маски, зажигается необходимый диод.

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

Когда мы, наконец, определились с идеей проекта, то первым делом попытались мысленно набросать примерные варианты схем для его реализации. Основной вопрос стоял в том, каким образом адресовать 60 светодиодов. Собственно говоря, ответ на этот вопрос и определял способ построения практически всей схемы.

Первый пришедший на ум вариант был связан с использованием дешифраторов. Составленная схема представляла собой каскад из четырёх дешифраторов 4 - 16 и одного дешифратора 2 - 4, и те и другие с входами разрешения дешифрации. Такой каскад позволял обеспечивать адресацию на 64 выхода, чего с избытком хватало для подключения 60 светодиодов.

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

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

Чтобы удовлетворить это требование мы подумали, что можно дать возможность каждому светодиоду хранить своё состояние. Для этой цели хорошо подходят регистры, где каждый отдельно взятый разряд соответствует состоянию одного из светодиодов. Мы решили использовать регистры на 8 разрядов, так как они более распространённые и более практичные. Соответственно в нашей схеме нам понадобится 8 таких регистров, чтобы обеспечить поддержку 60 светодиодов.

Дальше мы задумались о том, как осуществлять управление состоянием светодиодов с Arduino через регистры. Каждый регистр для нормальной работы должен получать все 8 бит целиком. Arduino Uno, конечно, предоставляет достаточно выходов для передачи нескольких бит одновременно, но такой подход будет не рациональным. Кроме того в схеме всего 8 регистров, а значит нужно их как-то адресовать. Для этой цели мы добавили в схему дешифратор и два 8 разрядных сдвиговых регистра, соединённых каскадом. Один сдвиговый регистр хранит 8-битую маску состояний, которая будет загружена в один из 8 обычных регистров, номер которого хранится во втором сдвиговом регистре. Соответственно, ко второму сдвиговому регистру подключён дешифратор. Для этих целей вполне хватит дешифратора 3 на 8.

Чтобы убрать инверсию с нужного нам количества выходов мы использовали две микросхемы инверторов КР1533ЛН1. Это, конечно, несколько усложнило схему.

Ещё одной задачей стало рабочее напряжение светодиодов равное 12 вольтам по сравнению с 5 вольтами логических микросхем. Предложенное решение заключалось в применении инвертора с открытым стоком. Такая микросхема исполняет роль ключа, который замыкает (при логической 1) или размыкает (при логическом 0) один из контактов светодиода с землёй, тем самым включая или отключая светодиод. Схема предполагает работу от 12 вольт, в соответствии с рабочим напряжением светодиодов, поэтому чтобы получить 5 вольт для логических микросхем в схему был добавлен стабилизатор КР142ЕН5А с двумя конденсаторами.

Некоторые входы определённых микросхем подразумевают константное значение на входе, поэтому были заведены на землю или источник питания. В данном случае это следующие входы:

  • Инверсный вход сброса MR в обоих сдвиговых регистрах через нагрузочный регистр подключён к выходу стабилизатора на 5 вольт.
  • Инверсный вход разрешения выхода OE в обоих сдвиговых регистрах подключён напрямую к земле.
  • Инверсный вход разрешения дешифратора E0 подключён к земле

Управление схемой осуществляется четырьмя входами (E1, SH, ST, DS). Назначение и уровни сигнала каждого из них более подробно рассмотрим ниже:

Вход E1 предназначен для включения дешифратора. В нашем случае, изначально на дешифраторе есть два управляющих входа E1,E0, и они оба являются инверсными. Выхода будет достаточно и одного, поэтому второй (E0) можно завести на землю. Состояние дешифратора “по умолчанию” – рабочее, пока на E1 не подать высокий уровень сигнала. Для того, чтобы сделать наоборот, мы подключили данный вход к инвертору. Без этого дешифратор может выдавать неверные управляющие сигналы регистрам, например, в момент обновления данных в сдвиговом регистре. Как уже говорилось, в схеме можно использовать дешифратор 3 на 8, у которого может быть один не инверсный управляющий вход, что позволит с лёгкостью решить все описанные выше проблемы без лишних проводов и паяльника.

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

Следующие три входа предназначаются уже для управления сдвиговыми регистрами. Начать стоит с самого простого - входа данных DS. Данный вход, как уже следует из названия, предназначен для передачи данных. Так как сдвиговые регистры в схеме соединяются каскадом, то DS представляет соответствующий вывод одного из них. Вход второго сдвигового регистра соединён с выводом последнего разряда первого регистра. В результате получается один сдвиговый регистр на 16 разрядов, из которых используются только 12 разрядов.

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

Последний вывод ST служит защёлкой данных на выходах регистра. На данный вход подаётся импульс, однако подаётся только тогда, когда данные в сдвиговом регистре загружены окончательно и требуется зафиксировать их на выходе регистров. Только после подачи данного сигнала загруженные данные внутри регистра на первом ряду триггеров попадают на второй ряд триггеров и становятся доступны на шине. ST представляет собой контакт соединённый с выводами STcp обоих регистров.

Осталось пояснить разводку двух выводов сдвиговых регистров MR и OE. Первый вход (MR) отвечает за сброс данных внутри регистра. В данной схеме такая возможность не требуется, поэтому на данный вывод через нагрузку подаётся высокий уровень сигнала.

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

Ещё один не описанный выше контакт предназначен для снятия уровня сигнал с кнопки в центре часов, схема кнопки типична и представляет собой нагрузку и ключ, в зависимости от положения которого на Arduino подаётся низкий или высокий уровень сигнала. В зависимости от состояния кнопки, часы работают либо в режиме заставки, либо в режиме показа времени.
Подключение к Arduino не имеет особенностей, за исключением того что вывод SH в идеале подключаться к цифровому выводу SCK. Остальные выводы схемы могут подключаться к любому из доступных цифровых входов общего назначения. В нашем случае подключение имеет следующий вид:

  • Arduino pin13 (SCK) – вывод схемы SH
  • Arduino pin 11 – вывод схемы ST Arduino pin 8 – вывод схемы DS Arduino pin 5 – вывод схемы E1 Arduino pin 3 – вывод кнопки Arduino pin GND – земля схемы (также подключается и к земле блока питания)
    После того как с проектированием схемы было покончено, началась работа над основой для часов.

    Были сделаны заготовки из ДВП: круг диаметром 36 см - задняя часть часов; и кольцо размерами 36 см (внешний диаметр) \ 26 см (внутренний диаметр) - передняя часть. В оригинале Shadowplay имеет диаметр круга 72 см, но нам хватило и 36. На круг приклеивается светодиодная лента, предварительно разрезанная на 60 частей (диод + резистор). По границе круга просверлили отверстия. Через них провода, подключенные к светодиодам, будут соединяться с макетной платой, которая находится на обратной стороне круга.

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

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

    Макетная плата и общий вид устройства сзади.



    Да-да, нам стыдно.

    Изначально планировалось сделать точную копию Shadowplay. Однако способ, которым палец пользователя детектируется в центре устройства, не описывался в статье. Поразмышляв, мы пришли к выводу, что возможно для этих целей используется фоторезистор. Однако вскоре отказались от этой идеи, т.к. у фоторезистора возможны случайные срабатывания. Устройство может находится в условиях разной степени освещённости, а значит, не всегда сможет детектировать палец со 100% вероятностью. Предпочтение было отдано кнопке, которую мы и поместили в центр конструкции. Она обладает еще одним достоинством помимо надежности. Несмотря на ее небольшие размеры, тень от нее идеально подходит на роль стрелки часов. Таким образом, по желанию можно запрограммировать устройство на постоянную работу в режиме часов и без прикладывания пальца.

    После того, как вся схема была спаяна (долгие бессонные ночи кропотливой работы паяльником и пинцетом), выводы инверторов соединены со светодиодами, настал торжественный момент - первая попытка включить устройство. И, о чудо, диоды действительно горели! Но далеко не все. Поначалу появилось мнение, что что-то все-таки было неправильно спаяно. Однако, как выяснилось далее, причина крылась в другом. Так как при первом запуске мы подключили не все управляющие входы логических микросхем, а только лишь самые необходимые, то на оставшихся не подключенных входах образовалась неоднозначность в уровнях напряжения. К тому же, схема собиралась на макетной плате, с большой кучей проводов, а не вытравливалась.Провода были значительно подвержены электромагнитному излучению.Следовательно, при малейшем скачке напряжения из-за наводки на не подключенных входах логический элемент мог сработать. В результате любой предмет, находящийся в непосредственной близости от платы, вызывал ЭМИ и, соответственно, непредсказуемое поведение логики, а с ней и светодиодов.

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

    Программная часть

    Итак, с аппаратной частью покончено (практически). Настал черед написания программы под Arduino. Для начала, необходимо сконфигурировать модуль RTC, а именно - занести в него время. Микросхема базируется на высокоточном модуле DS1307, интерфейс подключения - I2C. Внутренний календарь в нем рассчитан до 2100 года с учетом високосных лет. Благодаря заряду батареи модуль может работать автономно около одного года. Ниже показана схема подключения RTC к Arduino, обнаруженная на этом сайте . Здесь же была взята масса информации о модуле RTC.

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

    Код

    #include #include char REG ; tmElements_t te; int c,reset=1; void setup() { pinMode(13, OUTPUT); pinMode(11, OUTPUT); pinMode(8, OUTPUT); pinMode(5, OUTPUT); pinMode(3, INPUT); Serial.begin(57600); //данный блок позволяет установить время в RTC используется однократно //te.Hour = 18; //te.Minute = 50; //te.Second = 0; //te.Day = 20; //день //te.Month = 4; // месяц //te.Year = CalendarYrToTm(2016); //RTC.write(te); } void loop() { if(digitalRead(3)) // сработает, если будет нажата кнопка {RTC.read(te); SetShadowTime(te.Hour,te.Minute,te.Second,2); // рассчитать и установить время на часах delay(900); reset=1; } else // если кнопка не нажата, установить заставку {wait1(); reset=1; } //сброс светодиодов for(int j = 0; j<8 ; j++) SetUpLightByMask(j,0); } //=======================================================================Вспомогательные функции void SetUpLightByMask(int RegNum, char LightMask) // функция подсветки светодиодов согласно полученной маске в заданном регистре { digitalWrite(5, LOW); digitalWrite(11, LOW); shiftOut(8, 13, MSBFIRST, LightMask); shiftOut(8, 13, LSBFIRST, RegNum); digitalWrite(11, HIGH); digitalWrite(5, HIGH); } void digitalClockDisplay() { //Функция вывода времени из RTC в консоль, полезна при настройке RTC RTC.read(te); Serial.print(te.Hour); Serial.print(" : "); Serial.print(te.Minute); Serial.print(" :"); Serial.print(te.Second); Serial.print(" "); Serial.print(te.Day); Serial.print(" "); Serial.print(te.Month); Serial.print(" "); Serial.print(tmYearToCalendar(te.Year)); Serial.println(); } //Функция рассчёта теневых стрелок на часах, в качестве параметров принимает часы, минуты, секунды и в качестве последнего параметра комбинацию стрелок: //0 - только часы,1 - часы и минуты, 2 - часы минуты и секунды void SetShadowTime(int Hours, int Minutes, int Seconds, int param){ int h,hshift,m,s; for(int j = 0; j<8 ; j++) REG[j] = 0; if(Hours >= 12) Hours -= 12; h = Hours + 6; if(h >= 12) h -= 12; hshift = (int) Minutes / 12; REG[(int)(((h*5)+hshift)/8)] = REG[(int)(((h*5)+hshift)/8)] | 1<<(((h*5)+hshift)%8); if(param == 1) {m = Minutes + 30; if(m ><<(m%8); } if(param == 2) {m = Minutes + 30; if(m >= 60) m -= 60; REG[(int)(m/8)] = REG[(int)(m/8)] | 1<<(m%8); s = Seconds + 30; if(s >= 60) s -= 60; REG[(int)(s/8)] = REG[(int)(s/8)] | 1<<(s%8); } for(int j = 0; j<8 ; j++) SetUpLightByMask(j,REG[j]); } void wait1() //один из вариантов функций заставки {for(int a = 0; a < 8; a++) {c=0; for(int b = 0; b < 8; b++) {c = c << 1; c = c | 1; SetUpLightByMask(a, c); delay(10); } } for(int a = 0; a < 8; a++) {c=255; for(int b = 0; b < 8; b++) {c = c << 1; SetUpLightByMask(a, c); delay(10); } } }

    Сборка

    Можно считать устройство практически готовым. Осталось лишь собрать все составные части вместе и запустить. Макетная плата и остальные запчасти (Arduino, RTC) прикрепились к задней стороне часов. Поверх круга со светодиодами закреплено кольцо, скрывающее детали реализации. Чтобы отвлечь внимание пользователя от несовершенств конструкции, кольцо расписали узором «а-ля микросхема». И наконец - включили в розетку. Результат ниже:

    Приносим извинения за качество фото.

    Вот небольшой пример того, какие комбинации можно запустить в качестве «заставки»:

    А вот, собственно, часы в рабочем состоянии:

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

    И да, предвкушая вопрос, который вы наверняка хотите задать. Как отличать часовую, минутную и секундную стрелки? Было немало споров на эту тему. Предлагались разнообразные решения данной проблемы: от разноцветной подсветки стрелок до поочередного включения стрелок (сначала часовая, через небольшой промежуток времени минутная, и т.д.). Однако, посмотрев на оригинал, мы поняли, что венские дизайнеры в принципе не озаботились данным вопросом. Было решено закрыть глаза на этот маленький недостаток. Вероятно, в будущем он будет устранен.

  • часы
  • Arduino
Добавить метки

После создания множества прототипов Arduino на макетной плате, я решил сделать что-то полезное, то, что можно использовать дома. А что может быть полезнее, чем светящиеся часы, которые почему-то с 2010 года перестали выпускаться? Начал я сборку цифровых часов с поиска необходимых деталей. Одним из критериев, который помог быстрее насобирать необходимые компоненты, стала доступность деталей в местных магазинах и от производителей из Китая, Малайзии.

Arduino часы реального времени (RTC) на 7-сегментных индикаторах

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

Вторым вариантом была идея подключения 7-сегментных LED -индикаторов к GPS модулю . Поскольку GPS сигнал дает очень точное время, этот вариант должен был решить проблему, и не пришлось бы настраивать часы каждый раз при их включении. Я взял свой карманный навигатор Garmin GPS 60 C, подключил его в последовательный разъем к Arduino и загрузил несколько библиотек GPS, получив таким образом сигнал очень точного времени.

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

Третий способ настройки часов оказался наилучшим. Заключается он в работе Arduino совместно с DS1307 часами реального времени (RTC). Питание на них идет от таблеточной 3-вольтовой батарейки, которая сохраняет настройки, когда устройство выключено и во время отсоединения микроконтроллера.

Я пошел в местный «электронный рай», расположенный в центре города, чтобы испытать свою удачу в поиске необходимых компонентов. К моему удивлению, там я нашел все необходимые детали для сборки цифровых часов.

Необходимыми деталями являются:

  1. плата Arduino для макетирования и загрузки скетча в микроконтроллер;
  2. микроконтроллер ATmega328P для работы часов;
  3. четыре красных 7-сегментных LED-индикатора (или другие, более холодного цвета, которые найдете на местном рынке);
  4. часы реального времени DS1307;
  5. кварцевый резонатор на 32,768 кГц;
  6. держатель для батарейки таблеточного размера CR2025 или CR2032;
  7. четыре микросхемы 74HC595 сдвигающего регистра для управления 7-сегментными LED-индикаторами;
  8. резисторы 220 Ом по 0.25 Вт;
  9. однорядные штыревые разъёмы;
  10. гнезда для интегральных микросхем (IC);
  11. соединительные провода.

Если нет навыков в изготовлении печатных плат, то рекомендую использовать паечную макетную плату (текстолитовая пластинка с множеством отверстий для закрепления на ней пайкой компонентов, которую ошибочно называют монтажной платой ) и припаять на неё все IC гнезда микросхем и штыревые разъёмы. Благодаря таким быстроразъемным контактам все 7-сегментные LED-индикаторы и интегральные микросхемы могут быть легко заменены при необходимости.

Поскольку размер макетной платы весьма ограничен, то удалось разместить на ней только 35-миллиметровые LED-индикаторы, ведь должно было ещё остаться место для держателя таблеточной батарейки. Хотелось бы поставить гораздо большие 7-сегментные индикаторы, но более крупным из них надо повышенное напряжение, свыше 5 В, и уже потребовалось таки усложнить схему двойными цепями питания. Иметь дело со стабилизатором на два выходных напряжения не хочется, лучше сосредоточиться на более простой версии цифровых часов.

Разделительные керамические конденсаторы 100 нФ на ножке питания Vcc каждого регистра 74HC595 добавлены, чтобы предотвратить любые проблемы с низкочастотными помехами.

Собираемые цифровые часы используют только 5 пинов Arduino:

  • 3 цифровых выхода для сдвигающих регистров 74HC595;
  • 2 аналоговых выхода для часов реального времени, подключенных с использованием соединения I2C.

Преимущество собираемых цифровых часов на Arduino в сравнении с заводскими в том, что к ним можно легко добавить любые функции, какие только могут стать полезны.

Вот некоторые идеи доработки часов:

  1. Чередование отображения на индикаторах часов/минут и минут/секунд;
  2. Проигрывание мелодии каждый час;
  3. Установка датчика LM35, и использование часов в качестве термометра;
  4. Функция утреннего будильника;
  5. Даже управление другими электрическими приборами с помощью электромеханического реле, включающегося в соответствии с определёнными по времени событиями или показаниями подключенных датчиков.

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

После того, как я припаял первую цифру 7 сегментного LED-индикатора с общим катодом к сдвигающему регистру 74HC595, открылась первая проблема. Я использовал только один резистор 220 Ом, соединенный с общим катодом LED-индикатора, чтобы сберечь резисторы, и обнаружил, что когда включается число 8, то все сегменты загораются очень тускло. Это нормально для прототипа, но не годится для действующих цифровых часов. Было бы очень неприятно иметь часы с по-разному светящимися цифрами. Так что пришлось разорвать отдельные провода и раздобыть побольше резисторов на 220 Ом, чтобы подключить их к каждому из семи сегментов LED-индикатора.

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

Поскольку слишком много труда уходит на пайку одного индикатора, вместе с присоединением всех резисторов к проводам, я решил сделать выносную платку с двумя светодиодами в качестве индикаторов секунд. Я найду способ установки двух точек между часовыми и минутными цифрами! На фотографии внизу, я просто снимаю по светодиоду на 13 выводе мигания с интервалом в 500 мс.

  • Есть коды .
  • Окончательный скетч

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

Эти часы запитаны от выносной платы Arduino в версии с FTDI кабелем и гнездом DC постоянного тока.

Сборка Arduino часов завершена после установки DHT11 датчика влажности и температуры.

Самодельный датчик температуры и влажности DHT11 и DHT22 – подключение к Arduino GPS часы на Arduino

Понравилась статья? Поделитесь ей