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

Ультразвук: видим груз

Робот измеряет расстояние звуком и останавливается перед грузом, не путая «нет эха» с «груз рядом».

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

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

Робот едет по линии и останавливается на заданном расстоянии от груза. Если эхо не вернулось, программа не принимает это за «груз рядом».

Ты научишься

  • Объяснить, как ультразвуковой датчик измеряет расстояние.
  • Вывести расстояние в монитор порта и проверить его линейкой.
  • Отличить отсутствие эха от маленького расстояния.
  • Остановить робота перед грузом по измерению, а не по времени.

Нужно знать

  • 3.2 П-регулятор: плавно и быстро

Понадобится

Ультразвуковой датчик расстоянияДатчик линии (аналоговый, Trema) × 2

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

Груз стоит в конце ответвления. Робот должен подъехать к ней и остановиться ровно так, чтобы захват мог её взять. Если ехать «по времени», робот то не доедет, то врежется. Сегодня он научится видеть груз ультразвуком — так же, как летучая мышь видит препятствия.

Разминка · вспомни
  1. Как робот останавливается на перекрёстке в программе из урока 4.1?
  2. Что делает break в цикле? (Если не помнишь — разберём сегодня.)
  3. Какие две команды нужны, чтобы робот ехал по линии с П-регулятором?
1
Занятие 1 · 45 мин
Измеряем расстояние
1

Как работает ультразвук

8 мин

Что должен делать робот. Курьеру нужно обнаружить предмет впереди, оценить расстояние до него и остановиться перед грузом. Датчики линии смотрят вниз и эту задачу не решают. Добавим ультразвуковой датчик: он поможет измерить расстояние, но не отличит груз от стены.

Что используем и как это работает. Передатчик датчика излучает короткую серию ультразвуковых колебаний, которые человек не слышит. Звук отражается от предмета, а приёмник улавливает эхо. Arduino запускает измерение импульсом на TRIG и измеряет длительность сигнала ECHO. Это электрический сигнал о времени измерения, а не сам звук. Путь звука двойной: до предмета и обратно. Поэтому расстояние равно скорости звука, умноженной на время и делённой на два.

Как связать измерение с действием. В учебной программе время в микросекундах делится на 58, чтобы получить приблизительные сантиметры: около 29 мкс на сантиметр в одну сторону и столько же обратно. Например, 580 мкс соответствует примерно 10 см. Целочисленный результат отбрасывает дробную часть; температура и отражающая поверхность тоже влияют на измерение. Сравниваем его с линейкой от передней поверхности датчика.

Если измерение не получилось. Наклонная поверхность может отразить звук в сторону, мягкая — поглотить, а слишком близкий или далёкий предмет — не дать пригодного эха. Поэтому «нет эха» означает «расстояние неизвестно», а не ноль и не свободный путь. В коде для этого есть отдельное значение −1. Программа принимает решение об остановке только после проверки измерения. Базовый пример при −1 продолжает движение — это ограничение учебного алгоритма, которое разберём в задании на потерю эха.

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

Предскажи

Звук пролетает 1 см примерно за 29 микросекунд. Предмет в 10 см. Сколько времени пройдёт до возвращения эха? (Не забудь: туда и обратно.)

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

Ты можешь объяснить: время эха → расстояние. До предмета в 10 см и обратно — около 580 мкс.

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

Предскажи

Звук пролетает 1 см примерно за 29 микросекунд. Сколько времени пройдёт до возвращения эха, если предмет в 10 см? А в 30 см?

  1. Запиши расчёт в журнал.
  2. Объясни, почему время нужно умножать на два.
Должно получиться

Расчёт для 10 и 30 см записан с объяснением про «туда и обратно».

Датчик посылает короткий щелчок ультразвука и слушает эхо. По времени полёта считают расстояние.

  1. Звук пролетает 1 см примерно за 29 мкс. Выведи формулу: расстояние в сантиметрах по времени эха в микросекундах.
  2. Скорость звука зависит от температуры. При 0 °C звук пролетает 1 см примерно за 30 мкс. Груз стоит в 50 см. Сколько покажет датчик зимой в холодном коридоре, если программа считает по 29 мкс? Важна ли эта ошибка для остановки в 5 см?
Должно получиться

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

2

Расстояние в мониторе порта

20 мин
  1. Посмотри номера контактов TRIG и ECHO на карточке у робота. Карточки нет — проследи провода от выводов TRIG и ECHO датчика до платы и прочитай номера у гнёзд. Запиши в журнал.
  2. Создай скетч L51_Distance и впиши номера контактов вместо -1.
Расстояние в мониторе портаL51_Distance.ino.ino
// Контакты ультразвукового датчика: впиши номера из таблицы проводки своего робота.const int TRIG_PIN = -1;const int ECHO_PIN = -1; // Расстояние в сантиметрах или -1, если эхо не вернулось.int readDistanceCm() {  digitalWrite(TRIG_PIN, LOW);  delayMicroseconds(2);  digitalWrite(TRIG_PIN, HIGH);  delayMicroseconds(10);  digitalWrite(TRIG_PIN, LOW);  unsigned long echoUs = pulseIn(ECHO_PIN, HIGH, 25000);  if (echoUs == 0) {    return -1;  }  return echoUs / 58;} void setupSonar() {  // Без контактов датчика программа дальше не пойдёт.  if (TRIG_PIN < 0 || ECHO_PIN < 0) {    while (true) {    }  }  pinMode(TRIG_PIN, OUTPUT);  pinMode(ECHO_PIN, INPUT);} void setup() {  Serial.begin(9600);  setupSonar();} void loop() {  int distance = readDistanceCm();  if (distance < 0) {    Serial.println("нет эха");  } else {    Serial.print(distance);    Serial.println(" см");  }  delay(200);}
  1. Загрузи, открой монитор порта. Ставь груз на 5, 10, 20 и 30 см по линейке. Запиши показания.
По линейкеПоказание датчика
5 см
10 см
20 см
30 см
Должно получиться

Показания датчика близки к линейке, разница — 1–2 см.

Как это устроено: Как работает readDistanceCm
  • На TRIG подаём короткий импульс 10 мкс — датчик щёлкает.
  • pulseIn(ECHO_PIN, HIGH, 25000) ждёт эхо не дольше 25 000 мкс и возвращает время в микросекундах. Если эхо не вернулось — возвращает 0.
  • Делим время на 58: это 29 мкс на сантиметр туда и 29 обратно.
  • Если эха нет, функция возвращает −1: «измерения нет».
Если не получилось
Что видишьЧто сделать
Программа ничего не печатаетВписаны ли номера TRIG и ECHO вместо −1?
Всегда «нет эха»Перепутаны TRIG и ECHO или датчик не получает питание
Числа прыгаютГруз должна стоять прямо напротив датчика
  1. Посмотри номера контактов TRIG и ECHO на карточке у робота. Карточки нет — проследи провода от выводов TRIG и ECHO датчика до платы и прочитай номера у гнёзд. Запиши в журнал.
  2. Создай скетч L51_Distance по шаблону и впиши номера контактов вместо -1.
  3. Напиши функцию readDistanceCm() сам. Печать в мониторе порта уже готова. Пока функция не написана, монитор печатает «нет эха».
КомандаЧто делает
digitalWrite(TRIG_PIN, HIGH); … LOWЩелчок: TRIG в HIGH на 10 мкс, перед этим коротко LOW
delayMicroseconds(мкс);Ждёт указанное число микросекунд
pulseIn(ECHO_PIN, HIGH, 25000)Время эха в микросекундах; 0 — эха нет за 25 000 мкс
Шаблон: расстояниеL51_Distance_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях. // Контакты ультразвукового датчика: впиши номера из таблицы проводки своего робота.const int TRIG_PIN = -1;const int ECHO_PIN = -1; // ===== Твоя часть: напиши сам ===== int readDistanceCm() {  // Щёлкнуть датчиком и вернуть расстояние до груза в сантиметрах.  // Если эхо не вернулось за 25 000 мкс, вернуть -1.  return -1;} // ===== Готовое: настройка датчика и печать — не меняй ===== void setupSonar() {  // Без контактов датчика программа дальше не пойдёт.  if (TRIG_PIN < 0 || ECHO_PIN < 0) {    while (true) {    }  }  pinMode(TRIG_PIN, OUTPUT);  pinMode(ECHO_PIN, INPUT);} void setup() {  Serial.begin(9600);  setupSonar();} void loop() {  int distance = readDistanceCm();  if (distance < 0) {    Serial.println("нет эха");  } else {    Serial.print(distance);    Serial.println(" см");  }  delay(200);}
Предскажи

Эхо вернулось через 1160 мкс. Сколько сантиметров до груза?

  1. Загрузи, открой монитор порта. Ставь груз на 5, 10, 20 и 30 см по линейке. Запиши показания.
По линейкеПоказание датчика
5 см
10 см
20 см
30 см
Подсказка: На что делить

Звук летит туда и обратно: 29 мкс на сантиметр в одну сторону и 29 — в другую. Сколько микросекунд приходится на один сантиметр расстояния до груза?

Подсказка: Время эха — большое число

Время может быть больше, чем помещается в int. Для него берут unsigned long.

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

Показания близки к линейке, разница — 1–2 см. Прогноз для 1160 мкс сошёлся.

Если не получилось
Что видишьЧто сделать
Программа ничего не печатаетВписаны ли номера TRIG и ECHO вместо −1?
Всегда «нет эха»Есть ли щелчок перед ожиданием эха? Не перепутаны ли TRIG и ECHO?
Числа прыгаютГруз должен стоять прямо напротив датчика
  1. Посмотри номера контактов TRIG и ECHO на карточке у робота. Карточки нет — проследи провода от выводов TRIG и ECHO датчика до платы и прочитай номера у гнёзд. Запиши в журнал.

Требование 1. Функция readDistanceCm() возвращает расстояние в сантиметрах или −1, если эха нет. Как работает датчик:

  • на TRIG подаётся импульс HIGH длиной 10 мкс (перед ним — короткий LOW);
  • датчик держит ECHO в HIGH столько микросекунд, сколько звук летел туда и обратно;
  • звук пролетает 1 см примерно за 29 мкс;
  • ждать эхо дольше 25 000 мкс не нужно: команда pulseIn(pin, HIGH, timeoutUs) вернёт 0.

Без номеров контактов программа не должна работать с датчиком: пусть она остановится. Напиши скетч L51_Distance, который печатает расстояние или «нет эха».

Приёмка. Таблица по линейке и ответы в журнале.

По линейкеПоказаниеОшибка, см
5 см
10 см
20 см
30 см
  1. Какое самое большое расстояние может измерить функция при ожидании 25 000 мкс?
  2. Растёт ли ошибка с расстоянием? Чем ты это объяснишь?
Подсказка: Идея (1 из 3)

Щёлкнуть, измерить длину импульса эха, перевести микросекунды в сантиметры.

Подсказка: План (2 из 3)
  1. TRIG: LOW 2 мкс, HIGH 10 мкс, LOW.
  2. pulseIn на ECHO с ожиданием 25 000 мкс.
  3. Ноль — нет эха. Иначе — время делить на 58.
Подсказка: Фрагмент кода (3 из 3)

unsigned long echoUs = pulseIn(ECHO_PIN, HIGH, 25000); — почему unsigned long, а не int?

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

Функция выполняет требование 1, таблица с ошибками заполнена, ответы записаны.

3

«Нет эха» — не «рядом»

15 мин
  1. Направь датчик в пустоту или на мягкую ткань под углом. Что печатает монитор?
  2. Поднеси ладонь вплотную к датчику, ближе 2 см. Что печатает?
Найди ошибку · Робот закрыл захват в пустоте

Соседи написали остановку так: if (readDistanceCm() <= 5) { stopMotors(); }. Робот иногда останавливается посреди пустой дороги. Почему? Что вернёт функция, если эха нет?

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

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

  1. Проверь датчик в трёх положениях и запиши, что печатает монитор:
ПоложениеЧто печатает
В пустоту
На мягкую ткань под углом
Ладонь ближе 2 см
Найди ошибку · Робот закрыл захват в пустоте

Соседи написали остановку так: if (readDistanceCm() <= 5) { stopMotors(); }. Робот иногда останавливается посреди пустой дороги. Почему? Что вернёт функция, если эха нет?

  1. Запиши правильное условие остановки.
Должно получиться

Таблица заполнена, ошибка соседей объяснена, правильное условие записано.

Найди границы, за которыми датчику нельзя верить.

  1. Поставь груз в 20 см и поворачивай его боком к датчику. С какого угла пропадает эхо?
  2. Придвигай груз к датчику. С какого расстояния показания перестают совпадать с линейкой?
  3. Направь датчик на мягкую ткань. Что печатает монитор?
Найди ошибку · Робот закрыл захват в пустоте

Соседи написали остановку так: if (readDistanceCm() <= 5) { stopMotors(); }. Робот иногда останавливается посреди пустой дороги. Почему?

  1. Запиши, какие из найденных границ опасны для доставки и как программа должна себя вести в каждом случае.
Должно получиться

В журнале — угол потери эха, ближняя граница, поведение на ткани и правила для программы.

2
Занятие 2 · 45 мин
Стоп перед грузом
4

Едем к грузу и останавливаемся

17 мин
  1. Создай скетч L51_Stop_At_Can. Перенеси измерения, kp, baseSpeed и контакты датчика.
Стоп перед грузомL51_Stop_At_Can.ino.ino
const int LEFT_SENSOR_PIN = A4;const int RIGHT_SENSOR_PIN = A5;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; // Измерения и настройки из журнала (уроки 3.1 и 3.2).const int LEFT_WHITE = 0;const int LEFT_BLACK = 0;const int RIGHT_WHITE = 0;const int RIGHT_BLACK = 0;float kp = 0.5;int baseSpeed = 100; int leftLevel = 100;int rightLevel = 100; int level(int value, int white, int black) {  long result = (long)(value - black) * 100 / (white - black);  return constrain(result, 0, 100);} void readSensors() {  leftLevel = level(analogRead(LEFT_SENSOR_PIN), LEFT_WHITE, LEFT_BLACK);  rightLevel = level(analogRead(RIGHT_SENSOR_PIN), RIGHT_WHITE, RIGHT_BLACK);} 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 stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void followLineStep() {  int error = leftLevel - rightLevel;  int correction = kp * error;  drive(FORWARD, constrain(baseSpeed + correction, 0, 255),        FORWARD, constrain(baseSpeed - correction, 0, 255));} void setupRobot() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  // Без измерений робот не поедет.  if (LEFT_WHITE == LEFT_BLACK || RIGHT_WHITE == RIGHT_BLACK) {    while (true) {    }  }  delay(2000);} // Контакты ультразвукового датчика: впиши номера из таблицы проводки своего робота.const int TRIG_PIN = -1;const int ECHO_PIN = -1; // Расстояние в сантиметрах или -1, если эхо не вернулось.int readDistanceCm() {  digitalWrite(TRIG_PIN, LOW);  delayMicroseconds(2);  digitalWrite(TRIG_PIN, HIGH);  delayMicroseconds(10);  digitalWrite(TRIG_PIN, LOW);  unsigned long echoUs = pulseIn(ECHO_PIN, HIGH, 25000);  if (echoUs == 0) {    return -1;  }  return echoUs / 58;} void setupSonar() {  // Без контактов датчика программа дальше не пойдёт.  if (TRIG_PIN < 0 || ECHO_PIN < 0) {    while (true) {    }  }  pinMode(TRIG_PIN, OUTPUT);  pinMode(ECHO_PIN, INPUT);} const int STOP_CM = 5; // на каком расстоянии от груза остановиться void setup() {  setupSonar();  setupRobot();   while (true) {    int distance = readDistanceCm();    if (distance > 0 && distance <= STOP_CM) {      break;    }    readSensors();    followLineStep();  }  stopMotors();} void loop() {}
  1. Поставь груз в конце линии. Запусти робота с другого конца.
Должно получиться

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

Как это устроено: Что делает break

break немедленно выходит из цикла while. После цикла программа выполняет stopMotors(). Так «стоп по расстоянию» оказывается в одном месте программы.

  1. Создай скетч L51_Stop_At_Can по шаблону. Перенеси измерения, kp, baseSpeed, контакты датчика и замени readDistanceCm своей функцией.
  2. Напиши движение в setup() сам: робот едет по линии и останавливается перед грузом. Помни шаг «Нет эха — не рядом».
Шаблон: стоп перед грузомL51_Stop_At_Can_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях.// Функцию readDistanceCm ниже замени своей из L51_Distance. const int LEFT_SENSOR_PIN = A4;const int RIGHT_SENSOR_PIN = A5;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; // Измерения и настройки из журнала (уроки 3.1 и 3.2).const int LEFT_WHITE = 0;const int LEFT_BLACK = 0;const int RIGHT_WHITE = 0;const int RIGHT_BLACK = 0;float kp = 0.5;int baseSpeed = 100;int leftLevel = 100;int rightLevel = 100; // Контакты ультразвукового датчика: впиши номера из таблицы проводки своего робота.const int TRIG_PIN = -1;const int ECHO_PIN = -1;const int STOP_CM = 5; // на каком расстоянии от груза остановиться // ===== Твоя часть: напиши сам ===== void setup() {  setupSonar();  setupRobot();   // Ехать по линии и остановиться, когда груз не дальше STOP_CM.  // «Нет эха» — не «груз рядом»: тогда робот едет дальше.} // ===== Готовое из уроков 3.2 и 5.1 — не меняй ===== int level(int value, int white, int black) {  long result = (long)(value - black) * 100 / (white - black);  return constrain(result, 0, 100);} void readSensors() {  leftLevel = level(analogRead(LEFT_SENSOR_PIN), LEFT_WHITE, LEFT_BLACK);  rightLevel = level(analogRead(RIGHT_SENSOR_PIN), RIGHT_WHITE, RIGHT_BLACK);} 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 stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void followLineStep() {  int error = leftLevel - rightLevel;  int correction = kp * error;  drive(FORWARD, constrain(baseSpeed + correction, 0, 255),        FORWARD, constrain(baseSpeed - correction, 0, 255));} void setupRobot() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  // Без измерений робот не поедет.  if (LEFT_WHITE == LEFT_BLACK || RIGHT_WHITE == RIGHT_BLACK) {    while (true) {    }  }  delay(2000);} // Расстояние в сантиметрах или -1, если эхо не вернулось.int readDistanceCm() {  digitalWrite(TRIG_PIN, LOW);  delayMicroseconds(2);  digitalWrite(TRIG_PIN, HIGH);  delayMicroseconds(10);  digitalWrite(TRIG_PIN, LOW);  unsigned long echoUs = pulseIn(ECHO_PIN, HIGH, 25000);  if (echoUs == 0) {    return -1;  }  return echoUs / 58;} void setupSonar() {  // Без контактов датчика программа дальше не пойдёт.  if (TRIG_PIN < 0 || ECHO_PIN < 0) {    while (true) {    }  }  pinMode(TRIG_PIN, OUTPUT);  pinMode(ECHO_PIN, INPUT);} void loop() {}
  1. Поставь груз в конце линии. Запусти робота с другого конца.
Подсказка: Ехать, пока…

Как в followLineToCrossing() урока 4.1: в цикле измерить расстояние, решить, пора ли останавливаться, иначе сделать шаг по линии.

Подсказка: Две проверки

Остановиться можно, только если измерение есть и груз близко. Какое число вернёт твоя функция, если эха нет?

Как это устроено: Как выйти из цикла

break немедленно выходит из цикла while. Программа продолжается после цикла.

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

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

Требование 2. Продолжи свою программу L42_Turn_At_Crossing и сохрани как L51_Stop_At_Can. Функция followLineToCan(stopCm) ведёт робота по линии и останавливает его, когда груз не дальше stopCm:

  • «нет эха» никогда не считается «груз рядом»;
  • после остановки моторы выключены;
  • функции линии и перекрёстков из прошлых уроков не меняются.

Приёмка. Груз в конце линии — робот останавливается, не касаясь груза. Груза нет — робот доезжает до конца линии, не останавливаясь посреди дороги (будь готов выключить питание).

Подсказка: Идея (1 из 2)

Это followLineToCrossing() из урока 4.1, только выход — по расстоянию.

Подсказка: Фрагмент кода (2 из 2)

if (distance > 0 && distance <= stopCm) { return; } — почему здесь return, а не break?

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

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

5

Точная остановка

15 мин
  1. Измерь линейкой, на каком расстоянии от груза остановился робот.
  2. Подбери STOP_CM и baseSpeed, чтобы робот останавливался там, где удобно захвату.
  3. Повтори три раза. Запиши в журнал STOP_CM и фактическое расстояние.
Подсказка: Робот останавливается дальше или ближе, чем STOP_CM

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

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

Робот три раза подряд останавливается на нужном расстоянии от груза.

Подбери STOP_CM и baseSpeed так, чтобы робот останавливался там, где удобно захвату. Меняй одно число за раз.

  1. Реши, на каком расстоянии от груза роботу нужно стоять. Если захват уже стоит, измерь у него; если нет — выбери расстояние, при котором робот не касается груза, и уточни его на уроке 5.2. Запиши.
  2. Запусти, измерь линейкой, где робот остановился. Запиши в таблицу и реши, что менять.
STOP_CMbaseSpeedГде остановился, смЧто поменять и почему
  1. Когда получилось, повтори три раза.
Подсказка: Робот останавливается ближе, чем STOP_CM

Робот не останавливается мгновенно: он ещё немного катится. Чем выше скорость, тем дальше.

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

Робот три раза подряд останавливается на нужном расстоянии. В журнале — таблица попыток с объяснением.

Добейся остановки на нужном расстоянии ±1 см три раза из трёх на своей рабочей скорости — той, на которой робот проходит линию.

  1. Измерь выбег: при baseSpeed 80, 120 и своей рабочей поставь STOP_CM = 15 и измерь, на сколько сантиметров робот прокатился после команды стоп.
  2. Выбери способ точной остановки и обоснуй его таблицей: поправить STOP_CM на выбег или ехать медленнее в последние сантиметры перед грузом.
  3. Проверь три раза.
baseSpeedSTOP_CMГде остановился, смВыбег, см
8015
12015
15
Подсказка: Медленно в конце

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

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

Таблица выбега, выбранный способ с обоснованием и три остановки ±1 см записаны.

6

Задания по уровням

13 мин
Основное · Стоп в 5 см

Остановиться в 5 см от груза, стоящего в конце линии.

Средний уровень · Повтор при отсутствии эха

Если эха нет, измерь ещё раз. Если эха нет пять раз подряд — останови робота: что-то не так с датчиком. Так робот не уедет с поля, потеряв груз.

Продвинутый уровень · Медиана из трёх

Делай три измерения и бери среднее по величине — медиану. Одно случайное неверное число тогда не испортит остановку. Сравни в мониторе порта сырые измерения и медиану.

Проверь себя

Проверь себя

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

● Основное

1.Как ультразвуковой датчик узнаёт расстояние?
2.readDistanceCm() вернула −1. Что это значит?
3.Какое условие остановки правильное?
4.Робот всегда останавливается на 3 см ближе, чем STOP_CM. Почему?
5.Три измерения: 12, 85, 13. Какая медиана?

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

1.Эха нет пять раз подряд. Что делает робот по заданию ★?
2.Измерение вернуло «нет эха». Что программа делает сначала?
3.Эхо вернулось через 1160 мкс. Сколько сантиметров до груза?
4.Почему время эха делят на 58, а не на 29?
5.На высокой скорости робот останавливается ближе к грузу, чем на низкой. Почему?

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

1.pulseIn ждёт эхо не дольше 25 000 мкс. Какое наибольшее расстояние может вернуть функция?
2.Почему для остановки берут медиану трёх измерений, а не среднее арифметическое?
3.Где ошибка, опасная для робота?
int readDistanceCm() {  digitalWrite(TRIG_PIN, HIGH);  delayMicroseconds(10);  digitalWrite(TRIG_PIN, LOW);  unsigned long echoUs = pulseIn(ECHO_PIN, HIGH, 25000);  return echoUs / 58;}
4.Выбег при рабочей скорости — 3 см. Роботу нужно стоять в 5 см от груза. Какой STOP_CM поставить?
5.Сравнение с линейкой: 5 → 6, 10 → 11, 20 → 21, 30 → 31 см. Что это значит?

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

Итог

Робот видит груз и останавливается перед ним по измерению. Осталось научиться его брать — в следующем уроке.

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

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

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

ультразвукЗвук такой высоты, что человек его не слышит. Датчик посылает щелчок и ждёт эхо.
эхоЗвук, отразившийся от предмета и вернувшийся к датчику.
pulseInКоманда, которая измеряет, сколько микросекунд длился сигнал на входе.
мксМикросекунда — миллионная доля секунды.
медианаСреднее по величине из нескольких чисел: из 4, 25 и 5 это 5.