BigClock.jpg


Я никогда не хотел себе домой часы. Наручные или в телефоне — их вполне достаточно, чтоб ориентироваться во времени. А вот о какой-нибудь подсветке в комнату я периодически помышляю. При этом у меня, как и у многих других, стоит лампа на столе и с потолка свисает скучная люстра.


Сидеть в самоизоляции и полумраке — та ещё перспектива. Так светодиодная лента и картонные упаковки из Икеа на ресайклинг стали отличным условием «дано» для светодиодного табло, которое я полюбил.


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


Часы. Большие часы. Слышу доносящиеся откуда-то голоса, а воображение начинает выстраивать всяческие образы.


Самым простым и понятным мне показался вариант в виде семисегментных индикаторов. А что? Сделаю каркас из гофрокартона, нарежу отрезков светодиодной ленты и закреплю их на нём в форме восьмёрки. Звучит несложно.


Что для этого понадобится


Есть 100 вариантов, где можно достать железо для этого проекта. Никаких особых, редких или проприетарных модулей в нём нет; главное — концепция. Я, однако, работаю в Амперке, поэтому взял всё необходимое в конторе. Чего и вам желаю.
Итак, мой комплект:


Материалы:



Инструменты:



Как собрать


Я как ниндзя вырезал канцелярским ножом основу для будущего индикатора.


ninja-cut.gif


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


led-wire.jpg


На одну из сторон индикатора (теперь она будет тыльной) наклеил дополнительные «прямоугольнички», вырезанные из того же картона вдоль рёбер жёсткости. Сквозь эти рёбра я пущу провода от сегментов.


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


Wire-chanel.jpg


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


cylinder.gif


Готовые цилиндры приклеил к каркасу индикатора и пропустил провода в отверстия.


join-cylinder.jpg


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


cable-management.gif


Торцы цилиндров я закрыл заглушками, вырезанными всё из того же картона.


stub.jpg


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


laser-cut.jpg


Иначе стоит запастись терпением, вырезая такое количество деталей канцелярским ножом.


Управление


Когда индикатор собран — самое время подумать, как им рулить.
И тут меня поджидало несколько «сюрпризов».


Сюрприз первый. Ток


Привычными индикаторами, каждый сегмент которых потребляет всего 20-30 мА, можно управлять напрямую контроллером. Например, с входов-выходов популярной Arduino Uno можно снять до 40 мА.


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


commutation.jpg


Реле — шумно и громоздко для такой задачи, а вот силовые ключи на MOSFET-транзисторах — кажется, то, что нужно.


Сюрприз второй. Контакты


Чтобы управлять одним индикатором, понадобится 7 выходов микроконтроллера. Четыре индикатора и разделитель — это 29, а у Ардуино Уно выходов всего 20.


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


display.jpg


Третий сюрприз. Габариты


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


a-lot-of-fets.jpg


Решение всех проблем!


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


octofet.jpg


Подключение


Провода от каждого сегмента индикатора я подключил к клеммникам выходов Octofet’а.


Connection.png


А сам Octofet, чтобы не болтался, закрепил на основании, которое тоже вырезал из картона.


connectOctofet.jpg


Подключать модули к Ардуино я буду через Troyka Shield. Остаётся просто соединить всё шлейфами.


Arduino-Test-Connection.png


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


bitmap.gif


Прошивка


Программировать контроллер буду через Arduino IDE.
Для работы с Octofet’ом и часами реального времени дополнительно надо будет скачать и установить пару библиотек.



Чтобы проверить, всё ли правильно собрано, в Arduino нужно загрузить тестовый скетч.


// библиотека для работы с модулями по интрефейсу SPI
#include <SPI.h>
// библиотека для работы со сборкой силовых ключей
#include <AmperkaFET.h>
// пин выбора устройства на шине SPI
#define PIN_CS  2

// кол-во сегментов в индикаторе
#define SEGMENT_COUNT       8

// префикс «0b» означает, что целое число за ним записано в
// в двоичном коде. Единицами мы обозначим номера сегментов
// индикатора, которые должны быть включены для отображения
// арабской цифры. Всего цифр 10, поэтому в массиве 10 чисел.
// Нам достаточно всего байта (англ. byte, 8 бит) для хранения
// комбинации сегментов для каждой из цифр.
byte numberSegments[10] = {
  0b11101110, 0b00100100, 0b11110010, 0b10110110, 0b00111100,
  0b10011110, 0b11011110, 0b00100110, 0b11111110, 0b10111110,
};

// создаём объект mosfet для работы со сборкой силовых ключей
// передаём номер пина выбора устройства на шине SPI
FET mosfet(PIN_CS);

void setup()
{
  // начало работы с силовыми ключами
  mosfet.begin();
}

void loop()
{
  // определяем число, которое собираемся отображать. Пусть им
  // будет номер текущей секунды, зацикленный на десятке
  int number = (millis() / 1000) % 10;
  // получаем код, в котором зашифрована арабская цифра
  int mask = numberSegments[number];
  // для каждого из 7 сегментов индикатора...
  for (int i = 0; i < SEGMENT_COUNT; ++i) {
    // ...определяем, должен ли он быть включён. Для этого
    // считываем бит (англ. read bit), соответствующий текущему
    // сегменту «i». Истина — он установлен (1), ложь — нет (0)
    boolean enableSegment = bitRead(mask, i);
    // включаем/выключаем сегмент на основе полученного значения
    mosfet.digitalWrite(i, enableSegment);
  }
}

Если всё сделано верно, заветные цифры начнут загораться на индикаторе.


singleDigit.gif


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


fullSchem.png


Исходный код


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


// библиотека для работы с модулями по интерфейсу SPI
#include <SPI.h>
// библиотека для работы I²C
#include <Wire.h>
// библиотека для работы со сборкой силовых ключей
#include <AmperkaFET.h>
// библиотека для работы с часами реального времени
#include <TroykaRTC.h>
// пин выбора сборки устройств на шине SPI
#define PIN_CS  2

// префикс «0b» означает, что целое число за ним записано в
// в двоичном коде. Единицами мы обозначим номера сегментов
// индикатора, которые должны быть включены для отображения
// арабской цифры. Всего цифр 10, поэтому в массиве 10 чисел.
// Нам достаточно всего байта (англ. byte, 8 бит) для хранения
// комбинации сегментов для каждой из цифр.
byte numberSegments[10] = {
  0b11101110, 0b00100100, 0b11110010, 0b10110110, 0b00111100,
  0b10011110, 0b11011110, 0b00100110, 0b11111110, 0b10111110,
};

// создаём объект mosfet для работы со сборкой силовых ключей
// передаём номер пина выбора устройств на шине SPI
// и количество устройств подключённых в цепочке
FET mosfet(PIN_CS, 4);

// создаём объект для работы с часами реального времени
RTC clock;

void setup() {
  // начало работы с силовыми ключами
  mosfet.begin();
  // инициализация часов
  clock.begin();
  // метод установки времени и даты в модуль вручную
  // clock.set(10,25,45,27,07,2005,THURSDAY);    
  // метод установки времени и даты автоматически при компиляции
  clock.set(__TIMESTAMP__);
}

void loop() {
  // запрашиваем данные с часов  
  clock.read();

  // делим минуты и часы на разряды и отображаем на индикаторах
  showDigit (0, clock.getHour() / 10);
  showDigit (1, clock.getHour() % 10);
  showDigit (2, clock.getMinute() / 10);
  showDigit (3, clock.getMinute() % 10); 

  // мигаем разделителем
  mosfet.digitalWrite(1, 0, HIGH);  
  delay(1000);
  mosfet.digitalWrite(1, 0, LOW);
  delay(1000);
}

void showDigit (int module, int digit ){
  // получаем код, в котором зашифрована арабская цифра
  int mask = numberSegments[digit];
  // для каждого из 7 сегментов индикатора...
  for (int i = 0; i < 8; ++i) {
    // ...определяем, должен ли он быть включён. Для этого
    // считываем бит (англ. read bit), соответствующий текущему
    // сегменту «i». Истина — он установлен (1), ложь — нет (0)
    boolean enableSegment = bitRead(mask, i);
    // включаем/выключаем сегмент на основе полученного значения
    mosfet.digitalWrite(module, i, enableSegment);
  }
}

Чтобы после прошивки и включения часов время считывалось с модуля RTC,
закомментируйте оба метода clock.set() и загрузите код снова;

То, что получилось, мне очень нравится. Зацените сами!


i-did-it.jpg


Добавлю сюда кнопку или даже ИК-приемник, чтобы дистанционно включать и выключать свет обычным пультом от телека или кондиционера. И будет вообще огонь!


Это лишь пример того, как поступил я. Вы можете сделать девайс по-своему. Добавьте сюда, что угодно! Модуль Bluetooth для настройки и управления, или звуковое оповещение зуммером, чтобы превратить часы в будильник. А лучше и то, и другое.


На этом у меня всё!


Пока!

Комментарии (33)