Урок 20. Подключение семисегментного светодиодного (LED) индикатора к Ардуино. Библиотека управления индикатором.

LED индикаторы

Подключим семисегментный светодиодный индикатор к плате Ардуино и научимся управлять им с помощью библиотеки Led4Digits.h.

Предыдущий урок     Список уроков     Следующий урок

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

 

Мне попался типичный семисегментный светодиодный индикатор GNQ-3641BUE-21. Это четырех разрядный индикатор, очень яркий, светится при малых токах. Технические характеристики можно посмотреть в формате PDF - GNQ-3641Ax-Bx.pdf.

Схема подключения индикатора к плате Ардуино выглядит так.

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

Я собрал ее на монтажной плате.

Подключение LED к плате Ардуино

Для управления индикаторами я написал библиотеку Led4Digits.h. Библиотека позволяет управлять семисегментными индикаторами:

  • размерностью до четырех разрядов ;
  • с любыми вариантами полярностей управляющих импульсов (все схемы подключения);
  • работает в параллельном процессе;
  • позволяет выводить на индикатор:
    • сегменты каждого разряда;
    • цифру каждого разряда;
    • целое число 0 … 9999;
  • для вывода целого числа может быть задано число разрядов;
  • есть режим гашения незначащих разрядов.

Загрузить библиотеку Led4Digits.h можете по этой ссылке. Как устанавливать написано в уроке 9.

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

 

Библиотека управления LED индикаторами для Ардуино Led4Digits.

Вот описание класса. Я привел только public методы и свойства.

class Led4Digits {
  public:
    byte digit[4];  // коды управления сегментами разрядов
    void regen(); // регенерация, метод должен вызываться регулярно
    void tetradToSegCod(byte dig, byte tetrad);  // преобразования тетрады в коды сегментов
    boolean print(unsigned int value, byte digitNum, byte blank); // вывод целого числа
    Led4Digits (byte typeLed, byte digitPin0,  byte digitPin1, byte digitPin2, byte digitPin3,
                byte segPinA, byte segPinB, byte segPinC, byte segPinD,
                byte segPinE, byte segPinF, byte segPinG, byte segPinH );    
} ;

Конструктор.

    Led4Digits (byte typeLed, byte digitPin0,  byte digitPin1, byte digitPin2, byte digitPin3,
                byte segPinA, byte segPinB, byte segPinC, byte segPinD,
                byte segPinE, byte segPinF, byte segPinG, byte segPinH );    

typeLed  Задает полярности управляющих импульсов для сигналов выбора разрядов и сегментов. Поддерживает любые схемы подключения (Урок 19).

typeLed Выбор разряда Выбор сегмента Тип схемы
0 -_- -_- Общий анод с ключами выбора разряда
1 _-_ -_- Общий анод
2 -_- _-_ Общий катод
3 _-_ _-_ Общий катод с ключами выбора разряда

digitPin0 … digitPin3 – выводы выбора разрядов. Если digitPin = 255, то разряд отключен. Это позволяет подключать индикаторы с меньшим количеством разрядов. digitPin0 – младший (правый) разряд.

segPinA … segPinH – выводы управления сегментами.

Например,

Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

означает:  тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13.

Метод  void regen()

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

Например,

// обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

Массив    byte digit[4]

Содержит состояние сегментов. digit[0] это младший разряд, младший бит digit[0] это сегмент ”A” младшего разряда. Состояние бита равное 1, означает, что сегмент светится.

Например,

digit[1] = B0000101;

означает, что во втором разряде светятся сегменты ”A” и ”C”.

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

// бегущие сегменты
#include <MsTimer2.h>
#include <Led4Digits.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

void setup() {
  MsTimer2::set(2, timerInterrupt); // прерывание по таймеру 2 мс
  MsTimer2::start();               // разрешение прерывания 
}

void loop() {
  for (int i = 0; i < 32; i++) {
    if ( i == 0) disp.digit[0]= 1;
    else if ( i == 8)  disp.digit[1]= 1;
    else if ( i == 16) disp.digit[2]= 1;
    else if ( i == 24) disp.digit[3]= 1;
    else {
      disp.digit[0] = disp.digit[0] << 1;
      disp.digit[1] = disp.digit[1] << 1;
      disp.digit[2] = disp.digit[2] << 1;
      disp.digit[3] = disp.digit[3] << 1;     
    }
    delay(250);   
  } 
}

// обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

В массиве digit[] сдвигается 1 и индикаторы отображают это.

Метод  void tetradToSegCod(byte dig, byte tetrad)

Метод позволяет выводить на отдельные разряды цифры и буквы шестнадцатеричного кода. Имеет аргументы:

  • dig – номер разряда 0 … 3;
  • tetrad – десятичный код символа. Код 0 отобразит цифру ”0”, код 1 - цифру ”1”, код 14 - букву ”E”.

Например,

tetrad(2, 7);

выведет цифру “7” в третьем разряде.

Пример программы меняющей символы в каждом разряде по очереди.

// цифры по очереди
#include <MsTimer2.h>
#include <Led4Digits.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

void setup() {
  MsTimer2::set(2, timerInterrupt); // прерывание по таймеру 2 мс
  MsTimer2::start();               // разрешение прерывания 
}

void loop() {
  for (int i = 0; i < 64; i++) {
    disp.tetradToSegCod(i>>4, i);       
    delay(250);   
  }
}

// обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

Метод  boolean print(unsigned int value, byte digitNum, byte blank)

Метод выводит на индикаторы целое число. В нем двоичное число преобразуется в двоично-десятичный код для каждого разряда. Имеет аргументы:

  • value – число, которое выводится на индикатор.
  • digitNum – количество разрядов для числа. Не надо путать с количеством разрядов индикатора. Вы можете захотеть вывести число на 2х разрядах, а на остальных двух отобразить символы, используя digit[].
  • blank – признак гашения незначащих разрядов. blank=0 означает, что число должно отображаться со всеми нулями. Число ”7” будет выглядеть “0007”. При blank, отличном от 0 незначащие нули будут гаситься.

Если число value превышает допустимое для выбранного количества разрядов (digitNum), то функция отобразит на индикаторе ”---” и вернет false.

Пример программы вывода чисел.

// вывод числа
#include <MsTimer2.h>
#include <Led4Digits.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

void setup() {
  MsTimer2::set(2, timerInterrupt); // прерывание по таймеру 2 мс
  MsTimer2::start();               // разрешение прерывания
}

void loop() {
  for (int i = 0; i < 12000; i++) {
    disp.print(i, 4, 1);       
    delay(50);   
  } 
}

// обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

Последние два метода не меняют состояния сегмента ”H” – децимальной точки. Чтобы изменить состояние точки можно использовать команды:

digit[0] |= 0x80;  // зажечь децимальную точку
digit[0] &= 0x7f;  // погасить децимальную точку

 

Вывод на индикаторы отрицательных чисел (int).

Вывод отрицательных чисел можно производить следующим образом:

  • Проверить знак числа.
  • Если число отрицательное, то напечатать на старшем разряде знак минус и в функции print() изменить знак числа на положительный.
  • Если число положительное, то погасить разряд знака и вывести число функцией print().

Вот программа, которая демонстрирует такой способ. Она выводит числа от -999 до 999.

// вывод отрицательных чисел
#include <MsTimer2.h>
#include <Led4Digits.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

void setup() {
  MsTimer2::set(2, timerInterrupt); // прерывание по таймеру 2 мс
  MsTimer2::start();               // разрешение прерывания 
}

void loop() {
 
  for (int i = -999; i < 1000; i++) {

    if ( i < 0 ) {
    // число отрицательно
    disp.digit[3]= B01000000; // знак -
    disp.print(i * -1, 3, 1);             
    }
    else {
      disp.digit[3]= B00000000; // гашение знака
      disp.print(i, 3, 1);   
    }
           
    delay(50);   
  } 
}

// обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

 

Вывод на индикаторы дробных чисел, формат float.

Для вывода на индикаторы чисел с плавающей запятой (float) существует много способов с использованием стандартных функций языка C. Это, прежде всего, функция sprint(). Работает очень медленно, требует дополнительных преобразований кодов символов в двоично-десятичные коды, надо из строки выделять точку. С другими функциями те же проблемы.

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

  • Число с плавающей запятой умножается на 10 в степени соответствующей требуемому числу знаков после запятой. Если вам необходимо на индикаторы выводить 1 знак после запятой, умножаете на 10, если 2, то умножаете на 100, 3 знака – на 1000.
  • Далее число с плавающей запятой явно преобразуется в целое (int) и выводится на индикаторы функцией print().
  • В нужном разряде ставится точка.

Например, следующие строки выведут на семисегментные светодиодные индикаторы переменную типа float с двумя знаками после запятой.

float x = 2.12345;
disp.print((int)(x * 100.), 4, 1);  
disp.digit[2] |= 0x80;  // зажечь точку третьего разряда

Мы умножаем число на 100, а поставив точку в третьем разряде, делим результат на 100.

Вот программа, выводящая на индикаторы числа с плавающей запятой от 0.00 до 99.99.

// вывод чисел с плавающей запятой
#include <MsTimer2.h>
#include <Led4Digits.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

void setup() {
  MsTimer2::set(2, timerInterrupt); // прерывание по таймеру 2 мс
  MsTimer2::start();               // разрешение прерывания 
}

void loop() { 
  float x = 0;
 
  for (int i = 0; i < 10000; i++) {
    x += 0.01;

    disp.print((int)(x * 100.), 4, 1);   
    disp.digit[2] |= 0x80;  // зажечь точку третьего разряда
               
    delay(50);   
  } 
}

// обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

Как видите, библиотека Led4Digits.h значительно упрощает работу с семисегментыми светодиодными (LED) индикатороми, подключенными к плате Ардуино. Аналога такой библиотеки я не нашел.

 

В следующем уроке подключим к плате Ардуино одновременно светодиодный индикатор и матрицу кнопок. Напишем библиотеку для такой конструкции.

Предыдущий урок     Список уроков     Следующий урок

9 комментариев на «Урок 20. Подключение семисегментного светодиодного (LED) индикатора к Ардуино. Библиотека управления индикатором.»

  1. Замечательная библиотека! Ардуинка по количеству выводов позволяет подключить два четырёхразрядных индикатора (8+8+4=20 или 7+7+4=18). Хотелось бы использовать с двумя- есть ли такая возможность? Самый простой вариант применения- измерение тока и напряжения одновременно.

  2. Я думаю, что при количестве разрядов более 4 удобнее использовать LCD индикатор с контроллером. Сейчас пишу урок на эту тему.
    Что касается LED индикаторов. Может, попробуете сами библиотеку на большее число разрядов переписать? Я старался все объяснить подробно.

    • LCD индикатор с контроллером подключал, семисегментные LED индикаторы 3шт по 4 разряда через регистры тоже подключал. Но интересно было бы именно на голую Arduino PRO mini, то есть чтоб ничего лишнего. И кстати, не больше разрядов, а именно два индикатора, они могут отдельно стоять, и выходы общих анодов (катодов) общие для двух индикаторов, то есть скважность не увеличивается. До написания библиотек я вряд ли дорасту. Вообще странно, что для такой вроде востребованной функции есть только ваша библиотека. Спасибо!

    • Таки нашёл ещё одну библиотеку, тоже 4 разряда:
      https://github.com/fabiantheblind/Seven-Segment-LED-Arduino-Libraries/tree/master/Pineapple

  3. Спасибо, отличная библиотека и пояснения! Но у меня почему-то на цифрах 9, 5, 3 перестаёт работать нижний сегмент, хотя на всех остальных он есть, в чём может быть дело? Проверил все цепи, соединения нормальные.

    • Спасибо. Скорее всего у вас замкнут сегмент d с каким-то другим сегментом. Прозвоните все сегменты между собой.

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

  4. Здравствуйте! Огромное спасибо за ваши уроки!
    Отличная библиотека!
    Скажите, знак «минус» при выводе отрицательных чисел мерцает, — это так должно быть, или я что-то неправильно делаю?

    • Спасибо!
      Нет знак минус мерцать не должен. Посмотрите внимательно, что вы делаете с 3 разрядом. Для вывода отрицательных чисел в функции print должно быть указано 3 разряда.
      disp.print((int)(temperature * -1 * 10.), 3, 1);
      disp.digit[3]= 0x40; // отображается минус
      Посмотрите в уроках 24-27.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *