Arduino uno программа для создания бегущих огней. Бегущие поворотники на ленте WS2812 и Arduino. Вопросы для проверки себя

В этом уроке мы продолжим работу со светодиодами, но количество светодиодов увеличим до 5. И сделаем эффект бегущего огня. Для управления светодиодами будем использовать манипуляции с портами Arduino. Мы будем напрямую записывать данные в порты Arduino. Это лучше, чем работать с конкретными входами/выходами контроллера. Это позволит установить значения для светодиодов при помощи одной лишь операции.

У Arduino UNO имеется 3 порта:
B (цифровые входа/выхода с 8 по 13)
C (аналоговые входа)
D (цифровые входа/выхода с 0 по 7)

Каждый порт управляется 3 регистрами. Регистр DDR определяет чем будет являться нога (pin) входом или выходом. При помощи регистра PORT можно установить pin в состояние HIGH или LOW . При помощи регистра PIN можно считать состояние ножек Arduino, когда они работает на вход.

Мы будем использовать порт B. Сначала, мы должны установить все ножки порта B как цифровые выхода. У порта B имеется только 6 ножек. Биты регистра для В-порта DDRB должны быть установлены в 1, если нога будет использоваться как выход (OUTPUT), и в 0, если нога будет использовать как вход (INPUT). Биты портов нумеруются с 0 по 7, но не всегда содержат все 8 ног.
Пример:
DDRB = B00111110; // установить ножки порта В с 1 по 5 как выхода, а 0 как вход.

Обратите внимание, что в микроконтроллерах фирмы Microchip все наоборот. 0 бит - нога работает как выход, а 1 - как вход.

В нашем проекте бегущего огня мы будем использовать 5 выходов:
DDRB = B00011111; // установить ноги порта В с 0 по 4 как выхода

Для записи значений в порт В необходимо использовать регистр PORTB.
Зажечь первый светодиод можно командой:
PORTB = B00000001;
первый и четвертый:
PORTB = B00001001;

Теперь вы видите, как легко мы можем включать и выключать светодиоды. Теперь расскажем вам об операторах сдвига

Есть 2 оператора двоичного сдвига: оператор сдвига влево << и оператор сдвига вправо >>. Оператор сдвига влево << заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> сдвигает биты вправо.

Пример:
varA = 1; // 00000001
varA = 1 << 0; // 00000001
varA = 1 << 1; // 00000010
varA = 1 << 2; // 00000100

Теперь вернемся к нашей программе, которая показана ниже.
Нам нужно ввести 2 переменные: первая upDown будет содержать значение куда двигаться - вверх или вниз, а вторая cylon какие светодиоды зажигать.

В функции setup() мы определяем какие ножки должны работать как выхода.

В главном цикле программы loop() , светодиоды по очереди загораются вверх путем увеличения переменной cylon , а когда доходит до самого верхнего, то переменной upDown присваивается 0 и светодиоды загораются вниз по очереди.

/* Бегущий огонь. 5 светодиодов */ unsigned char upDown=1; // начинаем с движения вверх unsigned char cylon=0; // определяет очередность LED void setup() { DDRB = B00011111; // устанавливаем порт B с 0 по 4 как выхода } void loop() { if(upDown==1){ // если идем вверх, то cylon++; if(cylon>=4) upDown=0; // когда достигнут наибольший номер LED, то в след. цикле идем вниз } else { cylon--; if(cylon==0) upDown=1; // когда достигнут наименьший номер LED, то в след. цикле идем вверх } PORTB = 1 << cylon; //сдвиг delay(200); // пауза 200 мс }

Делаем бегущие огни из светодиодов на Arduino. В данном случае используется Arduino Mega 2560, который потенциально способен управлять бегущей дорожкой из 54-х светодиодов. Но схема и программа не изменятся, если вы будете использовать другие контроллеры из платформы Arduino такого типа (UNO, Leonardo...)

Схема подключения светодиодов к Ардуино Мега 2560.

Так выглядит скетч в окне стандартного приложения для программирования Ардуино.

Текст программы для реализации бегущих огней на платформе ардуино.

int first_out = 11; //первый дискретный выход

int last_out = 13; //последний дискретный выход

//блок для инициализации входов-выходов и других исходных данных

last_out = last_out + 1; //добавляем единицу для корректного использования в циклах

//определение 11-го, 12-го и 13-го дискретных выводов платы Ардуино как выходы

for (i = first_out; i < last_out; i++) { pinMode(i, OUTPUT); }

for (t = first_out; t < last_out; t++) { //перебираем номера дискретных выходов 11,12,13 поочереди

digitalWrite(t, HIGH); //зажигание следующего светодиода

delay(500); //задержка 500мсек

for (i = first_out; i < last_out; i++) { digitalWrite(i, LOW); }//гасим все светодиоды

Для увеличения количества управляемых светодиодов в гирлянде, в программе нужно будет просто заменить значения переменных first_out и last_out. Первая переменная хранит начальный дискретный выход контроллера, а вторая последний из группы выходов, которые идут подряд. Например, если мы хотим подключить 10 светодиодов в гирлянду, вводим такие значения: first_out = 4, last_out = 13. И светодиоды к выводам по порядку с 4-го по 13-й. А первый и второй вывод дискретных входов-выходов лучше не трогать, так как им мешает usb-порт, подключенный к компьютеру.

Объявляется переменная timer . Это целое число, с именем timer , и эта строка устанавливает это число равным 200. Как вы могли заметить, большинство строк программ Arduino заканчиваются точкой с запятой. При написании и изменении собственных скетчей Arduino не забываете о точке с запятой, поскольку строка без такого знака вызовет ошибку компиляции.

void setup() {
// use a for loop to initialize each pin as an output:
< 8; thisPin++) {
pinMode(thisPin, OUTPUT);
}
}

Процедура setup (Настройка) конфигурирует контакты платы с 3 по 7 как выходы с использованием цикла for, который представляет собой специальный цикл, который несколько раз повторяет небольшую часть кода на основе условия, используя счетчик приращений. Условие проверяется каждый раз когда повторяется цикл. Цикл продолжит выполнения кода внутри него до тех пор, пока условие истинно. Изначально переменная thisPin установлена в 3, условие заключается в том, что этот номер Pin должен быть меньше 8, а счетчик приращений увеличивает это значение переменной Pin при каждом повторении цикла (thisPin ++ - это то же самое, что и thisPin = thisPin + 1 ). Итак, на первом прохождении уикла, контакт с номером 3 устанавливается в режим выхода. Во второй проход уже контакт 4 конфигурируется на выход. И так далее, пока thisPin не станет равным 8, после чего условие thisPin < 8 станет ложным и код прекратит цикл, продолжая работу с остальной частью программы. Это может показаться слишком сложным способом сделать простую вещь, но программисты любят эффективность! Вы можете так же легко выполнить конфигурацию контактов следующим образом, так сказать "в лоб":

void setup() {
// initialize each pin as an output:
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
}

Вы можете заметить, что, как правило, при программировании для Arduino одну и ту же задачу можно решить разными способами. Кодирование похоже на создание вещей в вашей мастерской: вы, как правило, используете любые инструменты, которые у вас есть. Поэтому давайте использовать цикл
for для чего-то веселого... анимации!

Void loop() {

// loop from the lowest pin to the highest:
for (int thisPin = 3; thisPin < 8; thisPin++) {
// turn the pin on:
digitalWrite(thisPin, HIGH);
delay(timer);
// turn the pin off:
digitalWrite(thisPin, LOW);
}

Цикл начинается с того же самого оператора, что и раньше, при увеличении от меньшего числа до большего. Внутри цикла
for код включает светодиод на контакте Pin , останавливается на 200 мс (Мы ч вами ранее присвоили это число переменной timer ), затем код выключает этот светодиод. Далее цикл повторяется, но уже со следующим светодиодом

// loop from the highest pin to the lowest:
for (int thisPin = 7; thisPin >= 3; thisPin--) {
// turn the pin on:
digitalWrite(thisPin, HIGH);
delay(timer);
// turn the pin off:
digitalWrite(thisPin, LOW);
}
}

Следующая часть кода - еще один цикл, но он начинается с контакта платы с наибольшим номером и использует
thisPin-- (так называемый Декримент, уменьшение на единицу), что равносильно выражению thisPin = thisPin-1 . Можно писать и так, и так, но thisPin-- короче и эффективнее. Программа выходит из этого цикла когда thisPin становится меньше 3 (условие > = 3 , больше или равно трем, то есть 2). Конечная закрывающая фигурная скобка закрывает основной (главный, большой) цикл. Таким образом, эта программа подсвечивает каждый светодиод по порядку, затем изменяет порядок на противоположный и снова зажигает светодиоды.

Принципиальная схема

Схема на макетке

Обратите внимание

    Обратите внимание, что в данном эксперименте резисторы установлены между катодами и землей в отличие от эксперимента пульсар .

    Мы подключаем светодиоды к цифровым портам, начиная с порта 2. Мы можем использовать порты 0 и 1, но они являются каналами передачи данных последовательного порта и для каждой перепрошивки платы придется отключать устройства, подключенные к ним.

Скетч

Тип данных unsigned int используют для хранения целых чисел без знака, т.е. только неотрицательных . За счет лишнего бита, который теперь не используется для хранения знака, мы можем хранить в переменной такого типа значения до 65 535.

С помощью выражения (ms / 120) % 10 мы определяем, который из 10 светодиодов должен гореть сейчас. Перефразируя, мы определяем какой отрезок длиной в 120 мс идет сейчас и каков его номер внутри текущего десятка. Мы добавляем порядковый номер отрезка к номеру того порта, который в текущем наборе выступает первым.

То, что мы гасим светодиод с помощью digitalWrite(pin, LOW) всего через 10 мс после включения не заметно глазу, т.к. очень скоро будет вновь вычислено, какой из светодиодов включать, и он будет включен - только что погашенный или следующий.

Вопросы для проверки себя

    Почему в данном эксперименте мы подключаем светодиодную шкалу, не используя транзистор?

    Если бы мы включали светодиоды только на портах 5, 6, 7, 8, 9, что нужно было бы изменить в программе?

    С помощью какой другой инструкции можно выполнить действие, эквивалентное ++pin ?

    В чем разница между переменными типов int и unsigned int ?

    Что возвращает функция millis() ?

    Как в данном эксперименте мы вычисляем номер порта, на котором нужно включить светодиод?

В этом уроке мы продолжим работу со светодиодами, но количество светодиодов увеличим до 5. И сделаем эффект бегущего огня. Для управления светодиодами будем использовать манипуляции с портами Arduino. Мы будем напрямую записывать данные в порты Arduino. Это лучше, чем работать с конкретными входами/выходами контроллера. Это позволит установить значения для светодиодов при помощи одной лишь операции.

У Arduino UNO имеется 3 порта:

  • B (цифровые входа/выхода с 8 по 13)
  • C (аналоговые входа)
  • D (цифровые входа/выхода с 0 по 7)

Каждый порт управляется 3 регистрами. Регистр DDR определяет чем будет являться нога (pin) входом или выходом. При помощи регистра PORT можно установить pin в состояние HIGH или LOW. При помощи регистра PIN можно считать состояние ножек Arduino, когда они работает на вход.

Мы будем использовать порт B. Сначала, мы должны установить все ножки порта B как цифровые выхода. У порта B имеется только 6 ножек. Биты регистра для В-порта DDRB должны быть установлены в 1, если нога будет использоваться как выход (OUTPUT), и в 0, если нога будет использовать как вход (INPUT). Биты портов нумеруются с 0 по 7, но не всегда содержат все 8 ног.

Пример :

DDRB = B00111110; // установить ножки порта В с 1 по 5 как выхода, а 0 как вход.

Обратите внимание, что в микроконтроллерах фирмы Microchip все наоборот. 0 бит - нога работает как выход, а 1 - как вход.

В нашем проекте бегущего огня мы будем использовать 5 выходов:

DDRB = B00011111; // установить ноги порта В с 0 по 4 как выхода

Для записи значений в порт В необходимо использовать регистр PORTB. Зажечь первый светодиод можно командой:

PORTB = B00000001;
первый и четвертый:
PORTB = B00001001;

Теперь вы видите, как легко мы можем включать и выключать светодиоды. Теперь расскажем вам об операторах сдвига

Есть 2 оператора двоичного сдвига: оператор сдвига влево << и оператор сдвига вправо >>. Оператор сдвига влево << заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> сдвигает биты вправо.

Пример:

VarA = 1; // 00000001
varA = 1 << 0; // 00000001
varA = 1 << 1; // 00000010
varA = 1 << 2; // 00000100

Теперь вернемся к нашей программе, которая показана ниже. Нам нужно ввести 2 переменные: первая upDown будет содержать значение куда двигаться - вверх или вниз, а вторая cylon какие светодиоды зажигать.

В функции setup() мы определяем какие ножки должны работать как выхода.

В главном цикле программы loop() , светодиоды по очереди загораются вверх путем увеличения переменной cylon , а когда доходит до самого верхнего, то переменной upDown присваивается 0 и светодиоды загораются вниз по очереди.

Просмотров