Это старая версия документа!


Эксперимент 17. Индикатор уровня

В технике часто применяются индикаторы уровней на светодиодной шкале. Например в звукозаписывающем оборудовании, как индикаторы уровня громкости динамиков или микрофона. Давайте тоже соберем такой индикатор.

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

Подключим все 6 светодиодов к микроконтроллеру.

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

Рисунок 1. Электрическая принципиальная схема эксперимента

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

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

Exp17.ino
  1. #define ACD_PIN A0
  2.  
  3. int value = 0;
  4. int myPins[6] = {5, 12, 13, 14, 15, 16};
  5.  
  6. void ledOff(){
  7. for (int i = 0; i < 6; i++) {
  8. digitalWrite(myPins[i], LOW);
  9. }
  10. }
  11.  
  12. void ledOn(int count){
  13. for (int i = 0; i < count; i++) {
  14. digitalWrite(myPins[i], HIGH);
  15. }
  16. }
  17.  
  18. void setup()
  19. {
  20. for (int i = 0; i < 6; i++) {
  21. pinMode(myPins[i], OUTPUT);
  22. }
  23. }
  24.  
  25. void loop()
  26. {
  27. value = analogRead(ACD_PIN);
  28. ledOff();
  29.  
  30. if (value > 850) ledOn(6);
  31. else if (value > 680) ledOn(5);
  32. else if (value > 510) ledOn(4);
  33. else if (value > 340) ledOn(3);
  34. else if (value > 170) ledOn(2);
  35. else ledOn(1);
  36. }

В коде программы много нового. Давайте разбираться.

  1. int myPins[6] = {5, 12, 13, 14, 15, 16};

Массивы

Ранее мы уже много раз сталкивались с переменными. Это был некий контейнер для хранения какого либо значения или объекта. Например, мы записывали значение АЦП переменную. Теперь настала пора познакомиться с массивами. Массив, это тоже контейнер, как и переменная, но он может хранить не одно значение, а много. Если переменную можно было представить как коробку, в которую можно что-то положить, то переменная, это полка шкафа, на которую можно поставить несколько коробок со значениями.

В строке 4 мы объявили массив ledPins с помощью прямоугольных скобок и сразу записали в него 6 значений. Эти значения номера выводов, к которым подключены светодиоды. Важным свойством массива является то, что каждый элемент имеет свой номер. Номера элементов массива начинаются с 0. Так если в массиве 3 элемента, то у них будут номера 0, 1 и 2. Эти номера нам будут нужны потом для обращения к конкретным элементам массива для чтения или записи значений в них.

Аналогично объявляем массив для будущих объектов Pin, но этот массив пока будет пустым

  1. leds = []

Настало время создать объекты Pin и записать их в массив leds

  1. for pinNum in ledPins:
  2. leds.append(Pin(pinNum, Pin.OUT))

Мы уже знакомы с циклом for, он нужен для перебора всех значений списка. В данном случае он перебирает все значения массива ledPins, в котором записаны номера выводов. Эти номера поочередно присваиваются переменной pinNum и исполняется тело цикла.

  1. leds.append(Pin(pinNum, Pin.OUT))

Pin(pinNum, Pin.OUT) мы уже использовали много раз - это выражение создает объект Pin для заданного номера вывода и настраивает его как выход. Полученный таким образом объект Pin добавляется в массив leds с помощью оператора append.

После исполнения этого цикла в массиве leds окажутся 6 объектов Pin для выводов в соответствующем порядке.

Создаем объект АЦП

  1. adc = machine.ADC(0)

Объявляем подпрограмму ledOff()

  1. def ledOff():
  2. for led in leds:
  3. led.off()

Эта функция гасит все светодиоды. Она поочередно перебирает все светодиоды и выключает их.

Объявляем функцию ledOn()

  1. for i in range(count):
  2. led = leds[i]
  3. led.on()

Она нужна для включения нужного количества светодиодов подряд. В качестве параметра она принимает количество светодиодов для включения. Оператор range создает нужную последовательность чисел. Если нужно включить 3 светодиода, он генерирует последовательность чисел 0, 1, 2. Цикл for перебирает эту последовательность и каждое число из последовательности записывает в переменную i.

Отлично, теперь у нас есть понимание, что нужно зажечь, например, первый, второй и третий светодиод. Но как а ним обратиться? Объекты светодиодов записаны в массив leds и лежат в нем под своими номерами, начиная с 0. Номер элемента массива называется индексом. Обратимся к элементам массива по индексам. Именно это и происходит в строке 18. Мы берем i-ый элемент массива, то есть i-ый светодиод, записываем его в переменную led

  1. led = leds[i]

И, когда нужный объект светодиода в переменной, включаем его привычным способом

  1. led.on()

Теперь у нас есть 2 функции ledOff, которая гасит все светодиоды и ledOn, которая включает нужное число светодиодов начиная с первого. Осталось воспользоваться этими функциями для создания светодиодной шкалы.

  1. while True:
  2. value = adc.read()
  3. ledOff()
  4.  
  5. if value in range(0,170):
  6. ledOn(1)
  7. elif value in range(171,340):
  8. ledOn(2)
  9. elif value in range(341,510):
  10. ledOn(3)
  11. elif value in range(511,680):
  12. ledOn(4)
  13. elif value in range(681,850):
  14. ledOn(5)
  15. elif value in range(851,1023):
  16. ledOn(6)

Здесь все просто. Мы считываем значение напряжения с помощью АЦП, выключаем все светодиоды и анализируем сколько светодиодов нужно зажечь. Мы помним, что при 0 вольт результатом преобразования АЦП является 0, а при напряжении питания — 1023. Разобьем этот диапазон на 6 одинаковых интервалов.

Если сигнал в интервале от 0 до 170, то мы должны включить 1 светодиод. Если сигнал в интервале от 171 до 340 — зажигаем 2 светодиода и т.д. С помощью оператора in проверяется попадание переменной в указанный интервал. Если это так, то выражение истинно и оператор if выполняет код для соответствующего условия.

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

  • Попробуй изменить интервалы, чтобы добиться более резкого или плавного роста показаний шкалы
  • Измени 1 строку в программе, чтобы светодиодная шкала начинала светиться не снизу-вверх, а наоборот