3.04. Структуры повторения.md


Ваши программы для Рудирона уже умеют работать с данными, выполнять вычисления и принимать решения. Теперь пора научить их повторять действия, чтобы не писать один и тот же код много раз! В этом параграфе вы познакомитесь со структурами повторения, или циклами, которые позволяют плате выполнять задачи многократно.

Представьте, что вы хотите заставить светодиод мигнуть 100 раз. Можно, конечно, 200 раз написать digitalWrite() и delay(), но это ужасно неудобно. Цикл позволяет сказать: «Выполни вот это действие 100 раз», и микроконтроллер сделает это сам.

В C++ для этого используют циклы while и for. Давайте разберёмся, как они работают и как их применять в ваших проектах!

Рис. 1. Принцип работы циклов

Что такое циклы?

Циклы - это специальные конструкции в программировании, которые заставляют микроконтроллер выполнять один и тот же блок кода несколько раз подряд. Это один из фундаментальных принципов, который позволяет автоматизировать задачи и делать программы короткими и мощными. В Рудироне циклы незаменимы для таких задач, как мигание светодиодами, считывание данных с датчиков до получения нужного значения или отправка серии команд мотору.

Мы изучим два основных типа циклов:

  • Цикл while - повторяет действия, пока выполняется определённое условие.
  • Цикл for - повторяет действия заданное количество раз.

Цикл while - повторение по условию

Рис. 2. Принцип работы while

Цикл while (в переводе с английского - «пока») идеально подходит для ситуаций, когда мы не знаем заранее, сколько раз нужно будет повторить действие. Программа будет выполнять блок кода снова и снова, пока условие в скобках остаётся истинным (true).

Аналогия. Вы ждёте, пока закипит чайник. Вы смотрите на него (while (чайник не кипит)), и пока он не кипит, вы продолжаете ждать (тело цикла). Как только он закипел (условие стало false), вы перестаёте ждать и идёте пить чай.

Синтаксис while:

while (условие) {
  // Команды, которые повторяются, пока условие истинно
}
  • условие - это выражение, возвращающее true или false (например, digitalRead(buttonPin) == LOW).

Пример (ожидание старта по кнопке): Представим, что мы создали устройство, которое должно начать свою основную работу только после того, как пользователь нажмёт кнопку «Старт».

const int buttonPin = 35; // Встроенная кнопка B1
const int ledPin = 5;     // Встроенный светодиод L1

void setup() {
  pinMode(buttonPin, INPUT_PULLDOWN);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  
  Serial.println("Устройство готово. Нажмите B1 для старта.");

  // Программа будет "заперта" в этом цикле, пока кнопка не будет нажата
  while (digitalRead(buttonPin) == LOW) {
    // Индикацию ожидания
    digitalWrite(ledPin, HIGH);
    delay(150);
    digitalWrite(ledPin, LOW);
    delay(150);
  }
  
  // Как только кнопка будет нажата, цикл while завершится,
  // и программа перейдёт к выполнению остальной части setup()
  Serial.println("Старт!");
  digitalWrite(ledPin, HIGH); // Зажигаем светодиод, чтобы показать, что работа началась
}

void loop() {
  // Здесь будет основной код программы,
  // который начнёт выполняться только после нажатия кнопки.
  // Пока оставим его пустым.
}

В этом примере, Рудирон после включения не начнёт сразу выполнять loop(). Он будет ждать в setup() внутри цикла while, мигая светодиодом. И только после того, как вы нажмёте кнопку B1, он выйдет из цикла, выведет «Старт!» и перейдёт к основной части программы в loop().

Цикл for - повторение заданное число раз

Рис. 3. Принцип работы for

Цикл for используется, когда вы точно знаете, сколько раз нужно повторить действие. Например, если вы хотите, чтобы светодиод мигнул ровно 5 раз, или чтобы робот сделал ровно 10 шагов. Этот цикл удобен тем, что в одной строке объединяет всё необходимое для подсчёта повторений.

Синтаксис for:

for (инициализация; условие; шаг) {
  // Команды, которые повторяются на каждой итерации
}

Эта конструкция состоит из трёх частей, разделённых точкой с запятой:
1. Инициализация. Создаётся переменная-счётчик и ей задаётся начальное значение. Выполняется один раз в самом начале. Пример: int i = 0.
2. Условие. Проверяется перед каждым выполнением блока кода. Если оно true, цикл продолжается. Если false — завершается. Пример: i < 5.
3. Шаг (инкремент/декремент) Изменяет счётчик после каждого выполнения блока кода. Чаще всего это i++ (увеличить i на 1).

Пример (мигаем светодиодом ровно 5 раз):

const int ledPin = 5;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // Этот цикл выполнится 5 раз (для i = 0, 1, 2, 3, 4)
  for (int i = 0; i < 5; i++) {
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
  }

  // После 5 миганий программа сделает длинную паузу
  delay(2000); 
  // И так как это loop(), всё начнётся заново
}

В этом коде Рудирон мигнёт светодиодом ровно 5 раз. После этого он подождёт 2 секунды и, поскольку находится в loop(), снова повторит серию из 5 миганий.

Зачем это нужно?

Циклы while и for — это мощные инструменты для ваших проектов. Они позволяют автоматизировать повторяющиеся задачи, делая код коротким и читаемым.

  • С while вы можете заставить программу ждать какого-то события, например, нажатия кнопки или получения нужных данных с датчика.
  • С for вы можете выполнять действия точное количество раз, например, проигрывать мелодию из 10 нот или заставлять сервопривод делать 3 движения.

Освоив циклы, вы сможете писать гораздо более сложные и интересные программы.


Вы освоили циклы while и for, которые позволяют плате Рудирон автоматизировать повторяющиеся задачи. Теперь переходите к следующему параграфу, чтобы научиться работать с массивами и хранить наборы данных для ваших проектов. А чтобы закрепить знания, попробуйте выполнить задания к этому параграфу.