Введение в программирование LEGO-роботов на языке NXT-G

Циклы

Показывать лекцию целиком

При написании программ часто возникает необходимость в циклическом повторении группы команд. Для этого используется языковая конструкция цикл, которой в NXT-G соответствует блок Loop.

(рис 4.1) Блок Loop в меню Flow полной палитры и пример его использования

Внутрь цикла помещаются блоки, которые нужно выполнить многократно. Заметим, что следует с осторожностью (точнее, с пониманием) размещать в цикле блоки, которые сами в некотором роде обладают цикличностью, например Move, Sound и некоторые другие.

Программируя цикл, мы должны заранее знать в каком случае он прекратит свою работу. Завершение цикла (выход из цикла) может происходить по разным причинам. В NXT-G возможны следующие способы выхода из цикла, доступные в поле Control:

  • Forever - бесконечно (по умолчанию);
  • Sensor - по срабатыванию датчика;
  • Time - через определённое время;
  • Count - после выполнения цикла заданного количества раз;
  • Logic - при выполнении некоторого логического условия, заданного программистом.
  • (рис 4.2) Выбор варианта выхода из цикла

    В процессе изучения языка NXT-G мы постепенно освоим все эти способы. Начнём с бесконечного цикла.

    Простейшие виды циклов

    Задание 4.1. Подготовьте робот с датчиком цвета в передней части; датчик должен быть направлен вниз и находиться на расстоянии около 1 см от стола. Расположите робот перед чёрным полем (или чёрной линией) на расстоянии от неё около 20 см.

    Задание 4.2. Движение до линии. Используя датчик цвета в режиме измерения освещённости, напишите программу, позволяющую роботу доехать до чёрной полосы и остановиться (см. задание 3.3).

    Задание 4.3. Движение до линии и обратно. Измените программу из задания 4.2 так, чтобы после достижения чёрной линии робот отъезжал на белое поле.

    Задание 4.4. Бесконечное циклическое движение до линии и обратно. Измените программу из задания 4.3 так, чтобы робот выполнял движение до линии и обратно бесконечное количество раз. Для этого заключите предыдущую программу в бесконечный (forever) цикл.

    Задание 4.5. Циклическое движение до линии и обратно по счётчику. Измените программу из задания 4.4 так, чтобы робот выполнял движение до линии и обратно три раза. Для этого измените настройки цикла следующим образом:

    (рис 4.3) Настройки цикла со счётчиком

    Движение робота по линии

    Пример 4.1. Перейдём к классической задаче о движении робота вдоль линии. Полигон с такой линией имеется в каждом наборе.

    Разберёмся, может ли робот двигаться по линии, то есть так, чтобы сенсор всегда находился на чёрном поле. Для этого представим себе, что через некоторое время после старта сенсор "уехал" с чёрного поля и оказался на белом. Мы понимаем, что в этом случае робот должен немного подрулить чтобы вернуться обратно на чёрную линию. Но куда именно подрулить: налево или направо? Дело в том, что белый цвет по обе стороны от чёрной линии одинаков. Поэтому, попав в такую ситуацию, робот не сможет принять однозначное правильное решение.

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

    Что при этом изменится? Робот и человек по-разному воспринимают границу линии.

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

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

    (рис 4.4) "Чёрное" плюс "белое" пополам равно "серое"

    При движении робота уход влево (в чёрную область) приведёт к уменьшению показаний датчика, а уход вправо (в белую область) - к увеличению. Таким образом мы всегда сможем отличить левое от правого.

    Получим примерно такую программу для движения вдоль линии:

    (рис 4.5) Движение робота вдоль линии

    Обратите внимание на следующее: перед стартом робот ставится на поле так, чтобы датчик цвета "смотрел" на границу линии: чёрное - слева, белое - справа.

    Задание 4.6. Найдите отличия между предложенным решением и программой из задания 4.4.

    Задание 4.7. Запрограммируйте робот на движение вдоль чёрной линии, изменив код программы 4.4 и проверьте её работоспособность.

    Задание 4.8. Требуется запустить робот по той же линии, но в обратную сторону. Как это сделать не изменяя программу?

    Цикл со счётчиком. Передача данных между блоками

    Разберём следующий пример.

    Пример 4.2. Написать программу движения робота с ускорением.

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

  • Повтори 20 раз:
  • Вперёд
  • В настройках блока Move отметьте Coast (без торможения в конце выполнения блока). В поле Duration оставим значение 1 Rotation.

    Проверьте работу программы. Робот движется прямо с постоянной скоростью.

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

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

    В настройках блока Loop включите флажок Show Counter (Показать Счётчик). Обратите внимание на то, как изменился внешний вид цикла: появился разъём Loop Count

    (рис 4.6) Включение отображения счётчика цикла (слева) и доступ к нему (справа)

    Откройте концентратор данных блока Move, щёлкнув на кнопке в левой нижней части блока:

    (рис 4.7) Концентратор данных в свёрнутом состоянии

    В результате откроются входные (расположенные на левой стороне) и выходные (расположенные на правой стороне) разъёмы, к которым можно подключать шины данных от разъёмов других блоковЩёлкнув по тому же месту блока можно закрыть выдвижную панель. (Рис. 4.8). Таким способом можно передавать данные внутри программы на NXT-G без фактического использования переменных.

    (рис 4.8) Концентратор данных в раскрытом состоянии

    Соедините шиной разъём счётчика цикла и разъём Power (Мощность) блока Move (при наведении указателя мыши на разъём появляется соответствующая всплывающая подсказка). Чтобы сделать соединение, щёлкните левой кнопкой мыши на начало, проведите мышь в конец пути и щёлкните ещё раз; можно делать дополнительные щелчки по ходу траектории в местах её желаемых сгибов. В поле Duration укажите Unlimited (без ограничения длительности). Сверните концентратор данных щёлкните по выпадающей панели блока так, как будто хотите её свернуть. Все разъёмы, к которым не подходят шины, исчезнут. Этот трюк может заметно уменьшить площадь, занимаемую программой.

    В результате программа примет вид:

    (рис 4.9) Движение робота с ускорением

    Проверьте её работу.

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

    (рис 4.10) Движение робота с ускорением с задержкой времени выполнения для большей наглядности

    Пример 4.3. Вывод информации на экран блока NXT.

    Проверим, что на самом деле поступает из цикла на вход блока Move. Для этого разработаем упрощённую программу, в которой значение счётчика цикла выводится на экран блока NXT. Напомним, что для вывода используется блок Display из панели Common.

    Мы собираемся выводить на экран числовую информацию, поэтому её нужно вначале преобразовать к текстовому типу. Делается это при помощи блока Number to Text панели Advanced.

    (рис 4.11) Доступ к блоку Number to Text панели Advanced

    Получаем следующую схему программы:

  • в настройках блока Loop значение счётчика устанавливаем равное 10;
  • значение счётчика цикла передаём на преобразователь "Число → Текст";
  • полученный текст подаём на вход блока Display;
  • делаем задержку, чтобы успеть рассмотреть значение на экране;
  • после цикла ставим задержку до нажатия на кнопку Start, чтобы рассмотреть последнее выведенное на экран значение.
  • Пример программы приведен на Рис. 4.12.

    Обратите внимание на то, что шины разных данных окрашены по-разному. Всего в NXT-G используются три типа данных, каждому из них соответствует своя окраска:

  • числовой тип данных - жёлтый цвет;
  • текстовый тип данных - красный цвет;
  • логический тип данных - зелёный цвет.
  • (рис 4.12) Вывод значений счётчика на экран

    На Рис. 4.13 приведены настройки последнего блока:

    (рис 4.13) Настройки блока Wait

    Цикл с выходом по значению сенсора

    В NXT-G есть вариант использования цикла, в котором выход происходит в соответствии с определённым значением какого-либо сенсора. Настройка такого цикла полностью аналогична настройке блока Wait, с той лишь разницей, что в параметрах цикла присутствует флажок Show Counter. Пустой цикл с выходом по значению сенсора аналогичен соответствующему блоку Wait. Но в теле цикла мы можем разместить блоки, которые должны повторяться многократно до срабатывания сенсора.

    Пример 4.4. Превратить программу на Рис. 4.12 в простейший секундомер. Для этого тоже нужно отсчитывать время, но остановка должна произойти после нажатия на кнопку. Решение см. на Рис. 4.14).

    (рис 4.14) Простейший секундомер с использованием цикла с выходом по значению сенсора

    Задание 4.9. Напишите программу, по которой робот, используя ультразвуковой датчик, должен доехать до стены и остановиться на расстоянии 30 см от неё. Текущее расстояние до стены должно выводиться на экран во время движения.

    Цикл с выходом по условию

    Иногда удобно использовать цикл, выход из которого происходит при выполнении некоторого логического условия. Это аналог циклов While и Repeat-Until в языке программирования Паскаль. Настройка цикла производится обычным образом:

    (рис 4.15) Настройки цикла с выходом по логическому условию

    Здесь разъём №1 (Loop Condition) появляется, если в поле №2 (Control) выбрать Logic. На этот порт цикла нужно подать провод с логическим значением (зелёный).

    Поле №3 (Until) позволяет определить условие выхода из цикла: либо когда условие, поданное на разъём, станет истиной (True), либо когда оно станет ложью (False).

    Пример 4.5. Моделирование ожидания в n секунд при помощи таймера на одну секунду.

    Этот не вполне содержательный пример приведён здесь исключительно для знакомства с циклом рассматриваемого вида. (рис 4.16) Моделирование ожидания в n секунд при помощи таймера на одну секунду

    Здесь в цикле, который настроен на выход по условию, выполняются следующие действия:

  • отсчитывается одна секунда при помощи соответствующего блока;
  • номер итерации цикла, поступающий из порта Counter, подаётся на блок сравнения Compare из меню Data (Данные) полной палитры (Рис. 4.17);
  • там он сравнивается с числом n, и результат этого сравнения по зелёному проводу передаётся на второй разъём цикла;
  • если выполняется заданное в блоке сравнения условие, то цикл прекращает работу и мы слышим голос из динамика.
  • (рис 4.17) Блок Compare в полной палитре

    В блоке Compare доступны следующие логические операции:

  • Less than - "меньше, чем";
  • Greater than - "больше, чем";
  • Equal - "равно".
  • Данные в поля блока Compare могут поступать как по внешним разъёмам, так и путём ввода в соответствующие поля. Так, в примере 4.5 данные в поле A поступают с разъёма счётчика цикла (в этом случае ввод в поле не доступен), а в поле B вводятся пользователем.

    (рис 4.18) Настройки блока Compare в примере 4.5 (здесь n = 10):

    Задание 4.10. Изучите код программы из примера 4.5. Составьте программу и проверьте её работу для разных значений n.

    Задание 4.11. Напишите программу, которая после запуска ждёт нажатия на оранжевую кнопку NXT, после чего что-нибудь говорит и завершается. Для обработки нажатия на оранжевую кнопку воспользуйтесь программным блоком NXT Buttons из меню Sensors и циклом с выходом по условию. При выполнении этого задания использовать блок Wait запрещается! Напомним, что жёлтые блоки группы Sensors позволяют узнать текущие показания датчиков.

    Задание 4.12. Исправьте предыдущую программу так, чтобы её завершение происходило после n-го нажатия на оранжевую кнопку. Подсказка: используйте вложенные циклы.

    Вернуться к учебному плану