Лабораторная работа №1. Управление работой светодиодов на плате Arduino UNO

Для того, чтобы выполнить то, что описано в этой работе, кроме самой платы, нам понадобится среда разработки Arduino IDE, светодиоды, провода, резисторы, потенциометр. Приступим…

Первым делом запускаем Arduino IDE, выбираем меню «Файл» и нажимаем «Новый».

1. Работа с двумя светодиодами (Мигалка)

Возьмём два светодиода разного цвета, резистор и соберём схему на ​​ макетной плате, подключив один светодиод к выводу номер 3 и другому входу GND, а второй светодиод к выводу номер 9.

 

 

Отредактируем программу таким образом, чтобы оба светодиода мигали в противофазу: первый выключен, второй горит максимально ярко и наоборот.

У меня получился следующий код.

int led_9 = 9; // контакт 9

int led_3 = 3; // контакт 3

int brightness = 0;  ​​ ​​​​ // минимальная яркость

int fadeAmount = 5;  ​​ ​​​​ // величина изменения яркости за шаг

void setup() ​​ { 

 ​​​​ // два контакта в режиме вывода

 ​​​​ pinMode(led_9, OUTPUT);

 ​​​​ pinMode(led_3, OUTPUT);

} 

void loop() ​​ { 

 ​​​​ // у первого контакта минимальное значение, ​​ у второго - максимальное

 ​​​​ analogWrite(led_9, brightness); 

 ​​​​ analogWrite(led_3, 255 - brightness); ​​ 

 ​​​​ // остальной код без изменений

 ​​​​ // change the brightness for next time through the loop:

 ​​​​ brightness = brightness + fadeAmount;

 ​​​​ // reverse the direction of the fading at the ends of the fade: 

 ​​​​ if (brightness == 0 || brightness == 255) {

 ​​ ​​ ​​​​ fadeAmount = -fadeAmount ; 

 ​​​​ }  ​​ ​​ ​​​​ 

 ​​​​​ // wait for 30 milliseconds to see the dimming effect  ​​ ​​​​ 

 ​​​​ delay(30);  ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ 

}

2. ​​ Работа со множеством светодиодов

Для знакомства с циклом for в Arduino IDE есть пример File / Examples / 05.Control / ForLoopIteration.

Для эксперимента нам понадобятся шесть светодиодов. Соответственно, к ним нужно добавить шесть резисторов. Соединяем их как на рисунке. Задействуем цифровые выводы 2, 3, 4, 5, 6, 7.

Цель скетча — поочерёдно зажигать и гасить светодиоды в одном направлении, а затем в другом.

int timer = 100;  ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ // интервал между миганиями светодиодов

void setup() {

 ​​​​ // проходимся в цикле по каждому светодиоду от 2 до 7 и влючаем нужный режим

 ​​​​ for (int thisPin = 2; thisPin < 8; thisPin++) {

 ​​ ​​ ​​​​ pinMode(thisPin, OUTPUT);

 ​​​​ }

}

void loop() {

 ​​​​ // опять проходимся в цикле по каждому светодиоду

 ​​​​ for (int thisPin = 2; thisPin < 8; thisPin++) {

 ​​ ​​ ​​​​ // включаем

 ​​ ​​ ​​​​ digitalWrite(thisPin, HIGH);

 ​​ ​​ ​​​​ delay(timer);

 ​​ ​​ ​​​​ // выключаем

 ​​ ​​ ​​​​ digitalWrite(thisPin, LOW);

 ​​​​ }

 ​​​​ // ещё раз проходимся в цикле, но в обратном порядке от 7 до 2

 ​​​​ for (int thisPin = 7; thisPin >= 2; thisPin--) {

 ​​ ​​ ​​​​ // включаем

 ​​ ​​ ​​​​ digitalWrite(thisPin, HIGH);

 ​​ ​​ ​​​​ delay(timer);

 ​​ ​​ ​​​​ // выключаем

 ​​ ​​ ​​​​ digitalWrite(thisPin, LOW);

 ​​​​ }

}

Обращаться к каждому светодиоду можно не только по очереди в цикле, но и через массив. Использование массивов даёт больше гибкости. Посмотрим на примере File / Examples / 5.Control / Arrays. Схема остаётся прежней из предыдущего примера.

Массив объявляется с помощью квадратных скобок, а затем к переменной массива обращаются, указывая в квадратных скобках индекс массива, который начинается с 0. Таким образом, чтобы обратиться к первому элементу массива, следует писать ledPins[0].

int timer = 100;

int ledPins[] = {

 ​​​​ 2, 7, 4, 6, 5, 3

};  ​​ ​​ ​​ ​​ ​​​​ // массив в случайном порядке

int pinCount = 6;  ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ // количество светодиодов (размер массива)

void setup() {

 ​​​​ for (int thisPin = 0; thisPin < pinCount; thisPin++) {

 ​​ ​​ ​​​​ pinMode(ledPins[thisPin], OUTPUT);

 ​​​​ }

}

void loop() {

 ​​​​ for (int thisPin = 0; thisPin < pinCount; thisPin++) {

 ​​ ​​ ​​​​ digitalWrite(ledPins[thisPin], HIGH);

 ​​ ​​ ​​​​ delay(timer);

 ​​ ​​ ​​​​ digitalWrite(ledPins[thisPin], LOW);

 ​​​​ }

 ​​​​ // loop from the highest pin to the lowest:

 ​​​​ for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) {

 ​​ ​​ ​​​​ digitalWrite(ledPins[thisPin], HIGH);

 ​​ ​​ ​​​​ delay(timer);

 ​​ ​​ ​​​​ digitalWrite(ledPins[thisPin], LOW);

 ​​​​ }

}

Если вы замените строку int ledPins[] = {2, 7, 4, 6, 5, 3}; на int ledPins[] = {2, 3, 4, 5, 6, 7};, то получите точно такое же поведение светодиодов из предыдущего примера с циклом for, когда светодиоды загораются и гаснут по очереди. Но использование массива позволяет поменять начальное положение светодиодов, не меняя остальной код. И вы можете только в одном месте менять начальные позиции для запуска волны. Например, зададим массив через одного: {2, 4, 6, 3, 5, 7}.

Бегущие огни

Ещё один вариант бегущих по порядку огней. На этот раз уместим код в один цикл for, добавив переменную, следящую за направлением движения.

const int ARRAY_SIZE = 6;

int ledPin[] = {2, 3, 4, 5, 6, 7};

int ledDelay = 500;

int direction = 1;

int currentLed = 0;

unsigned long changeTime;




void setup() {

 ​​​​ for (int i = 0; i < ARRAY_SIZE; i++) {

 ​​ ​​ ​​​​ pinMode(ledPin[i], OUTPUT);

 ​​​​ }

 ​​​​ changeTime = millis();

}

void loop() {

 ​​​​ if ((millis() - changeTime) > ledDelay) {

 ​​ ​​ ​​​​ changeLed();

 ​​ ​​ ​​​​ changeTime = millis();

 ​​​​ }

}

void changeLed() {

 ​​​​ // выключаем все светодиоды

 ​​​​ for (int i = 0; i < ARRAY_SIZE; i++) {

 ​​ ​​ ​​​​ digitalWrite(ledPin[i], LOW);

 ​​​​ }

 ​​​​ // включаем текущий LED

 ​​​​ digitalWrite(ledPin[currentLed], HIGH);

 ​​​​ // увеличиваем значение

 ​​​​ currentLed += direction;

 ​​​​ // меняем направление, если достигли конца

 ​​​​ if (currentLed == ARRAY_SIZE - 1) {

 ​​ ​​ ​​​​ direction = -1;

 ​​​​ }

 ​​​​ if (currentLed == 0) {

 ​​ ​​ ​​​​ direction = 1;

 ​​​​ }

}

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

Световая шкала и потенциометр

Рассмотрим пример с использованием светодиодной шкалы и потенциометраExamples / 07.Display / barGraph. Если световой шкалы нет, то замените на 10 обычных светодиодов.

Изменяя вручную напряжение при помощи потенциометра, мы будем выводить информацию на световую шкалу.

Добавим на схему потенциометр. Средняя ножка ведёт на аналоговый вывод A0, а остальные две на 5 V и GND.

// константы

const int analogPin = A0;  ​​​​ // порт для потенциометра

const int ledCount = 10;  ​​ ​​​​ // число светодиодов на светодиодной шкале

int ledPins[] = {

 ​​​​ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };  ​​​​ // массив портов, к которым привязаны светодиоды

void setup() {

 ​​​​ // проходим через все элементы массива и устанавливаем режим для вывода

 ​​​​ for (int thisLed = 0; thisLed < ledCount; thisLed++) {

 ​​ ​​ ​​​​ pinMode(ledPins[thisLed], OUTPUT);

 ​​​​ }

}

void loop() {

 ​​​​ // считываем сигнал с потенциометра

 ​​​​ int sensorReading = analogRead(analogPin);

 ​​​​ // трансформируем результат в диапазон от 0 до 10 (по числу светодиодов)

 ​​​​ int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

 ​​​​ // проходим через массив светодиодов

 ​​​​ for (int thisLed = 0; thisLed < ledCount; thisLed++) {

 ​​ ​​ ​​​​ // если индекс элемента массива меньше чем ledLevel,

 ​​ ​​ ​​​​ // включаем порт для данного элемента:

 ​​ ​​ ​​​​ if (thisLed < ledLevel) {

 ​​ ​​ ​​ ​​ ​​​​ digitalWrite(ledPins[thisLed], HIGH);

 ​​ ​​ ​​​​ } 

 ​​ ​​ ​​​​ // Выключаем все порты, которые выше чем ledLevel:

 ​​ ​​ ​​​​ else {

 ​​ ​​ ​​ ​​ ​​​​ digitalWrite(ledPins[thisLed], LOW);

 ​​ ​​ ​​​​ }

 ​​​​ }

}

Данный пример интересен функцией map(), предназначенной для пропорционального перевода значений одного диапазона в значения другого диапазона. Мы знаем, что потенциометр может выводить результаты от 0 до 1023, а у нас всего десять светодиодов. Функция нам и поможет в преобразовании.

int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

Все значения будут равномерно распределены от 0 до 10 (приблизительно 102 единицы потенциометра на одну единицу). Представим себе, что у нас потенциометр показывает значение 110 единиц, что соответствует значению 1 после применения функции. Первый светодиод в массиве имеет значение 0, т.е. меньше 1. Первый светодиод загорится, а остальные погаснут (если горели до этого). Поворачивая ручку потенциометра, мы увеличиваем значения и соответственно увеличиваем число включённых светодиодов. Поворачивая ручку потенциометра в обратную сторону, мы уменьшаем число включённых светодиодов. Чтобы следить за результатами, добавьте в код наблюдение за последовательным портом Serial

 ​​​​ int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

 ​​​​ Serial.println(sensorReading);

 ​​​​ delay(1);

 ​​​​ ...