Как подключить 7-сегментный индикатор к arduino

Программа индикации на многоразрядном семисегментном индикаторе

Как я уже писал в другой статье — АЛГОРИТМ — предшественник программы, и чем продуманнее он будет написан, тем легче будет писать программу.

Назначение переменных:

Давайте посмотрим какие переменные для работы подпрограммы вывода данных на индикатор назначил я:

Data0, Data1 и  Data2 — переменные, в которые основная программа записывает вычисленное значение (трехзначное)Data — переменная, в которой записан адрес первой переменной данных — Data0@Data — эта запись означает, что в переменной Data будет храниться адрес первой переменной данных — Data0DataIndex — эта переменная хранит текущий номер переменной данных, которая выводилась на индикацию последней (0, 1 или 2, соответственно для Data0, Data1 или Data2)PortDigits — эта переменная хранит данные о том, какой разряд индикатора зажигался последним

Настройка стека:

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

Настройка восьмиразрядного таймера Taimer0:

Taimer0 в подпрограмме используется как средство обеспечивающее динамическую индикацию разрядов индикатора

Настроенный таймер через определенные промежутки времени вызывает прерывание, в результате чего происходит остановка основной программы и осуществляется переход в подпрограмму обработки прерывания. В нашем случае — вызывается подпрограмма вывода данных на индикатор.Как настраивается таймер: Частота переключения разрядов должна быть в пределах 100 Гц  для предотвращения мерцания индикаторов при их поочередном зажигании (дело это в принципе индивидуальное, и зависит от особенностей вашего зрения).Тактовая частота микроконтроллера — 1 мГц, или 1 000 000 Гц Устанавливаем внутренний делитель частоты таймера в СК/8 — рабочая частота таймера будет в 8 раз меньше тактовой частоты микроконтроллера Получаем: 1000 000/8 = 125 000 Гц, или 125 кГц — тактовая частота таймера Настраиваем вызов прерывания по переполнению счетчика таймера (счетчик таймера восьмиразрядный и считает до 255, после этого сбрасывается в ноль и вызывается прерывание) Получаем: 125 000/255 = 490 Гц (что соответствует времени приблизительно в 2 миллисекунды) Мы поочередно зажигаем три разряда: Получаем: 490/3 = 163 Гц — разряды индикатора будут переключаться с частотой 163 Гц.
Настройка таймера производится соответствующей настройкой соответствующих регистров таймера.Давайте посмотрим как это происходит в Algorithm Builder:

Инициализация индикатора

Инициализация индикатора — эта фраза подразумевает настройку разрядов портов, к которым подключены выводы индикатора на вывод, а также обнуление переменных данных Data0…2 и запись первоначальных данных в остальные переменные. Процесс инициализации индикатора прописывается в начале основной программы.
Назовем подпрограмму инициализации Ini_Indikator2/Давайте посмотрим этот процесс на примере:

В первой строке разряды порта РВ с 0 по 6 (к которым подключены семь сегментов индикатора) настраиваются на вывод информации (десятичную точку индикатора не используем).Во второй строке разряды порта PD с 0 по 2 (к которым подключены управляющие транзисторы) также настраиваются на вывод.Третьей строкой на выходах порта РВ устанавливается логический ноль — сегменты индикатора погашены для индикаторов с общим катодом).Четвертая строка — обнуляем переменную DataIndexПятая строка — в переменную PortDigits записываем единицуСледующие три строки — обнуляем переменные данных

Теперь нам необходимо куда-то записать двоичные коды цифр которые будут подаваться на разряды порта PB для высвечивания соответствующей цифры на индикаторе.
В статье по программированию работы одноразрядного семисегментного индикатора, мы эти коды записывали программным путем в ОЗУ микроконтроллера. Сейчас мы сделаем по-другому — запишем двоичные коды в теле самой программы.
Для этого создадим таблицу двоичных кодов и присвоим ей имя, к примеру D0_9:

В этой таблице размещены двоичные коды (хотя и записаны в шестнадцатиричной системе) цифр от 0 до 9.

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

Программирование

7segment.pde
#define CLOCK_PIN 2
#define RESET_PIN 3
 
/*
 * Функция resetNumber обнуляет текущее значение
 * на счётчике
 */
void resetNumber()
{
    // Для сброса на мгновение ставим контакт
    // reset в HIGH и возвращаем обратно в LOW
    digitalWrite(RESET_PIN, HIGH);
    digitalWrite(RESET_PIN, LOW);
}
 
/*
 * Функция showNumber устанавливает показания индикаторов
 * в заданное неотрицательное число `n` вне зависимости
 * от предыдущего значения
 */
void showNumber(int n)
{
    // Первым делом обнуляем текущее значение
    resetNumber();
 
    // Далее быстро «прокликиваем» счётчик до нужного
    // значения
    while (n--) {
        digitalWrite(CLOCK_PIN, HIGH);
        digitalWrite(CLOCK_PIN, LOW);
    }
}
 
void setup()
{
    pinMode(RESET_PIN, OUTPUT);
    pinMode(CLOCK_PIN, OUTPUT);
 
    // Обнуляем счётчик при старте, чтобы он не оказался
    // в случайном состоянии
    resetNumber();
}
 
void loop()
{
    // Получаем количество секунд в неполной минуте
    // с момента старта и выводим его на индикаторы
    showNumber((millis()  1000) % 60);
    delay(1000);
}

Программирование одноразрядного семисегментного индикатора

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

Алгоритм подпрограммы:

1. Инициализация индикатора (подпрограмма)
— настройка порта, к которому подключен индикатор на вывод информации
— запись кодов семисегментного индикатора, соответствующих десятичным цифрам в определенные ячейки памятиДанная подпрограмма должна вызываться отдельно из основной программы2. Вход в основную подпрограмму3. Основная часть
— считываем текущую цифру
— определяем какой код семисегментного индикатора соответствует текущей десятичной цифре
— записываем определенный код индикатора в порт микроконтроллера4. Выход из подпрограммы

Для оформления программы в виде подпрограммы нам необходимо проделать ряд действий:1. Присваиваем имя подпрограмме инициализации индикатора — Ini_Indiкator_1 (к примеру)2. Присваиваем имя основной подпрограмме — Indicator_13. Присваиваем имена переменным SRAM в которых будут храниться коды семисегментного индикатора, к примеру:
— D0 (для цифры 0, и так далее), D1, D2, D3, D4, D5, D6, D7, D8, D9
— присваиваем имя переменной в которой будет хранится адрес ячейки памяти (D0) с  кодом первой цифры (0)  — D0_94. Присваиваем имя переменной, в которой будет хранится текущая цифра, которую необходимо вывести на индикатор. В эту переменную основная программа будет записывать вычисленные данные (цифры), которые мы выводим на индикатор — Data (к примеру).

Вот как, к примеру, в Algorithm Builder (остальные примеры тоже для этой программы), объявляются имена переменных в памяти программ (ОЗУ, SRAM):

В графе «Name» перечислены все имена переменных. В графе «Adress» запись «@D0_9» означает, что в переменной D0_9 хранится адрес первой переменной (D0)

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

А теперь давайте посмотрим основную часть программы и расшифруем ее:

Основная программа записала в назначенную нами переменную Data текущую цифру (для примера — цифра 6) и для вывода ее на индикатор вызвала подпрограмму Indikator_1.

Работа подпрограммы:
— Содержимое переменной Data записывается в рабочий регистр R20, теперь в регистре число 6 (рабочий регистр может быть любой)
— Допустим, первая переменная с кодом цифры  у нас находится в ячейки памяти по адресу 100. На самом деле мы не знаем адреса ячеек памяти где хранятся значения D0…D9, но они точно следуют друг за другом. Поэтому была назначена переменная D0_9, в которой, как мы назначили, хранится адрес ячейки памяти D0 (в данный момент адрес =100).- Следующей командой:@D0_9 —> Y мы загружаем в двойной регистр Y адрес переменной D0 и получаем, что в регистре Y записалось число — 100.- Следующей командой:Y + R20 мы складываем число 100 с числом 6, результат = 106 при этом сохраняется в двойном регистре Y.- Следующей командой: —> R20 мы записываем содержимое ячейки памяти, расположенной по адресу, который записан в двойном регистре Y (106), а по этому адресу у нас расположена ячейка памяти переменной D6. Теперь в рабочем регистре R20 записано число 7Dh — код семисегментного индикатора для вывода цифры 6.- Следующей командой:R20 —> PortB мы выводим содержимое R20 в порт PB — высвечиваем цифру 6- Возвращаемся из подпрограммы

Надеюсь, что материал изложен доступно, если что-то не понятно, спрашивайте.

Часть 1: Семисегментный светодиодный индикатор: описание, подключение к микроконтроллеруЧасть 3: Многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации

Семисегментный индикатор: программированиеСемисегментный индикатор: подключение, программирование, перевод двоичного кода числа в код семисегментного индикатора
Published by: Мир микроконтроллеров

Date Published: 10/02/2015

Трехразрядные устройства

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

Тетроды в данном случае пороговое напряжение обязаны выдерживать на уровне 15 В. Проводимость их зависит от частотности конденсаторов. Многие специалисты при сборе часов советуют преобразователи устанавливать с тиристором. В данном случае блок питания можно использовать без усилителя. Для подключения индикаторов понадобятся проводники. Для безопасного использования прибора их необходимо изолировать.

Цепь для сегмента ‘а’

Из таблицы истинности видно, что сегмент а должен быть включен всегда, кроме цифры 1 и 4. Для упрощения можно сделать так, чтобы логическая единица была только в этих 2 состояниях, и на выход добавить логическое НЕ. Тогда у нас всегда будет 1, кроме 2-ух состояний. Вот схема:

Я добавил дополнительную инвертированную шину для удобства и наглядности.

На выходе должен быть логический при входных значениях 0 0 0 1 и 0 1 0 0 (на линиях 3, 2, 1, 0 соответственно). Поэтому я взял не инвертированную первую линию, а все остальные инвертированные, и получилось, что 0 0 0 1 трансформируется в 1′ 1′ 1′ 1 ( ‘ — инвертированный сигнал), после все эти сигналы группируются в один общий, который идет в вентиль ИЛИ-НЕ, который на конце и инвертирует логическую 1 в 0, чтобы при этих входных параметрах сегмент а не был включен. То же самое проделывается для другого случая: 0 1 0 0 преобразуется в 1′ 1 1′ 1’ и также идет в тот же вентиль ИЛИ-НЕ, как и при первом случае.

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

Исходный код программы на Python

В результате исполнения данной программы на семисегментном индикаторе будут последовательно высвечиваться цифры от 0 до 9.

Python

import RPi.GPIO as IO # подключение библиотеки для работы с контактами ввода/вывода
import time # подключение библиотеки для работы с задержками
DISPLAY = # строка с шестнадцатеричными кодами, которые используются для отображения цифр на семисегментном индикаторе
IO.setwarnings(False) # отключаем показ любых предупреждений
IO.setmode (IO.BCM) # мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть мы будем обращаться к PIN29 как ‘GPIO5’
IO.setup(13,IO.OUT) # инициализируем контакты GPIO в качестве цифровых выходов
IO.setup(6,IO.OUT)
IO.setup(16,IO.OUT)
IO.setup(20,IO.OUT)
IO.setup(21,IO.OUT)
IO.setup(19,IO.OUT)
IO.setup(26,IO.OUT)
IO.setup(12,IO.OUT)
def PORT(pin): # функция для передачи значения ‘pin’ на выходные контакты
if(pin&0x01 == 0x01):
IO.output(13,1) # если bit0 из 8bit ‘pin’ is true, на PIN13 устанавливаем high
else:
IO.output(13,0) # если bit0 из 8bit ‘pin’ is false, на PIN13 устанавливаем low
if(pin&0x02 == 0x02):
IO.output(6,1) # если bit1 из 8bit ‘pin’ is true, на PIN6 устанавливаем high
else:
IO.output(6,0) # если bit1 из 8bit ‘pin’ is false, на PIN6 устанавливаем low
if(pin&0x04 == 0x04):
IO.output(16,1)
else:
IO.output(16,0)
if(pin&0x08 == 0x08):
IO.output(20,1)
else:
IO.output(20,0)
if(pin&0x10 == 0x10):
IO.output(21,1)
else:
IO.output(21,0)
if(pin&0x20 == 0x20):
IO.output(19,1)
else:
IO.output(19,0)
if(pin&0x40 == 0x40):
IO.output(26,1)
else:
IO.output(26,0)
if(pin&0x80 == 0x80):
IO.output(12,1) # если bit7 из 8bit ‘pin’ is true, на PIN12 устанавливаем high
else:
IO.output(12,0) # если bit7 из 8bit ‘pin’ is false, на PIN12 устанавливаем low
while 1:
for x in range(10): # цикл, который исполняется 10 раз, в нем переменная x инкрементируется от 0 до 9
pin = DISPLAY # присваиваем значение переменной ‘pin’ для каждой цифры
PORT(pin); # показываем каждую цифру на семисегментном индикаторе
time.sleep(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

importRPi.GPIO asIO# подключение библиотеки для работы с контактами ввода/вывода

importtime# подключение библиотеки для работы с задержками

DISPLAY=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67# строка с шестнадцатеричными кодами, которые используются для отображения цифр на семисегментном индикаторе

IO.setwarnings(False)# отключаем показ любых предупреждений

IO.setmode(IO.BCM)# мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть мы будем обращаться к PIN29 как ‘GPIO5’

IO.setup(13,IO.OUT)# инициализируем контакты GPIO в качестве цифровых выходов

IO.setup(6,IO.OUT)

IO.setup(16,IO.OUT)

IO.setup(20,IO.OUT)

IO.setup(21,IO.OUT)

IO.setup(19,IO.OUT)

IO.setup(26,IO.OUT)

IO.setup(12,IO.OUT)

defPORT(pin)# функция для передачи значения ‘pin’ на выходные контакты

if(pin&0x01==0x01)

IO.output(13,1)# если  bit0 из 8bit ‘pin’ is true, на PIN13 устанавливаем high

else

IO.output(13,)# если  bit0 из 8bit ‘pin’ is false, на PIN13 устанавливаем low

if(pin&0x02==0x02)

IO.output(6,1)# если  bit1 из 8bit ‘pin’ is true, на PIN6 устанавливаем high

else

IO.output(6,)# если  bit1 из 8bit ‘pin’ is false, на PIN6 устанавливаем low

if(pin&0x04==0x04)

IO.output(16,1)

else

IO.output(16,)

if(pin&0x08==0x08)

IO.output(20,1)

else

IO.output(20,)

if(pin&0x10==0x10)

IO.output(21,1)

else

IO.output(21,)

if(pin&0x20==0x20)

IO.output(19,1)

else

IO.output(19,)

if(pin&0x40==0x40)

IO.output(26,1)

else

IO.output(26,)

if(pin&0x80==0x80)

IO.output(12,1)# если  bit7 из 8bit ‘pin’ is true, на PIN12 устанавливаем high

else

IO.output(12,)# если  bit7 из 8bit ‘pin’ is false, на PIN12 устанавливаем low

while1

forxinrange(10)# цикл, который исполняется 10 раз, в нем переменная x инкрементируется от 0 до 9

pin=DISPLAYx# присваиваем значение переменной ‘pin’ для каждой цифры

PORT(pin);# показываем каждую цифру на семисегментном индикаторе

time.sleep(1)

История

представление фигур можно найти в патентах еще в 1903 году (в ), когда Карл Кинсли изобрел метод телеграфной передачи букв и цифр и их печати на ленте в сегментированном формате. В 1908 году Ф. В. Вуд изобрел 8-сегментный дисплей, на котором число 4 отображалось на диагональной полосе ( ). В 1910 году на сигнальном табло котельной электростанции был установлен семисегментный индикатор, освещенный лампами накаливания. Они также использовались, чтобы показывать набранный телефонный номер операторам при переходе от ручного набора номера к автоматическому. Они не получили широкого распространения до появления светодиодов в 1970-х годах.

Семисегментный дисплей с нитью

Некоторые ранние семисегментные дисплеи использовали нити накаливания в вакуумированной лампочке; они также известны как нумитроны. Вариант (минитроны) использовал вакуумированный горшок . Минитроны — это сегментные дисплеи с нитью накала, которые размещены в DIP-корпусах, как современные сегментные светодиодные дисплеи. В них может быть до 16 сегментов . Были также сегментные дисплеи, в которых вместо светодиодов или нитей накаливания использовались маленькие лампы накаливания. Они работали так же, как современные сегментные светодиодные дисплеи.

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

Многие ранние (около 1970-х годов) светодиодные семисегментные дисплеи имели каждую цифру на одном кристалле . Это сделало цифры очень маленькими. Некоторые добавили в дизайн увеличительные линзы, чтобы цифры были более разборчивыми.

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

Для многих приложений точечно-матричные ЖК-дисплеи в значительной степени вытеснили светодиодные дисплеи в целом, хотя даже в ЖК-дисплеях широко распространены семисегментные дисплеи. В отличие от светодиодов, формы элементов ЖК-панели являются произвольными, поскольку они формируются на дисплее с помощью фотолитографии . Напротив, формы светодиодных сегментов имеют тенденцию быть простыми прямоугольниками , что отражает тот факт, что им необходимо физически придавать форму, что затрудняет формирование более сложных форм, чем сегменты 7-сегментных дисплеев. Однако высокий коэффициент распознавания семисегментных дисплеев и сравнительно высокий визуальный контраст, достигаемый такими дисплеями по сравнению с точечно-матричными цифрами, делают семисегментные многозначные ЖК-экраны очень распространенными на базовых калькуляторах .

Семисегментный дисплей вдохновил дизайнеров шрифтов на создание шрифтов, напоминающих этот дисплей (но более разборчивых), таких как New Alphabet , «DB LCD Temp», «ION B» и т. Д.

Используя ограниченный диапазон букв, которые выглядят как (перевернутые) цифры, семисегментные дисплеи обычно используются школьниками для формирования слов и фраз с использованием техники, известной как « калькулятор орфографии ».

Устройство

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

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

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

Своё название семисегментные индикаторы получили в связи с тем, что изображение символа формируется с помощью семи отдельно управляемых (подсвечиваемых светодиодом) элементов – сегментов. Эти элементы позволяют отобразить любую цифру 0..9, а также некоторые другие символы, например: ‘-‘, ‘A’, ‘b’, ‘C’, ‘d’, ‘E’, ‘F’ и другие.

Это даёт возможность использовать индикатор для вывода положительных и отрицательных десятичных и шестнадцатеричных чисел и даже текстовых сообщений. Обычно индикатор имеет также восьмой элемент – точку, используемую при отображении чисел с десятичной точкой. Сегменты индикатора обозначают буквами a, b, …, g (a – верхний элемент, далее буквы присваиваются сегментам по часовой стрелке; g – центральный сегмент; dp – точка). 8 независимых элементов, каждый из которых может находиться в одном из двух состояний – горит или не горит, дают всего 2**8=256 возможных комбинаций. Или 128 комбинаций, каждая из которых может быть с горящей точкой или без неё.

Семисегментный индикатор из четырех элементов

4-х разрядный семисегментный дисплей (4-Digit 7 Segment Display)

4-х разрядный семисегментный дисплей состоит из четырех семисегментных дисплеев, объединенных в единое устройство. Иногда говорят, что эти дисплеи “мультиплексированы вместе”, поэтому для управления ими можно использовать технологию мультиплексирования. Этот дисплей можно использовать для отображения цифр, а также некоторых букв. Дисплей можно использовать в обоих направлениях. 4 символа удобно использовать для изготовления электронных часов или счетчика от 0 до 9999.

На следующем рисунке показана внутренняя схема соединений 4-х разрядного семисегментного дисплея.

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

В семисегментном дисплее с общим катодом (ОК) отрицательные выводы всех светодиодов соединены вместе и образую общую землю. В схеме с общим анодом (ОА) положительные выводы всех светодиодов соединены вместе и они образуют общий вывод напряжения постоянного тока (VCC).

На нашем сайте есть достаточно подробные статьи про устройство семисегментных дисплеев и их программированию – они написаны для микроконтроллеров семейства AVR, но я думаю провести аналогию с Arduino вам будет не трудно:

  • семисегментный светодиодный индикатор: описание, подключение к микроконтроллеру;
  • перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор;
  • многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации.

Также можно посмотреть статью о подключении семисегментного дисплея к микроконтроллеру AVR ATmega32.

Использование технологии мультиплексирования

Так каким образом мы можем на подобном 4-х символьном семисегментном дисплее отобразить, к примеру, число 1234? Это возможно сделать с использованием технологии мультиплексирования. Смысл этой технологии достаточно прост – в каждый момент времени мы отображаем только один символ (из 4-х возможных) на данном дисплее. Переключение между отображением всех 4-х символов происходит достаточно быстро – поэтому человеческий глаз воспринимает их непрерывно горящими.

Реализация

Есть три способа воплотить данный декодер в жизнь.

  1. Из готовых микросхем логических вентилей, например серия микросхем 74HCxx. Данный способ самый простой, не самый практичный, но вполне допустимый. Также его будет просто модернизировать для n-разярдных индикаторов. И отлично подходит для тестов.

  2. Более сложный, но более «крутой» способ, создание всех логических вентилей на ТТЛ, отлично подойдут транзисторы BC546 и его комплементарная пара BC556. Этот способ потребует дополнительного создания схемы на транзисторах, для их корректной работы. Будет занимать больше пространства, но можно сделать прозрачный корпус и поставить на полочку. Ведь применение ТТЛ в наше время, дело совсем незаурядное.

  3. Промышленный способ — изготовление полноценных кремниевых интегральных схем. Этот способ не самый быстрый, но позволяет наладить массовое производство. НО стоит отметить, что уже давно выпускаются подобные микросхемы, и это будет не слишком целесообразно.

Одноразрядный 7-сегментный индикатор

Мы имеем дело опять с набором светодиодов, только на этот раз их 8 (семь полосок и один кружочек) и они расположены не друг за другом, а в определённом порядке, которые позволяют вам выводить цифры от 0 до 9.

Важная отличительная черта — у индикатора имеются общие ножки для катода (ножки 3 и 8). Всего их две и они равноценны. Это удобно, вам не нужно будет от каждого катода вести отдельный провод на землю. Достаточно выбрать один из общих катодов и от неё соединиться с GND. Аноды у всех отдельные.

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

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

Схематично можно изобразить следующим образом.

Принципиальная схема

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

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

Если мы хотим помигать цифрой 1, то нам надо использовать светодиоды 4 и 6, которые идут на порты 4 и 6 платы микроконтроллера.

Если мы захотим вывести цифру 5, то понадобится работать с пятью светодиодами, цифру 8 — уже семь светодиодов. При сложных проектах работать с таким количеством становится затруднительно. Придётся каждый раз смотреть на схему, что вспомнить, какие светодиоды нужно включить для отображения каждой цифры.

Но можно пойти другим путём. А поможет нам единица информации — байт. Байт в своём двоичном представлении состоит из 8 бит. Каждый бит может принимать значения 0 или 1. А наш светодиодный индикатор как раз и состоит из восьми светодиодов. Таким образом мы можем представить цифру на индикаторе в виде набора байт, где единица будет отвечать за включённый диод, а ноль — за выключенный диод.

Число в двоичном виде записывается следующим образом:

Первые два символа 0b дают понять, что речь идёт о двоичном счёте. Все нули означают, что все светодиоды будут выключены.

У нас задействованы порты от 2 по 9. Второй порт записывается в самую правую позицию. Чтобы его включить, поставим единицу.

Можно самостоятельно включать по отдельности каждый диод, перемещая единицу в представленном байте. Поняв принцип, можно, например, заметить, что за точку отвечает четвёртый бит справа. Если мы его не будем использовать, то он всегда будет равен 0. За чёрточку посередине индикатора отвечает самый последний байт (или первый слева).

Комбинируя набор нулей и единиц, можно создать нужные нам цифры. Например, цифра 0 будет представлена как 0b01110111.

Давайте напишем пример вывода цифры 0.

Код немного избыточен, переменная mask здесь лишняя, но она нам пригодится в следующем примере

Здесь важно, что мы пробегаемся в цикле по числу светодиодов и устанавливаем у всех режим OUTPUT. Затем также в цикле проходим через все светодиоды и узнаём, комбинацию бит с помощью метода bitRead()

Полученная информация помогает нам подсветить нужные светодиоды и получить цифру 0 на выходе.

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

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

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

На видео некоторые цифры отображаются коряво, видимо из-за особенностей записи. В реальности все цифры работают как положено.

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

На Амперке есть упоминания о двух компонентах, которые можно использовать для светодиодного индикатора. Я пока ими не пользовался:

http://amperka.ru/product/74hc595-shift-out-register
http://amperka.ru/product/cd4026-segment-driver

Управление семисегментными индикаторами


Схема подключения семисегментного индикатора с кнопкой

В следующем примере переключение чисел на индикаторе будет происходить только при нажатии тактовой кнопки. Дойдя до числа 3, таймер вновь обнулится и будет ожидать повторного нажатия на кнопку. Это довольно простые программы для Ардуино и семисегментного индикатора, для более сложных и интересных программ необходимо уже использовать сдвиговый регистр 74hc595 для Ардуино.

Скетч. Одноразрядный семисегментный индикатор и кнопка

#define A  8
#define B  7
#define C  6
#define D  5
#define E  4
#define F  3
#define G  2
#define BUTTON  12

byte v = 0;

void setup() {
   pinMode(A, OUTPUT);
   pinMode(B, OUTPUT);
   pinMode(C, OUTPUT);
   pinMode(D, OUTPUT);
   pinMode(E, OUTPUT);
   pinMode(F, OUTPUT);
   pinMode(G, OUTPUT);
   pinMode(BUTTON, INPUT);
}

void loop() {
   digitalWrite(A, HIGH); //цифра нуль
   digitalWrite(B, HIGH);
   digitalWrite(C, HIGH);
   digitalWrite(D, HIGH);
   digitalWrite(E, HIGH);
   digitalWrite(F, HIGH);
   digitalWrite(G, LOW);
   if (digitalRead(BUTTON) == HIGH) { delay(500); v = 1; }

   while (v == 1) {
      digitalWrite(A, LOW); //цифра один
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, LOW);
      digitalWrite(E, LOW);
      digitalWrite(F, LOW);
      digitalWrite(G, LOW);
      if (digitalRead(BUTTON) == HIGH) { delay(500); v = 2; }
   }
   while (v == 2) {
      digitalWrite(A, HIGH); //цифра два
      digitalWrite(B, HIGH);
      digitalWrite(C, LOW);
      digitalWrite(D, HIGH);
      digitalWrite(E, HIGH);
      digitalWrite(F, LOW);
      digitalWrite(G, HIGH);
      if (digitalRead(BUTTON) == HIGH) { delay(500); v = 3; }
   }
   while (v == 3) {
      digitalWrite(A, HIGH); //цифра три
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(E, LOW);
      digitalWrite(F, LOW);
      digitalWrite(G, HIGH);
      if (digitalRead(BUTTON) == HIGH) { delay(500); v = 0; }
   }
}

Пояснения к коду:

  1. переменная используется в программе для перехода одного цикла while к другому. При нажатии на кнопку значение переменной v меняется;
  2. в программе поставлена небольшая задержка в каждом условии для защиты от быстрого перехода от одного цикла while в другой.

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