Цифровые часы с большим индикатором

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

bigtimefront

Большие часы времени, основанные на ATtiny3216, используют гигантские 7-сегментные светодиодные дисплеи. Коробок для масштаба.

Введение

Эти часы были были задуманы как идея использования 2.3" одноразрядных 7-сегментных индикаторов, которые я видел на AliExpress. Я решил, что было бы интересно иметь часы, которые  можно ясно видеть издалека. Дисплеи бывают разных цветов и напряжений; я выбрал красные версии 4V, чтобы я мог управлять ими непосредственно от линий ввода/вывода микроконтроллера без необходимости использования транзисторов. Мои дисплеи имеют общий катод, но при небольшом изменении в программе можно работать и с дисплеями собщим анодом.

Схема

Вот такая схема:

bigtime

Схема больших часов времени, основанная на ATtiny3216.

Схема основана на одном из новых контроллеров ATtiny, которые имеют встроенный счетчик часов реального времени, который можно тактироватьс внешнего кварца на 32.768 кГц. Я выбрал ATtiny3216, 20-контактный микроконтроллер с 32кбайт флэш-памяти, который имеет достаточно линий ввода/вывода, чтобы управлять дисплеями простым способом, не прибегая к методу чарлиплексинга.

Токоограничивающие резисторы последовательно соединены с каждым сегментом для обеспечения постоянной яркости дисплея. Кнопка предусмотрена, чтобы устанавливать время, также  установлен разъем, подключенный выводу UPDI для программирования ATtiny3216, и вохд, RX, в случае, если вы захотите подключить часы к модулю GPS.

 

Сборка

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

bigtime3

ATtiny3216 в корпусе SOIC,  резисторы и конденсатор размера 0805 установлены на главной плате.

bigtimeboard

Задняя часть главной главной платы часов.

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

Я установил восемь 5-контактных разъемов для подключения индикаторов, но вы можете также просто припаять их.

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

Программа

Отображение цифр

Индикация на 7-сегментных индикаторах обновляется из четырех значений в масиве Digits[], используя прерывания, генерируемые таймером / счетчиком часов. Например:

Digits[0] = 1; 
Digits[1] = 2;
Digits[2] = 3;
Digits[3] = 4;

будет отображаться "1234". Дисплей настраивается с помощью обычной функции DisplaySetup():

void DisplaySetup () {
 // Драйверы сегментов
 ВОРОТА.DIR = PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm; / / установить PA4-PA7 в качестве выходных данных
 PORTC.DIR = PIN0_bm | PIN1_bm | PIN2_bm | PIN3_bm; / / установить PC0-PC3 в качестве выходов
 // Драйверы цифр
 PORTB.DIR = PIN0_bm | PIN1_bm | PIN4_bm | PIN5_bm; / / установить выходы PB0 PB1 PB4 PB5
 PORTB.OUT = PIN0_bm / PIN1_bm | PIN4_bm | PIN5_bm; / / установить PB0 PB1 PB4 PB5 high
 // Настройка таймера / счетчика для мультиплексирования дисплея
 TCB0.CCMP = 19999; / / разделить 5 МГц на 20000 = 250 Гц
 TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; / / включить таймер, разделить на 1
 TCB0.CTRLB = 0; / / режим периодического прерывания
 TCB0.INTCTRL = TCB_CAPT_bm; / / включить прерывание
}

Это во-первых делает все сегментные и цифровые линии выходами, и устанавливает четыре выхода PB0, PB1, PB4 и PB5 в высокий уровень, чтобы погасить цифры.

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

Подпрограмма службы прерывания часов просто очищает прерывание и вызывает функцию DisplayNextDigit():

ISR(TCB0_INT_vect) {
 TCB0.INTFLAGS = TCB_CAPT_bm; / / снимает флаг прерывания
 DisplayNextDigit();
}

Текущая цифра хранится в глобальной переменной Digit . Каждый вызов функции DisplayNextDigit () выключает текущую цифру, задает сегменты для следующей цифры, а затем включает ее:

void DisplayNextDigit() 
{
PORTB.OUTSET = 1<<Pins[Digit]; // Take digit high
Digit = (Digit+1) % Ndigits;
uint8_t segs = charArray[Digits[Digit]];
PORTA.OUT = segs & 0xF0; // Set PA4-PA7
PORTC.OUT = segs & 0x0F; // Set PC0-PC3
PORTB.OUTCLR = 1<<Pins[Digit]; // Take digit low
}

Кнопка установки времени

Кнопка Set Time позволяет установить часы на правильное время. При удержании ее нажатой,  значение часов увеличивается дважды в секунду. При отпускании и снова нажатии накнопку, значение минут увеличивается два раза в секунду.

Кнопка использует порт ввода-вывода PA1 и подтягивается к питанию:

void ButtonSetup () 
{ PORTA.PIN1CTRL = PORT_PULLUPEN_bm; // PA1 input pullup
}

Состояние кнопки считывается методом ButtonDown (), который возвращает true, если кнопка нажата:

boolean ButtonDown () 
{
return (PORTA.IN & PIN1_bm) == 0; // True if button pressed
}

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

Периферийное устройство часов реального времени настроено как периодический таймер прерывания (PIT), генерирующий регулярное прерывание. В этом проекте для прерывания используется делитель 16384, который делит частоту кварца 32.768 кГц, чтобы дать два прерывания в секунду; это позволяет прерыванию увеличивать значений часов или минут дважды в секунду при настройке времени.

Подпрограмма обработки прерывания вычисляет текущее время в часах и минутах из глобальной переменной Time in half-seconds. Если кнопка Set Time не нажата, то она увеличивает время и обновляет массив Digits[] текущими значениями:

ISR(RTC_PIT_vect) 
{ int minutes, hours;
RTC.PITINTFLAGS = RTC_PI_bm; // Clear interrupt flag
minutes = (Time / 120) % 60;
hours = (Time / 7200) % 12;
if (ButtonDown())
{ if (ButtonState == 1 || ButtonState == 3)
{ ButtonState = (ButtonState + 1) % 4;
}
if (ButtonState == 0)
{ // Advance hours
hours = (hours + 1) % 12;
minutes = 0;
}
else { // Advance minutes
minutes = (minutes + 1) % 60;
}
Time = (unsigned long)hours * 7200 + minutes * 120;
}
else
{ // Button up
if (ButtonState == 0 || ButtonState == 2)
{ ButtonState = (ButtonState + 1) % 4;
}
Time = (Time + 1) % 172800; // Wrap around after 24 hours
}
Digits[0] = (hours+1)/10;
Digits[1] = (hours+1)%10;
Digits[2] = minutes/10;
Digits[3] = minutes%10;
}

Нажатие кнопки Set Time приводит к переходу переменной ButtonState между двумя состояниями: 1, которое изменяет значения часов, и 3, которое изменяет значения минут. В промежуточных состояниях 0 и 2 часы работают нормально.

Компиляция программы

Скомпилируйте программу с помощью megaTiny Core от Spence Konde's на GitHub. Выберите ATtiny3216/1616/1606/816/806/416/406 в разделе megaTinyCore в меню платы. Убедитесь, что последующие параметры установлены следующим образом (игнорируйте любые другие параметры):

Чип: "ATtiny3216"
тактовая частота:" 5 МГц "
программатор:" jtag2updi (megaTinyCore)"

Затем загрузите программу в контроллер с помощью программатора UPDI. В качестве альтернативы вы можете сделать программатор UPDI из Arduino Uno или другой платы на основе ATmega328P, как описано здесь.

Вы можете игнорировать ошибку "не удается найти Флэш-и загрузочные накопители в описании".

Вот весь текст программы: bigtime.txt .

Изготовление печатной платы

Скачать файлы Eagle для печатных плат часов с GitHub : https://github.com/technoblogy/big-time .

Дальнейшие предложения

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

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

Перевод с английского

Загрузка...