Урок 13. Секундомер


В этом уроке мы создаем секундомер, который считает до 10.

Список деталей для эксперимента

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

Схема на макетке

Обратите внимание

  • Выводы 3 и 8 семисегментного индикатора оба являются катодами, к земле можете подключать любой из них.
  • Внимательно рассмотрите схему, сопоставьте сегменты индикатора с номерами его ножек, а те, в свою очередь, с пинами Arduino, к которым мы их подключаем.
  • Вывод 5 индикатора — это точка. Мы не используем её в этом эксперименте
  • Сегменты индикатора — просто светодиоды, поэтому мы используем резистор с каждым из них.

Скетч

  1.     #define FIRST_SEGMENT_PIN   2
    
  2.     #define SEGMENT_COUNT       7
    
  3.  
  4.     // префикс «0b» означает, что целое число за ним записано в
    
  5.     // в двоичном коде. Единицами мы обозначим номера сегментов
    
  6.     // индикатора, которые должны быть включены для отображения
    
  7.     // арабской цифры. Всего цифр 10, поэтому в массиве 10 чисел.
    
  8.     // Нам достаточно всего байта (англ. byte, 8 бит) для хранения
    
  9.     // комбинации сегментов для каждой из цифр.
    
  10.     byte numberSegments[
    10
    ] = {
    
  11.       0b00111111, 0b00001010, 0b01011101, 0b01011110, 0b01101010,
  12.       0b01110110, 0b01110111, 0b00011010, 0b01111111, 0b01111110,
  13.     }
    ;
    
  14.  
  15.     void setup(
    )
    
  16.     {
    
  17.       for (
    int i = 0
    ; i < SEGMENT_COUNT; ++i)
    
  18.         pinMode(i + FIRST_SEGMENT_PIN, OUTPUT)
    ;
    
  19.     }
    
  20.  
  21.     void loop(
    )
    
  22.     {
    
  23.       // определяем число, которое собираемся отображать. Пусть им
    
  24.       // будет номер текущей секунды, зацикленный на десятке
    
  25.       int number = (millis(
    ) / 1000
    ) % 10
    ;
    
  26.       // получаем код, в котором зашифрована арабская цифра
    
  27.       int mask = numberSegments[number]
    ;
    
  28.       // для каждого из 7 сегментов индикатора...
    
  29.       for (
    int i = 0
    ; i < SEGMENT_COUNT; ++i) {
    
  30.         // ...определяем: должен ли он быть включён. Для этого
    
  31.         // считываем бит (англ. read bit), соответствующий текущему
    
  32.         // сегменту «i». Истина — он установлен (1), ложь — нет (0)
    
  33.         boolean enableSegment = bitRead(mask, i)
    ;
    
  34.         // включаем/выключаем сегмент на основе полученного значения
    
  35.         digitalWrite(i + FIRST_SEGMENT_PIN, enableSegment)
    ;
    
  36.       }
    
  37.     }
    

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

  • Мы создали массив типа byte: каждый его элемент это 1 байт, 8 бит, может принимать значения от 0 до 255.
  • Символы арабских цифр закодированы состоянием пинов, которые соединены с выводами соответствующих сегментов: 0, если сегмент должен быть выключен, и 1, если включен.
  • В переменную mask мы помещаем тот элемент массива numberSegments, который соответствует текущей секунде, вычисленной в предыдущей инструкции.
  • В цикле for мы пробегаем по всем сегментам, извлекая с помощью встроенной функции bitRead нужное состояние для текущего пина, в которое его и приводим с помощью digitalWrite и переменной enableSegment
  • bitRead(x, n) возвращает boolean значение: n-ный бит справа в байте x

Вопросы для проверки себя

  • К которой ножке нашего семисегментного индикатора нужно подключать землю?
  • Как мы храним закодированные символы цифр?
  • Каким образом мы выводим символ на индикатор?

Задания для самостоятельного решения

  • Измените код, чтобы индикатор отсчитывал десятые секунды.
  • Поменяйте программу так, чтобы вместо символа «0» отображался символ «А».
  • Дополните схему и программу таким образом, чтобы сегмент-точка включался при прохождении четных чисел и выключался на нечетных

 

 

Теги: 
Источник: 
wiki.amperka.ru