Робот-курьер Урок 2.1 Все курсыДля учителяПройти в программе Ученик Arduino Uno + шилд моторов L298P
Тема 2 · Урок 2.1

Моторы: едем и останавливаемся

Первые движения робота: вперёд, назад и обязательная остановка из программы.

2 × 45 мин1–2 ученика на роботаПрактика

Результат урока

Робот проезжает вперёд, останавливается и возвращается назад по программе. Движения оформлены функциями forward(), backward() и stopMotors().

Ты научишься

  • Объяснить, что задаёт контакт направления и что — контакт скорости.
  • Включить и остановить моторы командами digitalWrite и analogWrite.
  • Написать функции движения и вызвать их по порядку.
  • Объяснить, почему движение без команды остановки не заканчивается.

Нужно знать

  • 1.1 Собираем робота и оживляем плату

Понадобится

Мотор-редуктор × 2Шилд моторов L298P (Амперка)Батарейный отсек моторов с выключателемUSB-кабель для Arduino

Зачем этот урок

Робот собран, но пока стоит. Сегодня он поедет. Ты узнаешь, как плата командует моторами, и научишь робота ехать вперёд, назад и — самое важное — останавливаться по программе.

Разминка · вспомни
  1. Сколько раз выполняется setup(), а сколько — loop()?
  2. Что делает digitalWrite(вывод, HIGH)?
  3. Где на твоём роботе левый мотор?
Безопасность

Моторы проверяем на подставке: колёса не касаются стола. Программу загружаем при выключенном питании моторов. Чтобы остановить опыт, выключи питание моторов выключателем.

1
Занятие 1 · 45 мин
Один мотор, потом два
1

Подготовь робота

5 мин

Что должен делать робот. Роботу нужно начать движение, проехать участок и остановиться. Для этого научимся отдельно задавать направление и мощность каждого из двух моторов, а затем объединим команды в понятные действия.

Что используем и как это работает. Моторы подключены через драйвер L298P: вывод Arduino подаёт управляющий сигнал, а ток к мотору поступает через драйвер. DIR выбирает направление. ШИМ быстро чередует включение и выключение питания; большее значение analogWrite означает большую долю включённого времени. Это команда мощности, а не измеренная скорость в сантиметрах в секунду.

Как связать измерение с действием. Если оба колеса крутятся вперёд, робот едет; если одно слабее, он отклоняется. delay только задерживает следующую команду: мотор продолжает выполнять предыдущую. Поэтому в программе нужна отдельная остановка. Сначала наблюдаем колёса на подставке, затем проверяем направление, расстояние и остановку на поле.

  1. Поставь робота на подставку так, чтобы оба колеса висели в воздухе.
  2. Найди выключатель питания моторов и выключи его.
  3. Подключи USB-кабель.
Должно получиться

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

2

Включи левый мотор

15 мин

Каждым мотором управляют два контакта. Контакт направления решает, куда крутится колесо. Контакт скорости решает, насколько сильно: число от 0 (стоит) до 255 (полная мощность). Левый мотор подключён к контактам 7 (направление) и 6 (скорость).

Левый моторL21_Left_Motor.ino.ino
const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int FORWARD = HIGH; void setup() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);   digitalWrite(LEFT_DIR_PIN, FORWARD);  analogWrite(LEFT_SPEED_PIN, 100);  delay(2000);  analogWrite(LEFT_SPEED_PIN, 0);} void loop() {}
Предскажи

Что сделает колесо после загрузки? Сколько секунд оно будет крутиться? Остановится ли оно само? Скажи напарнику до запуска.

  1. Набери программу и загрузи её при выключенном питании моторов.
  2. Включи питание моторов и нажми кнопку Reset на плате: программа начнётся заново.
  3. Сравни, что произошло, со своим прогнозом.
Должно получиться

Левое колесо крутится вперёд 2 секунды и останавливается.

Как это устроено: Что значит каждая строка
  • const int LEFT_DIR_PIN = …; — имя для номера контакта. Дальше в программе пишем имя, а не число: так понятнее и меньше ошибок.
  • digitalWrite(LEFT_DIR_PIN, FORWARD); — выбрать направление «вперёд».
  • analogWrite(LEFT_SPEED_PIN, 100); — включить мотор с силой 100 из 255.
  • analogWrite(LEFT_SPEED_PIN, 0); — остановить мотор.
  • Всё написано в setup(), поэтому выполняется один раз. loop() пустой: после остановки робот просто стоит.
Если не получилось
Что видишьЧто сделать
Колесо не крутитсяВключено ли питание моторов? Нажми Reset после включения.
Колесо крутится назадЗапиши это в журнал — на следующем шаге исправим направлением.
Крутится правое колесоПровода моторов перепутаны на шилде. Выключи питание и поменяй местами провода в клеммах M1 и M2.

Каждым мотором управляют два контакта. Контакт направления решает, куда крутится колесо. Контакт скорости решает, насколько сильно: число от 0 (стоит) до 255 (полная мощность). Левый мотор подключён к контактам 7 (направление) и 6 (скорость).

КомандаЧто делает
pinMode(контакт, OUTPUT);Разрешает плате управлять контактом
digitalWrite(контакт, FORWARD);Выбирает направление «вперёд»
analogWrite(контакт, сила);Включает мотор с силой от 0 до 255; 0 — стоп
delay(мс);Ждёт указанное число миллисекунд
  1. Создай скетч L21_Left_Motor по шаблону и напиши setup() сам: что должно произойти, сказано в комментариях.
Шаблон: левый моторL21_Left_Motor_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях. const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int FORWARD = HIGH; // ===== Твоя часть: напиши сам ===== void setup() {  // Подготовь оба контакта левого мотора.  // Левое колесо крутится вперёд 2 секунды с силой 100 из 255 и останавливается само.} void loop() {}
Предскажи

Что будет, если забыть команду остановки? Запиши ответ и проверяй его только на подставке.

  1. Загрузи программу при выключенном питании моторов.
  2. Включи питание моторов и нажми кнопку Reset на плате: программа начнётся заново.
Подсказка: С чего начать

Сначала оба контакта должны стать выходами, потом — направление, потом сила.

Должно получиться

Левое колесо крутится вперёд 2 секунды и останавливается. Прогноз записан.

Если не получилось
Что видишьЧто сделать
Колесо не крутитсяНастроены ли контакты как выходы? Включено ли питание моторов? Нажми Reset.
Колесо крутится назадЗапиши это в журнал — на следующем шаге исправим направлением.
Крутится правое колесоПровода моторов перепутаны на шилде. Выключи питание и поменяй местами провода в клеммах M1 и M2.

Левый мотор подключён к контактам 7 (направление) и 6 (скорость). Направление «вперёд» на этом комплекте — уровень HIGH.

Как это устроено: Справка по командам
КомандаЧто делает
pinMode(pin, OUTPUT)Разрешает плате управлять контактом
digitalWrite(pin, HIGH) / LOWНаправление мотора
analogWrite(pin, v)Сила мотора: v от 0 (стоит) до 255
delay(ms)Ждать ms миллисекунд

Требование 1. Скетч L21_Left_Motor: левое колесо крутится вперёд ровно 2 секунды с силой из именованной переменной и останавливается само. Номера контактов — именованные константы, а не числа в командах.

Приёмка.

  1. На подставке напарник засекает по секундомеру, сколько крутится колесо.
  2. Замени уровень направления на противоположный. Что сделало колесо? Запиши, какой уровень на твоём роботе — «вперёд».
  3. Объясни в журнале, почему колесо остановилось, хотя loop() пустой.
Подсказка: Идея (1 из 2)

Один раз при включении: настроить контакты, выбрать направление, включить, подождать, выключить.

Подсказка: Подсказка к пункту 3 (2 из 2)

Где выполнилась команда остановки — в setup() или в loop()? Сколько раз?

Должно получиться

Колесо крутится 2 секунды и останавливается. В журнале — время по секундомеру, уровень «вперёд» и объяснение остановки.

3

Включи оба мотора

15 мин
  1. Создай скетч L21_Both_Motors и набери программу.
Оба мотораL21_Both_Motors.ino.ino
const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH; int speed = 100; void setup() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);   digitalWrite(LEFT_DIR_PIN, FORWARD);  digitalWrite(RIGHT_DIR_PIN, FORWARD);  analogWrite(LEFT_SPEED_PIN, speed);  analogWrite(RIGHT_SPEED_PIN, speed);  delay(1000);   analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void loop() {}
  1. Загрузи и запусти на подставке.
  2. Поменяй speed на 60, потом на 200. Как меняется вращение?
Должно получиться

Оба колеса крутятся вперёд одну секунду и останавливаются. С большим speed колёса крутятся быстрее.

Как это устроено: Почему 0–255, а не километры в час

Число в analogWrite — это не скорость, а доля времени, когда мотор включён. При 255 он включён всё время, при 100 — примерно 40 % времени. Настоящая скорость зависит ещё от батареи и пола. Поэтому скорость подбирают опытом.

Правый мотор устроен так же, как левый: контакт направления 4 и контакт скорости 5. Имена всех четырёх контактов в шаблоне уже есть.

  1. Создай скетч L21_Both_Motors по шаблону и напиши setup() сам. Свою программу левого мотора используй как образец.
Шаблон: оба мотораL21_Both_Motors_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях. const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;int speed = 100; // ===== Твоя часть: напиши сам ===== void setup() {  // Подготовь контакты обоих моторов.  // Оба колеса крутятся вперёд со скоростью speed одну секунду и останавливаются.} void loop() {}
  1. Загрузи и запусти на подставке.
  2. Поменяй speed на 60, потом на 200. Как меняется вращение?
Предскажи

Ты включаешь колёса по очереди: сначала левое, потом правое. Заметно ли, что они трогаются не одновременно? Почему?

Подсказка: Колёса ведут себя по-разному

Сравни команды для левого и правого мотора строка за строкой: для каждого нужны настройка, направление, сила и остановка.

Должно получиться

Оба колеса крутятся вперёд одну секунду и останавливаются. С большим speed колёса крутятся быстрее, прогноз записан.

Как это устроено: Почему 0–255, а не километры в час

Число в analogWrite — это не скорость, а доля времени, когда мотор включён. При 255 он включён всё время, при 100 — примерно 40 % времени. Настоящая скорость зависит ещё от батареи и пола. Поэтому скорость подбирают опытом.

Требование 2. Оба колеса крутятся вперёд ровно одну секунду со скоростью из одной именованной переменной speed и останавливаются. Правый мотор подключён к контактам 4 (направление) и 5 (скорость). Начни со своей программы для левого мотора и сохрани её как L21_Both_Motors.

Исследование: с какого числа колесо трогается. На подставке ставь speed = 20, 40, 60, 80… и запиши для каждого колеса, при каком наименьшем числе оно начинает уверенно крутиться.

speedЛевое крутится?Правое крутится?
20
40
60
Предскажи

Будут ли эти числа одинаковыми у двух колёс? А у тебя и у соседней команды?

Подсказка: Колесо гудит, но не крутится

Мотору не хватает силы сдвинуть редуктор. Такое число — ещё «мёртвая зона».

Должно получиться

Оба колеса крутятся одну секунду и останавливаются. В журнале — наименьшая скорость трогания для каждого колеса и вывод, какие числа speed брать нельзя.

4

Найди ошибку остановки

10 мин
Найди ошибку · Робот не останавливается

Соседи перенесли команды движения в loop() и убрали остановку:

void loop() {
  analogWrite(LEFT_SPEED_PIN, speed);
  analogWrite(RIGHT_SPEED_PIN, speed);
  delay(1000);
}

Они ждали, что робот проедет одну секунду. Что будет на самом деле и почему? Как исправить?

Должно получиться

Ты можешь объяснить: delay только ждёт, моторы сами не выключаются, а loop() повторяет команды снова и снова.

Найди ошибку · Робот почти не останавливается

Соседи перенесли движение в loop() и добавили остановку:

void loop() {
  analogWrite(LEFT_SPEED_PIN, speed);
  analogWrite(RIGHT_SPEED_PIN, speed);
  delay(1000);
  analogWrite(LEFT_SPEED_PIN, 0);
  analogWrite(RIGHT_SPEED_PIN, 0);
}

Они ждали: секунду едет, потом стоит. На подставке колёса крутятся почти без остановки. Почему?

  1. Запиши ответ в журнал.
  2. Предложи два разных исправления и запиши их кодом: одно — без loop(), второе — оставив движение в loop().
Подсказка: Второе исправление

Можно ли после остановки «застрять» на месте, чтобы loop() больше не повторялся? Вспомни защиту из урока 1.1… или пустой бесконечный цикл while (true) { }.

Должно получиться

Ты можешь объяснить, почему остановка длится мгновение, и в журнале два исправления.

Найди ошибку · Пустой loop(), а робот едет

У соседей loop() пустой, а движение — в setup():

void forward(int ms) {
  drive(FORWARD, speed, FORWARD, speed);
  delay(ms);
}

void setup() {
  // … настройка контактов
  forward(1000);
}

void loop() {
}

Робот должен был проехать одну секунду, а едет, пока его не выключат. Почему, если loop() пустой? Запиши ответ в журнал.

Требование. Перепиши программу так, чтобы движение осталось в loop(), но робот проехал ровно одну секунду и больше не трогался. while (true) использовать нельзя.

  1. Проверь на подставке: колёса крутятся одну секунду и стоят, пока не нажмёшь Reset.
  2. Объясни в журнале, как твоя программа «помнит», что движение уже было.
Подсказка: Идея

Нужна переменная, которая хранит «уже ехали» — bool. Её проверяют в начале loop().

Должно получиться

Программа выполняет требование, объяснение записано.

2
Занятие 2 · 45 мин
Функции движения
5

Оформи движения функциями

15 мин

Писать каждый раз по четыре строки неудобно. Соберём их в функции: forward(), backward(), stopMotors(). Внутри них — знакомые команды.

  1. Создай скетч L21_Moves и набери программу.
Функции движенияL21_Moves.ino.ino
const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH; int speed = 100; void drive(int leftDir, int leftSpeed, int rightDir, int rightSpeed) {  digitalWrite(LEFT_DIR_PIN, leftDir);  digitalWrite(RIGHT_DIR_PIN, rightDir);  analogWrite(LEFT_SPEED_PIN, leftSpeed);  analogWrite(RIGHT_SPEED_PIN, rightSpeed);} void forward(int ms) {  drive(FORWARD, speed, FORWARD, speed);  delay(ms);} void backward(int ms) {  drive(BACKWARD, speed, BACKWARD, speed);  delay(ms);} void stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void setup() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  delay(2000); // время убрать руки от робота   forward(1000);  stopMotors();  delay(500);  backward(1000);  stopMotors();} void loop() {}
  1. Найди, где функции описаны и где они вызываются. Покажи напарнику.
Как это устроено: Как устроена функция с параметром

void forward(int ms) — функция с именем forward и параметром ms. Когда пишем forward(1000), внутри функции ms равно 1000. Так одна функция умеет ехать любое время.

drive(…) — вспомогательная функция: она сразу задаёт направление и скорость обоих колёс. Ей пользуются остальные функции.

Должно получиться

Программа проверяется без ошибок. Ты можешь показать описание и вызов forward.

Писать каждый раз по четыре строки неудобно. Соберём их в функции: forward(), backward(), stopMotors(). Функции drive и forward в шаблоне — образец.

  1. Создай скетч L21_Moves по шаблону. Напиши backward, stopMotors и движение в setup() сам.
Шаблон: функции движенияL21_Moves_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях.// Функции drive и forward ниже — образец. const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH;int speed = 100; // ===== Твоя часть: напиши сам ===== void backward(int ms) {  // Оба колеса крутятся назад со скоростью speed ms миллисекунд.} void stopMotors() {  // Оба мотора стоят.} void setup() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  delay(2000); // время убрать руки от робота   // Вперёд 1 секунду, остановка, пауза полсекунды, назад 1 секунду, остановка.} // ===== Образец — не меняй ===== void drive(int leftDir, int leftSpeed, int rightDir, int rightSpeed) {  digitalWrite(LEFT_DIR_PIN, leftDir);  digitalWrite(RIGHT_DIR_PIN, rightDir);  analogWrite(LEFT_SPEED_PIN, leftSpeed);  analogWrite(RIGHT_SPEED_PIN, rightSpeed);} void forward(int ms) {  drive(FORWARD, speed, FORWARD, speed);  delay(ms);} void loop() {}
  1. Найди, где функции описаны и где они вызываются. Покажи напарнику.
Подсказка: Функция назад

Чем «назад» отличается от «вперёд»? В программе уже есть константа для этого направления.

Подсказка: Как вызвать функцию

Вызов — имя функции и значение параметра в скобках, в конце ;.

Как это устроено: Как устроена функция с параметром

void forward(int ms) — функция с именем forward и параметром ms. Когда пишем forward(1000), внутри функции ms равно 1000. Так одна функция умеет ехать любое время.

Должно получиться

Программа проверяется без ошибок. Ты можешь показать описание и вызов backward.

Требование 3. Программа L21_Moves построена из функций:

  • drive(leftDir, leftSpeed, rightDir, rightSpeed) — единственное место, где задаются направление и скорость колёс;
  • forward(ms) и backward(ms) — движение на заданное время, stopMotors() — остановка;
  • направление «назад» не записано числом, а получено из FORWARD: на другом комплекте FORWARD может быть другим;
  • после включения есть 2 секунды, чтобы убрать руки;
  • в setup(): вперёд 1 секунду, стоп, пауза полсекунды, назад 1 секунду, стоп.
Подсказка: Идея (1 из 3)

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

Подсказка: План (2 из 3)
  1. drive — четыре строки из своей программы, но с параметрами вместо чисел.
  2. forward(ms) — drive вперёд и delay(ms).
  3. backward(ms) — то же назад. stopMotors() — скорость 0.
Подсказка: Фрагмент кода (3 из 3)

const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH; — прочитай как «если FORWARD равен HIGH, то LOW, иначе HIGH».

Должно получиться

Программа выполняет требование 3 и проверяется без ошибок.

6

Первый заезд по полу

15 мин
Безопасность

Освободи на полу или столе место не меньше метра вперёд и назад. Держи руку рядом с выключателем.

  1. Загрузи программу на подставке и проверь: вперёд, пауза, назад, стоп.
  2. Поставь робота на пол, включи питание моторов и нажми Reset.
  3. Отметь на полу мелом или скотчем точку старта и точку, где робот остановился.
Должно получиться

Робот проезжает вперёд, останавливается и возвращается примерно на место старта.

Если не получилось
Что видишьЧто сделать
Робот едет не прямоМоторы не одинаковые — это нормально. Запиши, куда уводит.
Робот вернулся не на стартВперёд и назад колёса крутятся чуть по-разному. Запиши разницу.
Робот поехал сразу после загрузкиТак и есть: программа стартует сама. Поэтому в setup() есть пауза 2 секунды.
  1. Загрузи программу на подставке и проверь: вперёд, пауза, назад, стоп.
  2. Поставь робота на пол, отметь старт скотчем, включи питание моторов и нажми Reset.
  3. Повтори три раза. Каждый раз отметь, где робот остановился, и измерь линейкой, на сколько сантиметров он ушёл от старта вперёд-назад и вбок.
ЗаездВперёд или назад, смВбок, смКуда уводит
1
2
3
  1. Одинаково ли робот ошибается в трёх заездах? Запиши вывод.
Должно получиться

Таблица из трёх заездов и вывод: куда и насколько уводит твоего робота.

Если не получилось
Что видишьЧто сделать
Робот едет не прямоМоторы не одинаковые — это нормально. Запиши, куда уводит.
Робот поехал сразу после загрузкиТак и есть: программа стартует сама. Поэтому в setup() есть пауза 2 секунды.

Узнай, насколько прямо едет твой робот, и попробуй это исправить одним изменением.

  1. Проверь программу на подставке, потом поставь робота на пол у начала метровой полосы скотча. Проедь вперёд 2 секунды. Измерь, на сколько сантиметров нос ушёл вбок от полосы. Повтори три раза.
  2. Предложи одно изменение, которое уменьшит увод: например, разные скорости левого и правого колеса. Запиши, почему ты ожидаешь улучшения.
  3. Сделай изменение и снова три заезда. Стало лучше? На сколько?
Увод 1, смУвод 2, смУвод 3, см
До
После
Подсказка: Колёса разные

Если робот уходит вправо, какое колесо крутится быстрее?

Должно получиться

Две серии по три заезда, одно изменение с обоснованием и вывод по числам.

7

Измени программу

10 мин
  1. Сделай так, чтобы робот проехал вперёд в два раза дальше, а назад — как раньше.
  2. Сделай «челнок»: вперёд — назад три раза подряд с паузами.
Проверь себя
  1. Сделай так, чтобы робот проехал вперёд в два раза дальше, а назад — как раньше.
  2. Сделай «челнок» — вперёд, стоп, назад, стоп три раза подряд, — написав вызовы forward, stopMotors, backward только один раз. Нужен цикл for из урока 1.1.
Предскажи

Вернётся ли робот после трёх челноков точно на старт? Запиши прогноз, потом отметь старт и финиш на полу.

Подсказка: Как устроен for

for (int i = 0; i < 3; i++) { … } повторяет команды в скобках три раза.

Должно получиться

Робот выполняет оба задания. В журнале — прогноз и насколько робот ушёл от старта после трёх челноков.

Проверь себя

Требование 4. Функция shuttle(times, ms) делает «челнок» times раз: вперёд ms миллисекунд, стоп, назад, стоп. Вызовы движений в ней написаны один раз.

Исследование: сколько проезжает робот.

  1. Три раза запусти forward(1000) при speed = 100 и измерь путь линейкой в миллиметрах. Повтори при speed = 200.
  2. Посчитай, сколько миллиметров в секунду проезжает робот при каждой скорости. Во сколько раз отличаются результаты? Вдвое ли, как отличаются числа speed?
  3. Подбери время backward так, чтобы после одного челнока робот вставал не дальше 2 см от старта. Запиши, почему вперёд и назад время получилось разным.
speedПуть 1, ммПуть 2, ммПуть 3, мммм за секунду
100
200
Подсказка: Пути разные при одной программе

Это нормально: колёса проскальзывают, батарея садится. Поэтому меряем три раза и берём среднее.

Должно получиться

shuttle работает. В журнале — таблица путей, скорость в мм/с для двух speed, вывод про связь числа speed и настоящей скорости и подобранное время возврата.

Проверь себя
Основное · Вперёд, стоп, назад

Робот проезжает вперёд 1 секунду, останавливается и возвращается назад.

Средний уровень · Челнок без копирования

Сделай «челнок» из трёх повторов, написав вызовы forward, stopMotors, backward только один раз. Подсказка: цикл for из урока 1.1.

Продвинутый уровень · Возврат на старт

Измерь, сколько миллиметров робот проезжает за секунду, и подбери время назад так, чтобы после челнока он вставал не дальше 2 см от старта. Запиши, почему время вперёд и назад разное.

Проверь себя

Выберите ответы для подготовки. Они не сохраняются и не оцениваются на сайте. Пройдите проверку знаний в программе курса или обсудите ответы с преподавателем.

● Основное

1.Что задаёт число в команде analogWrite(LEFT_SPEED_PIN, 100)?
2.Как сделать, чтобы левое колесо крутилось назад?
3.Что сделает робот?
forward(1000);delay(500);
4.Зачем описывать движения функциями forward(), backward(), stopMotors()?
5.Почему в setup() перед движением стоит delay(2000)?

★ Средний уровень

1.Нужно повторить «вперёд — стоп — назад» три раза, написав вызовы функций только один раз. Что подойдёт?
2.Скорость уменьшили со 200 до 100, а время езды вперёд осталось 1 секунда. Что изменится?
3.В программе забыли остановить правый мотор. Что сделает робот после секунды движения?
4.Вызвали forward(1000), а сразу за ним — backward(1000) без stopMotors() между ними. Что получится?
5.После трёх челноков робот оказался в 6 см от старта, а после одного — в 2 см. Почему ошибка растёт?

★★ Продвинутый уровень

1.Робот едет «прямо», но плавно уходит вправо. Что проверить первым?
2.При speed = 30 колесо гудит, но не крутится. Что это значит для программы?
3.Почему направление «назад» получают из FORWARD, а не пишут числом?
const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH;
4.При speed = 100 робот за 1 секунду проехал 180, 200 и 190 мм. Какую скорость записать в журнал?
5.В чём ошибка функции?
void shuttle(int times, int ms) {  for (int i = 0; i < times; i++) {    forward(ms);    backward(ms);  }  stopMotors();}

Отвечай на вопросы своего уровня. Нужно верных ответов: Начальный — 4 из 5; Средний — 4 из 5; Продвинутый — 4 из 5. Ответы проверит преподаватель или программа курса.

Итог

Робот ездит по твоей программе. Главное: analogWrite включает мотор, и он крутится, пока другая команда его не остановит. Функции делают программу короче и понятнее. В следующем уроке робот научится поворачивать.

Как подтвердить результат

Для каждого опыта сохраняй условия, версию программы, наблюдение и вывод. Сравнивая попытки, меняй одну причину за раз; неудачные попытки тоже остаются в журнале. Отметка результата относится к уже выполненным действиям, повторять их ради отметки не нужно. Если результат не получен, запиши расхождение и следующую проверяемую гипотезу. Модель, измерения настоящего робота и объяснение — разные виды доказательств.

Словарь урока

ШИМЧастое включение и выключение питания мотора. Число от 0 до 255 задаёт, какую долю времени мотор включён.
направлениеСостояние контакта направления: одно значение крутит колесо вперёд, другое — назад.
константаЧисло с именем, которое не меняется во время работы программы, например номер контакта.
функцияИменованный блок команд. Его можно вызвать много раз, написав имя и скобки.
параметрЧисло, которое передают функции в скобках, например время движения.