Эксперимент 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. for (int i = 0; i < 6; i++) {
  20. pinMode(myPins[i], OUTPUT);
  21. }
  22. }
  23.  
  24. void loop() {
  25. value = analogRead(ACD_PIN);
  26. ledOff();
  27.  
  28. if (value > 850) ledOn(6);
  29. else if (value > 680) ledOn(5);
  30. else if (value > 510) ledOn(4);
  31. else if (value > 340) ledOn(3);
  32. else if (value > 170) ledOn(2);
  33. else ledOn(1);
  34. }

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

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

Массивы

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

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

Теперь нам необходимо переключить 6 выводов микроконтроллера в режим OUTPUT c помощью знакомой нам функции pinMode(). Мы могли бы написать шесть строк с вызовом этой функции для каждого пина, но это достаточно громоздко. Цикл for позволит нам сделать тоже самое в 3 строчки. Вроде не очень большая экономия? Представь, что пинов не 6, а например 20 или еще больше.

  1. void setup()
  2. {
  3. for (int i = 0; i < 6; i++) {
  4. pinMode(myPins[i], OUTPUT);
  5. }
  6. }

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

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

  1. void ledOff(){
  2. for (int i = 0; i < 6; i++) {
  3. digitalWrite(myPins[i], LOW);
  4. }
  5. }

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

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

  1. void ledOn(int count){
  2. for (int i = 0; i < count; i++) {
  3. digitalWrite(myPins[i], HIGH);
  4. }
  5. }

Она нужна для включения нужного количества светодиодов подряд. В качестве параметра count она принимает количество светодиодов для включения. Цикл for перебирает элементы массива до полученного параметра count и зажигает светодиоды привычным нам способом.

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

  1. void loop()
  2. {
  3. value = analogRead(ACD_PIN);
  4. ledOff();
  5.  
  6. if (value > 850) ledOn(6);
  7. else if (value > 680) ledOn(5);
  8. else if (value > 510) ledOn(4);
  9. else if (value > 340) ledOn(3);
  10. else if (value > 170) ledOn(2);
  11. else ledOn(1);
  12. }

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

Мы последовательно с помощью оператора if…else сравниваем полученное значение с верхней границей интервала и если оно больше зажигаем с помощью функции ledOn() соответствующее количество светодиодов.

Внимательные экспериментаторы заметили отсутствие фигурных скобок {} после оператораif. После операторов и циклов допускается опускать фигурные скобки в случае, если тело состоит только из одной строки. Кроме того в этом случае тело можно записать в одной строке сразу после объявления оператора или цикла.

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

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