Рейтинг@Mail.ru

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

автор:
Be the first to comment! Arduino
Print Friendly, PDF & Email
Подключим к Arduino светодиодный семисегментный индикатор и научимся им управлять.

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

1Описание сегментного светодиодного индикатора

Индикатор называется 7-сегментным из-за того, что он состоит из семи светодиодов, которые расположены в форме цифры "8". Зажигая определённые сегменты, можно изображать разные цифры. Это похоже на цифры индекса на почтовом конверте: закрашивая определённые участки, мы пишем разные индексы. Зачастую дополнительно к 7-ми сегментам, индикатор содержит десятичную точку. Также индикатор может иметь несколько цифр – разрядов. Обычно от одного до 4-х. Сегменты индикатора обозначаются латинскими буквами от A до G, а DP – это десятичная точка (decimal point).

Обозначение сегментов для 7-, 9-, 14- и 16-сегментных индикаторов
Обозначение сегментов 7-, 9-, 14- и 16-сегментных индикаторов

К слову, существуют сегментные индикаторы, число сегментов которых отличается от 7-ми. Так, например, существуют 14- и 16-сегментные индикаторы. Кроме цифр от 0 до 9 они также позволяют выводить буквы. Принцип их работы и управления обычно идентичны таковым для 7-сегментных индикаторов.

Мы в качестве индикатора будем использовать семисегментный индикатор 3361AS-1. Он построен по принципу индикатора с общим катодом. Это значит, что индикатор состоит из нескольких светодиодов в одном корпусе, у которых общая земля, а питание на каждый светодиод подаётся отдельно.

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

2Подключение 7-сегментного индикатора непосредственно к Arduino

Мы можем подключить индикатор прямо к выводам Arduino. Для этого придётся задействовать сразу 7 ножек (или 8, если нужна десятичная точка). Обратим внимание, что индикатор 3361AS не имеет токоограничивающих резисторов. Необходимо обеспечить наличие сопротивления номиналом около 180…220 Ом на каждый вывод индикатора (т.к. питание подаём +5 В от Arduino).

Электрическая схема 7-сегментного индикатора 3361AS
Электрическая схема 7-сегментного индикатора 3361AS

Расположение выводов индикатора показано на иллюстрации:

Размеры корпуса и расположение выводов 7-сегментного индикатора 3361AS
Размеры корпуса и расположение выводов 7-сегментного индикатора 3361AS

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

Вывод индикатора 3361ASНазначениеВывод Arduino
1Сегмент ED6
2Сегмент DD5
3DPD9
4Сегмент CD4
5Сегмент GD8
7Сегмент BD3
8Выбор 3-го разряда5V
9Выбор 2-го разряда5V
10Сегмент FD7
11Сегмент AD2
12Выбор 1-го разрядаGND

Напишем скетч, который последовательно выводит числа от 0 до 9 на первом разряде индикатора.

Скетч управления индикатором 3361AS (разворачивается)
const int A = 2;
const int B = 3;
const int C = 4;
const int D = 5;
const int E = 6;
const int F = 7;
const int G = 8;
const int DP = 9;

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

void loop() {
  for (int i=0; i<=9; i++){
    printNumber(i);
    delay(1000);
  }
}

// зажигает на 7-сегментном индикаторе заданную цифру
void printNumber(int num){
  int numbers[10][8] = { // многомерный массив, в котором описаны состояния сегментов A…G и DP для цифр от 0 до 9
    {1,1,1,1,1,1,0,0}, // 0 
    {0,1,1,0,0,0,0,0}, // 1 
    {1,1,0,1,1,0,1,0}, // 2 
    {1,1,1,1,0,0,1,0}, // 3 
    {0,1,1,0,0,1,1,0}, // 4 
    {1,0,1,1,0,1,1,0}, // 5 
    {1,0,1,1,1,1,1,0}, // 6 
    {1,1,1,0,0,0,0,0}, // 7 
    {1,1,1,1,1,1,1,0}, // 8 
    {1,1,1,1,0,1,1,0}  // 9 
  };
  lightSegments(numbers[num]);
}

// зажигает заданные сегменты
void lightSegments(int segments[]){
  digitalWrite(A, segments[0]);
  digitalWrite(B, segments[1]);
  digitalWrite(C, segments[2]);
  digitalWrite(D, segments[3]);
  digitalWrite(E, segments[4]);
  digitalWrite(F, segments[5]);
  digitalWrite(G, segments[6]);
  digitalWrite(DP, segments[7]);
}

Небольшое пояснение по поводу массива numbers[] в функции printNumber(). Этот массив состоит из 10-ти подмассивов, каждый из которых определяет одну цифру от 0 до 9. В свою очередь подмассивы состоят из 8-ми элементов, которые задают состояния сегментов от A до G и DP. Например, первый подмассив описан как {1,1,1,1,1,1,0,0} и он отвечает за вывод на индикатор нуля. Это означает, что сегменты A,B,C,D,E,F должны гореть, а сегменты G и DP – нет.

    [1|1|1|1|1|1|0|0 ]
    [A|B|C|D|E|F|G|DP]

В результате получаем примерно следующее:

Управление 7-сегментным индикатором с помощью Arduino Nano
Управление 7-сегментным индикатором с помощью Arduino Nano

И вот так в динамике:

Это самый простой способ управления сегментным индикатором, но, как мы видим, он задействует почти все цифровые ножки Arduino. Особенно если мы решим использовать все разряды индикатора. Тогда кроме ножек для управления сегментами придётся дополнительно использовать столько выводов, сколько разрядов у индикатора. Получится, что для управления 7-сегментным индикатором с 3-мя разрядами необходимо 11 ножек (7 сегментов + 1 десятичная точка + 3 ножки для выбора разряда). Это расточительно, и не всегда можно такое себе позволить.

3Драйвер для управления 7-сегментным индикатором

Чтобы сократить число задействованных выводов микроконтроллера обычно на практике используются различные решения. Например, популярным способом управления 7-сегментным индикатором является применение микросхемы CD4511 – двоично-десятичного преобразователя. Он переводит двоичный код числа в напряжение на соответствующих цифре сегментах индикатора. Такой преобразователь будет использовать всего 4 ножки Arduino. То есть, например, если необходимо отобразить на индикаторе десятичное число 7, необходимо выставить на входе преобразователя двоичное 0111 ("LOW HIGH HIGH HIGH"). Микросхема CD4511 выполняется в разных типах корпусов. Назначение выводов в исполнении с 16-тью ножками, такое:

Выводы двоично-десятичного преобразователя CD4511
Выводы двоично-десятичного преобразователя CD4511

Отечественными аналогами данного преобразователя являются микросхемы серий ИД1…ИД7. Кстати, отечественные преобразователи изображают цифры "6" и "9", используя 6 сегментов, а зарубежные CD4511 – только 5 сегментов.

Разница в выводе цифр CD4511 и ИД7
Разница в выводе цифр CD4511 и ИД7

4Управление 7-сегментным индикатором с помощью драйвера CD4511 и Arduino

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

Вывод CD4511НазначениеПримечание
A0...A3Входы двоичного преобразователяСоответствуют разрядам двоичного числа.
a...gВыходы на сегменты индикатораПодключаются через токоограничивающие резисторы к соответствующим сегментам светодиодного индикатора.
Lamp Test#Тест индикатора (включает все сегменты)Подключим к питанию, не использовать его.
Blanking#Очистка индикатора (отключает все сегменты)Подключим к питанию, чтобы не использовать его.
Latch Enabled#Выход активенБудет подключен к земле, чтобы выход был всегда активен.
VDDПитание микросхемы и индикатораОт 3 до 15 В.
GNDЗемляОбщая у CD4511, Arduino, 7-сегментного индикатора.

Желательно также подключить керамический конденсатор ёмкостью примерно 1 мкФ между землёй и питанием микросхемы CD4511.

Подключение 7-сегментного индикатора к Arduino с двоичным декодером CD4511B
Подключение 7-сегментного индикатора к Arduino с двоичным декодером CD4511B

Теперь напишем простой скетч, чтобы проверить работоспособность 7-сегментного индикатора 3361AS-1 в связке с двоично-десятичным декодером, а также получить опыт работы с ними. Данный скетч будет поочерёдно перебирать числа от 0 до 9, перемещаясь по циклу от одного разряда индикатора к следующему.

Скетч для управления 7-сегментным индикатором (светится 1 разряд) (разворачивается)
// выводы Arduino для управления двоичным кодом на входе декодера CD4511:
const byte D_0 = 11;
const byte D_1 = 10;
const byte D_2 = 9;
const byte D_3 = 8;

// выводы Arduino для выбора десятичного разряда индикатора:
const byte B_0 = 7;
const byte B_1 = 6;
const byte B_2 = 5;

void setup() {
  pinMode(D_0, OUTPUT);
  pinMode(D_1, OUTPUT);
  pinMode(D_2, OUTPUT);
  pinMode(D_3, OUTPUT);
  pinMode(B_0, OUTPUT);
  pinMode(B_1, OUTPUT);
  pinMode(B_2, OUTPUT);
}

void loop() {
  for (int i=0; i<3; i++){ // перебираем разряды с 0 по 2-ой
    setDigit(i);
    for (int n=0; n<10; n++){ // перебираем числа от 0 до 9
      printNumber(n);
      delay(200);
    }    
  }
}

// выбирает разряд десятичного числа на счётчике:
void setDigit(byte b){
  switch (b) {
    case 0:
      digitalWrite(B_0, LOW);
      digitalWrite(B_1, HIGH);
      digitalWrite(B_2, HIGH);
      break;
    case 1:
      digitalWrite(B_0, HIGH);
      digitalWrite(B_1, LOW);
      digitalWrite(B_2, HIGH);
      break;
    case 2:
      digitalWrite(B_0, HIGH);
      digitalWrite(B_1, HIGH);
      digitalWrite(B_2, LOW);
      break;
  }
}

// зажигает заданную цифру 7-сегментного индикатора
void printNumber(byte n){
  switch(n){
    case 0:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 1:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 2:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 3:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 4:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 5:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 6:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 7:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 8:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, HIGH);
      break;
    case 9:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, HIGH);
      break;
  }
}

Загрузим скетч в Arduino и посмотрим результат.

В один момент времени светится только один разряд индикатора. Как же задействовать одновременно сразу три разряда индикатора? Это будет немного сложнее. Сложность заключается в том, что нам одновременно нужно управлять тремя разрядами десятичного число, используя только один преобразователь CD4511. Но чисто физически это невозможно. Однако можно добиться иллюзии постоянного свечения всех разрядов светодиодного индикатора. Для этого придётся быстро переключаться между разрядами, постоянно обновляя показание каждого разряда. Мы будем поочерёдно активировать каждый из разрядов индикатора 3361AS, выставлять на нём с помощью двоичного преобразователя CD4511 нужную цифру, а затем переключаться на следующий разряд.

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

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

Скетч для управления трёхразрядным 7-сегментным индикатором (разворачивается)
// Выводы Arduino для управления двоичным конвертером CD4511:
const byte bit0 = 11;
const byte bit1 = 10;
const byte bit2 = 9;
const byte bit3 = 8;

// Выводы Arduino для выбора десятичных разрядов индикатора 3361AS:
const byte B_0 = 5;
const byte B_1 = 6;
const byte B_2 = 7;

#define seconds() (millis()/1000) // макрос определения секунд, прошедших с начала работы скетча

void setup()
{
  pinMode(bit0, OUTPUT);
  pinMode(bit1, OUTPUT);
  pinMode(bit2, OUTPUT);
  pinMode(bit3, OUTPUT);
  
  pinMode(B_0, OUTPUT);
  pinMode(B_1, OUTPUT);
  pinMode(B_2, OUTPUT);

  digitalWrite(B_0, HIGH);
  digitalWrite(B_1, HIGH);
  digitalWrite(B_2, HIGH);
}

void loop()
{
  // Каждую секунду увеличиваем показания индикатора на 1:
  int sec = seconds();
  for (int i=0; i<1000; i++) {
    while (sec == seconds()) {
      printNumber(i);
    }
    sec = seconds();
  }
}

// Выводит 3-разрядное число на 7-сегментный индикатор.
void printNumber(int n) {
  setDigit(B_0, n/100); // выводим сотни десятичного числа
  setDigit(B_1, n/10 ); // выводим десятки
  setDigit(B_2, n/1  ); // выводим единицы
}

// Выводит заданное число на заданный разряд индикатора.
void setDigit(byte digit, int value) {
  digitalWrite(digit, LOW); // выбираем разряд индикатора 3361AS-1
  setNumber(value); // выводим на этот разряд число
  delay(4);
  digitalWrite(digit, HIGH); // снимаем выбор разряда индикатора
}

// Выставляет двоичный код на входе преобразователя CD4511
void setNumber(int n) {
  static const struct number {
    byte b3;
    byte b2;
    byte b1;
    byte b0;
  }
  
  numbers[] = {
    {0, 0, 0, 0}, // 0 
    {0, 0, 0, 1}, // 1 
    {0, 0, 1, 0}, // 2 
    {0, 0, 1, 1}, // 3 
    {0, 1, 0, 0}, // 4 
    {0, 1, 0, 1}, // 5 
    {0, 1, 1, 0}, // 6 
    {0, 1, 1, 1}, // 7 
    {1, 0, 0, 0}, // 8 
    {1, 0, 0, 1}, // 9 
  };

  digitalWrite(bit0, numbers[n%10].b0);
  digitalWrite(bit1, numbers[n%10].b1);
  digitalWrite(bit2, numbers[n%10].b2);
  digitalWrite(bit3, numbers[n%10].b3);
}

Получится вот такая картина.

Управление трёхразрядным семисегментным индикатором с помощью преобразователя CD4511 и Arduino
Управление трёхразрядным семисегментным индикатором с помощью преобразователя CD4511 и Arduino

В динамике это выглядит так. Тут как раз временами видны мерцания сегментов светодиодного индикатора.

Можно попробовать поиграть значением задержек в функции setDigit(). Если сделать задержки меньше, то мерцание станет меньше заметно. Но начнут сильнее засвечиваться соседние сегменты на выбранном разряде индикатора. Тут необходимо выбрать какое-то компромиссное решение.

5Управление 7-сегментным индикатором с помощью драйвера TM1637 и Arduino

Существуют и другие драйверы для подключения 7-сегментных дисплеев. Один из них – TM1637. Есть готовые модули, в которых уже присутствует и индикатор, и драйвер, и вся необходимая «обвязка» (резисторы, конденсаторы). Пример – модуль HW-069. В качестве семисегментного индикатора здесь 4-разрядный индикатор 3642BS-1.

Модуль HW-069 с драйвером TM1637 и четырёхразрядным семисегментным индикатором
Модуль HW-069 с драйвером TM1637 и четырёхразрядным семисегментным индикатором

Подключение модуля к Arduino предельно простое, т.к. для обмена с драйвером используется интерфейс, очень похожий на I2C. Т.е. необходимо подключить питание от 5 В Arduino, а данные передаются по DIO и тактируются по CLK. Но тем не менее, интерфейс не эквивалентен полностью I2C, т.к. у дисплея нет своего адреса.

Модуль HW-069 с драйвером TM1637 и четырёхразрядным семисегментным индикатором
Модуль HW-069 с драйвером TM1637 и четырёхразрядным семисегментным индикатором

Как всегда, есть множество готовых библиотек для управления индикатором через драйвер TM1637. Например, библиотека Gyver TM1637 или библиотека Avishay TM1637.

Модуль с драйвером TM1637 работает с Arduino UNO
Модуль с драйвером TM1637 работает с Arduino UNO

Эти библиотеки работают прекрасно, и рассказывать, как загружать и устанавливать библиотеку для Arduino не буду: мы это делали уже миллион раз. Мы же не ищем лёгких путей, поэтому попробуем разобраться в работе драйвера TM1637 самостоятельно, верно?

Продолжение следует …

Last modified onПонедельник, 08 Июнь 2020 06:47 Read 979 times

Поделиться

Print Friendly, PDF & Email

Leave a comment