12. Секундомер
В этом эксперименте мы создаем секундомер, который считает до 10.
Список деталей для эксперимента
Список деталей для эксперимента
- 1 плата Arduino Uno
- 1 беспаечная макетная плата
- 1 семисегментный индикатор
- 7 резисторов номиналом 220 Ом
- 9 проводов «папа-папа»
Принципиальная схема
Принципиальная схема
Схема на макетке
Схема на макетке
Обратите внимание
Обратите внимание
- Выводы 3 и 8 семисегментного индикатора оба являются катодами, к земле можете подключать любой из них.
- Внимательно рассмотрите схему, сопоставьте сегменты индикатора с номерами его ножек, а те, в свою очередь, с пинами Arduino, к которым мы их подключаем.
- Вывод 5 индикатора — это точка. Мы не используем её в этом эксперименте
- Сегменты индикатора — просто светодиоды, поэтому мы используем резистор с каждым из них.
Скетч
Скетч
p130_seven_segment_counter.ino
#define FIRST_SEGMENT_PIN 2
#define SEGMENT_COUNT 7
// префикс «0b» означает, что целое число за ним записано в
// в двоичном коде. Единицами мы обозначим номера сегментов
// индикатора, которые должны быть включены для отображения
// арабской цифры. Всего цифр 10, поэтому в массиве 10 чисел.
// Нам достаточно всего байта (англ. byte, 8 бит) для хранения
// комбинации сегментов для каждой из цифр.
byte numberSegments[10] = {
0b01000000, 0b11110101, 0b10100010, 0b10100001, 0b10010101,
0b10001001, 0b10001000, 0b11100101, 0b10000000, 0b10000001
};
void setup()
{
for (int i = 0; i < SEGMENT_COUNT; ++i)
pinMode(i + FIRST_SEGMENT_PIN, OUTPUT);
}
void loop()
{
// определяем число, которое собираемся отображать. Пусть им
// будет номер текущей секунды, зацикленный на десятке
int number = (millis() / 1000) % 10;
// получаем код, в котором зашифрована арабская цифра
int mask = numberSegments[number];
// для каждого из 7 сегментов индикатора...
for (int i = 0; i < SEGMENT_COUNT; ++i) {
// ...определяем: должен ли он быть включён. Для этого
// считываем бит (англ. read bit), соответствующий текущему
// сегменту «i». Истина — он установлен (1), ложь — нет (0)
boolean enableSegment = bitRead(mask, i);
// включаем/выключаем сегмент на основе полученного значения
digitalWrite(i + FIRST_SEGMENT_PIN, enableSegment);
}
}
Пояснения к коду
Пояснения к коду
- Мы создали массив типа
byte
: каждый его элемент это 1 байт, 8 бит, может принимать значения от 0 до 255. - Символы арабских цифр закодированы состоянием пинов, которые соединены с выводами соответствующих сегментов: 0, если сегмент должен быть выключен, и 1, если включен.
- В переменную
mask
мы помещаем тот элемент массиваnumberSegments
, который соответствует текущей секунде, вычисленной в предыдущей инструкции. - В цикле
for
мы пробегаем по всем сегментам, извлекая с помощью встроенной функцииbitRead
нужное состояние для текущего пина, в которое его и приводим с помощьюdigitalWrite
и переменнойenableSegment
bitRead(x, n)
возвращаетboolean
значение: n-ный бит справа в байте x
Вопросы для проверки себя
Вопросы для проверки себя
- К которой ножке нашего семисегментного индикатора нужно подключать землю?
- Как мы храним закодированные символы цифр?
- Каким образом мы выводим символ на индикатор?
Задания для самостоятельного решения
Задания для самостоятельного решения
- Измените код, чтобы индикатор отсчитывал десятые секунды.
- Поменяйте программу так, чтобы вместо символа «0» отображался символ «А».
- Дополните схему и программу таким образом, чтобы сегмент-точка включался при прохождении четных чисел и выключался на нечетных