Курс «Основы робототехники. Продвинутый уровень». Занятие 3. Функции
Ранее была написана программа управления моторами робота и их скоростью с использованием приложения Arduino Bluetooth RC Car. Добавим еще одну возможность – робот едет, только пока нажата кнопка в приложении, а когда она отпущена – не едет (управление скоростью кнопками фар в программе тоже должно быть). Зайдите в настройки приложения и включите режим Continuous Stream – в этом случае приложение пересылает рассмотренные ранее символы (F, B, L, R) каждый 50 миллисекунд, пока кнопка нажата. В данном случае нет необходимости для управления скоростью выводить управление моторами после switch, поэтому можно сделать таким образом:
switch (command) { // выполняем команду в соответствии с принятым символом case 'F': // вперед analogWrite(In1, speed); analogWrite(In2, 0); analogWrite(In3, speed); analogWrite(In4, 0); break; case 'B': // назад analogWrite(In1, 0); analogWrite(In2, speed); analogWrite(In3, 0); analogWrite(In4, speed); break; case 'L': // влево analogWrite(In1, speed); analogWrite(In2, 0); analogWrite(In3, 0); analogWrite(In4, speed); break; case 'R': // вправо analogWrite(In1, 0); analogWrite(In2, speed); analogWrite(In3, speed); analogWrite(In4, 0); break; case 'S': // стоп analogWrite(In1, 0); analogWrite(In2, 0); analogWrite(In3, 0); analogWrite(In4, 0); break; case 'U': // прибавить скорость speed = speed + 10; break; case 'u': // прибавить скорость speed = speed + 10; break; case 'W': // уменьшить скорость speed = speed - 10; break; case 'w': // уменьшить скорость speed = speed - 10; break; default: // если принят какой-то другой сигнал - стоп analogWrite(In1, 0); analogWrite(In2, 0); analogWrite(In3, 0); analogWrite(In4, 0); break; } |
Программа получается достаточно большой и трудно редактируемой, а в случае, если надо добавить что-то еще (например, раздельное управление скоростью моторов, сделанное, чтобы откалибровать робота на езду прямо вперед) громоздкость кода будет расти в геометрической прогрессии. Чтобы избежать подобного, используют функции.
Функция – это часть кода, обычно находящаяся после основного цикла loop, вызываемая своим именем, например, forward(). Те команды, которыми мы уже научились пользоваться, тоже являются функциями например, analogWrite(In1, 0). Но эти функции прописаны не в скетче, а входят в состав Arduino IDE. Научимся создавать свои функции.
Функция прописывается типом возвращаемой переменной – int, float и т.д., если такая переменная есть (например, функция float arcsin(x) ). В случае, если функция только производит только действия, а не вычисления, ее тип – void (пустая)
Функция движения вперед будет выглядеть следующим образом:
void forward () { // тип функции, название функции (должно отличаться от стандартных), в скобках (…) ставятся аргументы – значения, передаваемые в функцию, если они есть analogWrite(In1, speed); analogWrite(In2, 0); analogWrite(In3, speed); analogWrite(In4, 0); } |
Аналогично можно перенести программы движений из switch в отдельные функции. В этом случае switch можно свести к следующему коду:
switch (command) { // выполняем команду в соответствии с принятым символом case 'F': // вперед forward(); break; case 'B': // назад backrward(); break; case 'L': // влево left(); break; case 'R': // вправо right(); break; case 'S': // стоп stop_motors(); break; case 'U': // прибавить скорость speed = speed + 10; break; case 'u': // прибавить скорость speed = speed + 10; break; case 'W': // уменьшить скорость speed = speed - 10; break; case 'w': // уменьшить скорость speed = speed - 10; break; default: // если принят какой-то другой сигнал - стоп stop_motors(); break; } |
Причем, если нужно будет что-то изменять в сделанных движениях, switch трогать уже не придется, а только менять соответствующие функции. Также легче добавлять дополнительные команды в switch, написав новые функции и просто сделав их вызов
Практическое занятие 1: напишите программу управления ровером приложением Arduino Bluetooth RC Car удержанием клавиш, плюс возможность регулировки скорости кнопками включения фар. Испытайте программу на реальном роботе-ровере
Практическое занятие 2.
Воспользуемся преимуществами работы с функциями, чтобы улучшить работу робота. Как можно были заметить, не всегда робот едет прямо при нажатии соответствующей клавиши. Это связано с тем, что характеристики установленных на ровера моторов немного отличаются и при одном и том же напряжении скорость вращения у них различна. Добавим в программу возможность калибровки скоростей вращения моторов, чтобы выровнять их:
float k_speed_right = 1; // коэффициент, на который умножается скорость правого мотора для калибровки двигателей (чтобы робот двигался в прямом направлении) float k_speed_left = 1; // коэффициент, на который умножается скорость левого мотора для калибровки двигателей (у одного из моторов коэффициент = 1, у другого меньше 1) … void forward () { float speed_left = k_speed_left * speed; float speed_right = k_speed_right * speed; analogWrite(In1, 0); analogWrite(In2, speed_left); analogWrite(In3, 0); analogWrite(In4, speed_right); } |
Добавьте калибровки скоростей в остальные функции движений (backward, left, right). Двигая робота по прямой и наблюдая направление и уровень отклонений, подберите коэффициенты (например, k_speed_right = 1, k_speed_left = 0,95) таким образом, чтобы робот ехал по прямой. Скорее всего, потребуется несколько экспериментов
По возможности сохраните написанную программу на флеш-карту, т.к. она может быть использована в соревнованиях по управляемому робофутболу и управляемым гонкам.
Домашнее задание
Используйте передачу данных в функции. Пример: функция forward (200), где число в скобках – время, которое робот едет, в мс. Функция выглядит следующим образом:
void forward (int time) { // в скобках – объявляется переменная (аргумент функции), куда передается значение (200 в примере). Работает только внутри этой функции (локальная переменная) float speed_left = k_speed_left * speed; float speed_right = k_speed_right * speed; analogWrite(In1, 0); analogWrite(In2, speed_left); analogWrite(In3, 0); analogWrite(In4, speed_right); delay (time); stop_motors (); } |
Модифицируйте остальные функции движений (backward, left, right) аналогичным таким образом. Напишите движения роботов по какой-либо траектории (квадрат, треугольник, круг, восьмерка, спираль, написание буквы или слова и т.п.), используя в блоке loop такие функции или подобные им. Опционально (если есть возможность): установите на робота карандаш, ручку или маркер, принесите на занятие большой лист бумаги и продемонстрируйте, как робот рисует в процессе езды какую-либо фигуру.