Эксперимент 26. Секундомер

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

Схема эксперимента

Оставим схему, собранную на прошлом эксперименте. Рисунок 1. Электрическая принципиальная схема эксперимента

Токоограничительные резисторы обязательны!

Рисунок 2. Монтажная схема эксперимента

Программный код эксперимента

Exp26.py
  1. from machine import Pin
  2. import time
  3. _init()
  4.  
  5. segments = [14, 13, 4, 5, 12, 16, 15] # ABCDEFG
  6.  
  7. for s in segments:
  8. led = Pin(s, Pin.OUT).off()
  9.  
  10. digits = [
  11. [1, 1, 1, 1, 1, 1, 0], # 0
  12. [0, 1, 1, 0, 0, 0, 0], # 1
  13. [1, 1, 0, 1, 1, 0, 1], # 2
  14. [1, 1, 1, 1, 0, 0, 1], # 3
  15. [0, 1, 1, 0, 0, 1, 1], # 4
  16. [1, 0, 1, 1, 0, 1, 1], # 5
  17. [1, 0, 1, 1, 1, 1, 1], # 6
  18. [1, 1, 1, 0, 0, 0, 0], # 7
  19. [1, 1, 1, 1, 1, 1, 1], # 8
  20. [1, 1, 1, 1, 0, 1, 1], # 9
  21. ]
  22.  
  23.  
  24. def draw_time(digit):
  25. for el in enumerate(digit):
  26. if (el[1]):
  27. Pin(segments[el[0]]).on()
  28. else:
  29. Pin(segments[el[0]]).off()
  30.  
  31.  
  32. while True:
  33. for digit in digits:
  34. draw_time(digit)
  35. time.sleep(1)

В этой программе мы записали номера выводов микроконтроллера, к которым подключены сегменты индикатора, в массив segments. Порядок перечисления сегментов указан в комментарии в этой строке.

Комментарии используются в программах, чтобы записать какие либо пояснения к коду, и предназначены только для человека, который читает код. Комментарии никак не влияют на выполнение программы. В языке Python комментарий начинается с символа #. Также часто комментируют части кода, которые не должны исполняться, но удалять совсем их пока не нужно.

В строке 10 объявляем массив, в котором описываем цифры от 0 до 9 и какие сегменты должны светиться на индикаторе, чтобы эту цифру отобразить, а какие должны быть потушены. Для описания этого мы использовали двумерный массив. Это массив, у которого каждый из элементов является тоже массивом. Посмотрим внимательнее: элементом под индексом 0 у массива digits является массив [1, 1, 1, 1, 1, 1, 0]. Это перечисление состояний сегментов для отображения цифры 0. Порядок перечисления соответствует порядку в массиве segments. Это важно и потребуется нам для отображения цифр.

В основном цикле программы мы перебираем все элементы массива digits с целью отображения на дисплее.

  1. while True:
  2. for digit in digits:
  3. draw_time(digit)
  4. time.sleep(1)

Рассмотрим код функции draw_time, которая предназначена для отображения цифры, передаваемой ей в качестве параметра. Начнем с того, что разберемся что именно передается функции в качестве входных данных. Ей передается один из элементов массива digits, каждый элемент которого, как мы помним, сам является массивом, описывающим состояние сегментов.

  1. def draw_time(digit):
  2. for el in enumerate(digit):
  3. if (el[1]):
  4. Pin(segments[el[0]]).on()
  5. else:
  6. Pin(segments[el[0]]).off()

Получается, что функция получила данные о том какие сегменты ей нужно включить, а какие выключить. Соответственно она должна это исполнить. Для этого она проходит по всем элементам массива сегментов, как обычно, с помощью оператора in, но в этот раз мы использовали еще оператор enumerate. Обычно оператор in перебирая элементы массива записывает в переменную содержимое элемента массива, его значение, а enumerate(digit) создает последовательность кортежей, состоящих из индексов и значений. В кортеже el в элементе 0 оказывается индекс, а в элементе 1 значение.

Номер индекса нам нужен, чтобы обратиться по нему к нужному сегменту, а его значение, чтобы знать что с ним делать − зажигать или тушить.

  1. if (el[1]):
  2. Pin(segments[el[0]]).on()
  3. else:
  4. Pin(segments[el[0]]).off()

Если сегмент должен быть включен (el[1] истинно), то нужно его зажечь. Номер пина, который нужно включить, записан в переменной segments в элементе с индексом, который мы берем из el[0]. Именно поэтому мы сделали так, что последовательность пинов в массиве segments соответствует им в массиве digits, чтобы у них были одинаковые индексы.

Не совсем обычным является и то, как мы зажигаем сегменты. Pin(segments[el[0]]).on(). Обычно мы создавали объект Pin, записывали его в переменную и оперировали с ней. Сейчас мы сделали тоже самое, только не создавали отдельную переменную, а сделали все сразу. Просто нам не нужна эта переменная в будущем, поэтому мы ее не создавали и для краткости записи сделали так.

Дополнительные задания

Добавь к цифрам 0..9 еще буквы A, b, C d E F, чтобы секундомер переключал символы от 0 до F