← Пульсар | Оглавление | Мерзкое пианино →
В этом эксперименте мы заставляем огонёк бежать по светодиодной шкале.
// светодиодная шкала подключена к группе пинов расположенных // подряд. Даём понятные имена первому и последнему пинам #define FIRST_LED_PIN 2 #define LAST_LED_PIN 11 void setup() { // в шкале 10 светодиодов. Мы бы могли написать pinMode 10 // раз: для каждого из пинов, но это бы раздуло код и // сделало его изменение более проблематичным. // Поэтому лучше воспользоваться циклом. Мы выполняем // pinMode для (англ. for) каждого пина (переменная pin) // от первого (= FIRST_LED_PIN) до последнего включительно // (<= LAST_LED_PIN), всякий раз продвигаясь к следующему // (++pin увеличивает значение pin на единицу) // Так все пины от 2-го по 11-й друг за другом станут выходами for (int pin = FIRST_LED_PIN; pin <= LAST_LED_PIN; ++pin) pinMode(pin, OUTPUT); } void loop() { // получаем время в миллисекундах, прошедшее с момента // включения микроконтроллера unsigned int ms = millis(); // нехитрой арифметикой вычисляем, какой светодиод // должен гореть именно сейчас. Смена будет происходить // каждые 120 миллисекунд. Y % X — это остаток от // деления Y на X; плюс, минус, скобки — как в алгебре. int pin = FIRST_LED_PIN + (ms / 120) % 10; // включаем нужный светодиод на 10 миллисекунд, затем — // выключаем. На следующем проходе цикла он снова включится, // если гореть его черёд, и мы вообще не заметим отключения digitalWrite(pin, HIGH); delay(10); digitalWrite(pin, LOW); }
for
мы организуем цикл со счетчиком. В данном случае для настройки портов на выход. Чтобы сделать такой цикл, нужно:int pin = FIRST_LED_PIN
pin <= LAST_LED_PIN
++pin
(см. ниже об операторе ++
).for (int i = 10; i > 0; i = i - 1)
. В этом случае:i
присваивается значение 10i > 0
i
уменьшается на единицу, согласно заданному правилу, и принимает значение 9i
равного 0i
станет равна 0, условие i > 0
не выполнится, и выполнение цикла закончитсяfor
{}
, если в нем больше одной инструкции.for
, может использоваться внутри цикла. Например, в данном эксперименте pin
последовательно принимает значения от 2 до 11 и, будучи переданной в pinMode
, позволяет настроить 10 портов одной строкой, помещенной в цикл.pin
до или после цикла, компилятор выдаст ошибку о необъявленной переменной.i = i - 1
в пояснении выше не является уравнением! Мы используем оператор присваивания =
для того, чтобы в переменную i
поместить значение, равное текущему значению i
, уменьшенному на 1.++pin
— это т.н. оператор инкремента, примененный к переменной pin
. Эта инструкция даст тот же результат, что pin = pin + 1
--
, уменьшающий значение на единицу. Подробнее об этом в статье про арифметические операции.unsigned int
используют для хранения целых чисел без знака, т.е. только неотрицательных. За счет лишнего бита, который теперь не используется для хранения знака, мы можем хранить в переменной такого типа значения до 65 535.millis
возвращает количество миллисекунд, прошедших с момента включения или перезагрузки микроконтроллера. Здесь мы используем ее для отсчета времени между переключениями светодиодов. (ms / 120) % 10
мы определяем, который из 10 светодиодов должен гореть сейчас. Перефразируя, мы определяем какой отрезок длиной в 120 мс идет сейчас и каков его номер внутри текущего десятка. Мы добавляем порядковый номер отрезка к номеру того порта, который в текущем наборе выступает первым.digitalWrite(pin, LOW)
всего через 10 мс после включения не заметно глазу, т.к. очень скоро будет вновь вычислено, какой из светодиодов включать, и он будет включен — только что погашенный или следующий.++pin
?int
и unsigned int
?millis()
?int pin = FIRST_LED_PIN + (ms / 120) % 10
перемещением огонька управлял цикл for