Текст
                    УДК 007.52
ББК 32.816
М76
Момот М. В.
М76 Мобильные роботы на базе Arduino. — СПб.: БХВ-Петербург, 2017. — 288 с: ил.
ISBN 978-5-9775-3741-4
Руководство для начинающих конструкторов написано в форме практических про-
ектов по построению мобильных роботов. Для их реализации выбрана популярная плат-
форма Arduino и единая базовая четырехколесная конструкция. Сложность проектов
возрастает от простой, управляемой с пульта «машинки» до интеллектуального ро-
бота, самостоятельно играющего в кегельринг. Рассказано, как управлять моторами,
осуществлять сборку механики и электроники, программировать основные функции
и управлять роботом. Роботы смогут обходить препятствия, выбираться из запутанных
лабиринтов, искать кегли и определять их цвета, ориентироваться по электронному
компасу и даже балансировать на двух колесах.
Электронный архив, находящийся на сайте издательства, содержит детали робота для
печати на 3d-npnHTepe, векторные рисунки для резки лазером, листинги и дополнитель-
ные библиотеки
Для читателей, интересующихся электроникой и робототехникой
УДК 007.52
ББК 32.816
Группа подготовки издания:
Главный редактор Екатерина Кондукова
ЗаМ. главного редактора Евгений Рыбаков
Зав. редакцией Екатерина Капалыгина
Редактор Григорий Добин
Компьютерная верстка Людмилы Гауль
Корректор Зинаида Дмитриева
Оформление обложки Марины Дамбиевой
Подписано в печать 31.08.16.
Формат 70x1007i6. Печать офсетная. Усл. печ. л. 23,22.
Тираж 1500 экз. Заказ № 1543
«БХВ-Петербург», 191036, Санкт-Петербург, Гончарная ул., 20.
Первая Академическая типография «Наука»
199034, Санкт-Петербург, 9 линия, 12/28
ISBN 978-5-9775-3741 -4 © Момот М. В., 2017
© Оформление, издательство «БХВ-Петербург», 2017


ОГЛАВЛЕНИЕ Введение 11 Глава 1. Основные составные части робота 15 Информационно-измерительная система 16 Датчик касания 16 Датчик температуры 17 Датчик освещенности 17 Датчик препятствия 17 Ультразвуковой датчик расстояния 18 Оптический рефлекторный датчик расстояния 18 Детектор шума 19 Энкодер 20 Датчик движения 20 Датчик газа 21 Датчик влажности 21 Видеокамера 22 Система принятия решений 22 Микроконтроллер 23 Контроллер Arduino 23 Система связи 25 Инфракрасный приемник 25 Канал Bluetooth 26 Канал Wi-Fi 26 Дисплей 27
Оглавление Исполнительная система 27 Электрический двигатель постоянного тока 28 Сервомотор 29 Шаговый двигатель 30 Система энергоснабжения 30 Механика робота 30 Вспомогательные элементы 30 Резистор 31 Светодиод 31 Выключатель 31 Выводы 32 Глава 2. Провода и их соединения 33 Виды проводов 33 Одножильные 33 Многожильные 34 Способы соединений проводов 34 Скрутка 35 Соединение клеммами 35 Пайка и ее основы 36 Оборудование и материалы 36 Этапы пайки 37 Выбор паяльника 38 Уход за паяльником 39 Припои 39 Флюсы 39 Выводы 40 Глава 3. Электропитание 41 Закон Ома 41 Электрическая мощность 41 Характеристики элементов питания 42 Номинальное напряжение 1.42 Номинальный ток 42 Емкость 42 Форм-фактор 42 Типы элементов электрического питания 42 Солевые батареи 43 Алкалиновые батареи 43
Оглавление 5 Никель-металлогидридные аккумуляторы 43 Литий-ионные аккумуляторы 44 Стабилизация электропитания 44 Стабилизация напряжения 45 Стабилизация электрического тока 47 Выводы 47 Глава 4. Основы программирования Arduino 49 Компьютерная программа 49 Алгоритм 50 Среда разработки Arduino IDE 51 Установка Arduino IDE 51 Начало работы с Arduino IDE 52 Подключение контроллера Arduino к ПК 54 Мигаем светод иодом 56 Мониторинг работы программы 57 Переменные 58 Условные операторы 61 Оператор If... else 61 Оператор switch... case 65 Операторы циклов while и for 66 Функции 68 Элементы объектно-ориентированного программирования 69 Выводы 70 Глава 5. Ходовая часть 71 Типы ходовых частей 71 Ноги 71 Гусеницы 73 Колеса с дифференциалом 74 Колеса на моторах 74 Летающие роботы 75 Выбор двигателей 76 Драйверы двигателей 77 Широтно-импульсная модуляция 80 Вращение в обе стороны 80 Выводы 82
Оглавление Глава б. Сборка базовой модели 83 Минимальный комплект 83 Элементы питания 86 Двигатели 86 Драйвер двигателей 90 Соединение платы драйвера и двигателей 92 Проверка правильности подключения платы драйвера и двигателей 93 Подключение платы драйвера к контроллеру Arduino 95 Верх корпуса 96 Выключатель 99 Бокс для элементов питания 99 Подключение электропитания 101 Укладка проводов 103 Выводы 104 Глава 7. Схема управления движением 105 Переменные и функции управления моторами 105 Функции движений 106 Первая поездка 106 Алгоритм 106 Программа 107 „ Выводы 110 Глава 8. Дистанционное управление роботом 111 Способы дистанционного управления 111 Управление роботом по каналу инфракрасной связи 113 Схема подключения 114 Рекомендации по установке 114 Установка расширенной библиотеки 115 Получение кодов кнопок для используемого пульта 116 Программа 118 Управление роботом по каналу Bluetooth 125 Подбор элементной базы 125 Подключение к Arduino 127
Оглавление 7 Смена имени робота 128 Настройка смартфона 130 Устранение радиопомех 131 Программа 131 Выводы 136 Глава 9. Поворотная голова 137 Ультразвуковой дальномер HC-SR04 137 Схема подключения 138 Измерение расстояния 140 Управление сервомотором 141 Монтаж головы 143 Если что-то пошло не так 147 Выводы 148 Глава 10. Ходовые испытания — обход препятствий 149 Программа проверки и настройки основных функций робота 149 Константы и постоянные времени 154 Отладка программы 156 Выводы 162 Глава 11. Робот, находящий выход из лабиринта 163 Способ обхода лабиринта 165 Обход лабиринта без модернизации робота 166 Программа 168 Сравнение и выбор датчиков 171 Ультразвуковой датчик HC-SR04 171 Инфракрасный детектор препятствия 172 Инфракрасный датчик Sharp GP2Y0A21YK 173 Обоснование выбора датчика препятствия 173 Модернизация робота 174 Монтаж детекторов препятствия 174 Программа для робота с детекторами препятствия 178 Модернизируем программу 182 Выводы 184
8 Оглавление Глава 12. Робот, играющий в кегельринг 185 Простой кегельринг 186 Двухцветный кегельринг 188 Порядок обхода 188 Обнаружение черной линии 189 Фотодиод 189 Фоторезистор 190 Фототранзистор 191 Инфракрасный датчик отражения TCRT 5000 192 Обнаружение кегли 193 Определение цвета кегли 194 Коррекция направления движения 195 Модернизация робота 196 Установка датчиков 196 Схема соединений 198 Программа 201 Алгоритм поиска кегли 201 Алгоритм взаимодействия с кеглей 203 Выводы 212 Глава 13. Робот, держащий направление по электронному компасу 213 О компасе подробнее 213 Электронный компас 214 Подключение 214 Организация обмена данными 216 Модернизация робота 217 Получение данных от HMC5883L 218 Правильная установка магнитометра 222 Программа 223 Калибровка 229 Выводы 229 Глава 14. Балансирующий робот 231 Гироскоп 232 Акселерометр 232
Оглавление 9 Электронный гироскоп 235 Подключение гироскопа-акселерометра MPU-6050 235 Получение данных с MPU-6050 237 Шкала значений MPU-6050 240 Сборка балансирующего робота 241 Схема подключения 241 Конструкция 242 Программирование 246 Программа на показаниях гироскопа 246 Программа с фильтром Калмана 251 Программа с комплементарным фильтром 257 Комплементарный фильтр 257 Точная настройка 257 Выводы 262 Глава 15. Некоторые улучшения и прочая полезная информация 263 Модернизация детектора препятствий 263 Точные повороты 264 Самостоятельная сборка корпуса робота 272 Листинги 274 Интересные каналы YouTube 274 Приложение 1. Коммутационная плата Arduino UNO Sensor Shield V5.0 275 Приложение 2. Крепление серводвигателя и ультразвукового дальномера HC-SR04 на шасси робота 279 Приложение 3. Описание электронного архива 281 Предметный указатель 283
дерзай! книга + набор электронных компонентов н Основы программирования контроллера Arduino Конструирование базовой модели. Дистанционное управление с помощью IR-пульта или смартфона Android Базовые алгоритмы управления роботом «Обучение» робота движению по линии, выходу из лабиринта, игре в кегельринг и др.
ВВЕДЕНИЕ Здравствуйте, дорогие читатели! Впрочем, я не уверен, что правильно называть тех, кто читает эту книгу, читателями — скорее, они Конструкторы или Изобретатели. Ведь чтение книги без сопутствующей сборки и программирования роботов не столь интересно. Эту книгу я составлял как руководство для начинающих Конструкторов, то есть лю- дей, которым нравится конструировать. А за основу взял создание несложных робо- тов на весьма популярной в настоящее время платформе Arduino. Arduino же выбрал потому, что проекты, выполненные на ее основе, весьма просты и функциональны. Платформа открытая, а это значит, что изготавливать дополнительные модули для нее может любой человек или организация, то же относится и к разработке про- грамм. Итак, изучив книгу, вы научитесь программировать на платформе Arduino и обра- щаться с электронными и электрическими компонентами, из которых состоят ро- боты. Поймете принцип действия датчиков, при помощи которых роботы следят за внешним миром. Сможете делать своих оригинальных роботов и удаленно управ- лять ими. Книга разбита на главы. • Главы с первой по четвертую являются вводными — они дают основу, подго- тавливают к конструированию робота: ♦ первая глава посвящена составным частям, из которых может быть сделан робот; ♦ вторая глава учит выполнять электрические соединения; ♦ в третьей главе рассказано об источниках электрического питания, их стаби- лизации и выборе для робота подходящего источника питания; ♦ в четвертой главе даны основы программирования контроллеров Arduino, так что начинать программировать можно еще до установки модуля Arduino в тело робота.
12 Введение • Главы с пятой по десятую посвящены сборке базовой конструкции робота: ♦ пятая глава содержит обзор ходовых частей и учит основам управления дви- гателями; ♦ шестая глава описывает сборку ходовой части — здесь вы приобретете соответствующие практические навыки; ♦ седьмая глава дает основы управления роботом — в ней разрабатывается первая базовая программа, содержащая блоки управления движениями робота; ♦ восьмая глава посвящена способам дистанционного управления роботом со смартфона на ОС Android или с пульта дистанционного управления типа телевизионного; ♦ девятая глава дает знания и практические навыки по применению базового датчика — ультразвукового дальномера, расположенного на поворотной голове робота и помогающего роботу обходить препятствия; ♦ десятая глава научит настраивать робота и проводить отладку программ. • В главах с одиннадцатой по четырнадцатую содержатся проекты пяти разных роботов, построенных на основе базовой модели: ♦ глава одиннадцатая знакомит с различными детекторами препятствий и про- граммной логикой, которая позволяет роботу не заблудиться в запутанном лабиринте; ♦ в двенадцатой главе робот решает задачи поиска кегли в кегельринге и опре- деления ее цвета; ♦ в тринадцатой главе объясняется, как пользоваться электронным компасом и задействовать его для ориентирования робота в пространстве по сторонам света; ♦ четырнадцатая глава посвящена ориентированию робота в пространстве при помощи специальных электронных приборов: гироскопа и акселерометра. Используя их, двухколесные роботы с легкостью держат равновесие, а четы- рехколесные могут отслеживать свои координаты на основании расчетов по их показаниям. • Пятнадцатая глава посвящена улучшениям и модернизации — здесь модернизируются датчик препятствия и система поворотов робота, приведены варианты корпуса робота для самостоятельного изготовления его из плоских материалов (оргстекла или фанеры). Для того, чтобы роботы получили тот функционал, который описан в книге, вам в процессе ее чтения потребуется разобраться в работе некоторых датчиков: ультра- звукового датчика расстояния, детектора препятствия, датчика цвета (только чер- ный или белый). В книге также приведены примеры самостоятельного изготовления некоторых датчиков.
Введение 13 В электронном архиве, сопровождающем книгу, содержатся все программные моду- ли, которые приведены в книге, и даже некоторые не приведенные или приведенные не полностью. Кроме них, архив содержит файлы с рисунками корпуса робота, вы- полненные в векторном редакторе. По ним можно либо самостоятельно вырезать корпус из оргстекла, либо заказать подобную резку, например, при помощи лазерно- го резака. Колеса для робота можно также изготовить самостоятельно, напечатав их на ЗЭ-принтере, для этого в архиве есть файл с ЗБ-моделью колеса. Электронный архив Электронный архив с материалами к этой книге можно скачать с FTP-сервера издательства «БХВ-Петербург» по ссылке ftp://ftp.bhv.ru/9785977537414.zip или со страницы книги на сайте www.bhv.ru (см. приложение 3). Я уверен, что чтение книги и постройка роботов будет не только полезной вам с точ- ки зрения получения новых знаний и умений, но также станет увлекательным и ин- тересным занятием. С уважением, Михаил Момот
ГЛАВА 1 ОСНОВНЫЕ СОСТАВНЫЕ ЧАСТИ РОБОТА Что мы имеем в виду, когда произносим слово «робот»? В основном, подразумева- ется некое техническое творение, которое либо самостоятельно, либо посредством удаленного управления может совершать определенные действия. Слово «робот» впервые применил для обозначения искусственных людей чешский писатель Карел Чапек в своей пьесе «Россумские универсальные роботы». К. Чапек называл так искусственные создания, внешне не отличающиеся от обычных людей, но безгранично преданные человечеству и поэтому безмерно эксплуатируемые. Современные роботы, это, конечно, не искусственные люди, но довольно продви- нутые автоматические механизмы, способные на очень многое благодаря наличию у них развитой структуры компонентов, отвечающих за разнообразные действия. Внутренняя начинка роботов не сильно отличается от обычного персонального компьютера. Но, имея другие цели, роботы выглядят иначе. Любого робота можно условно разделить на следующие части: • информационно-измерительная система; • система принятия решений (система внутреннего управления); • система связи; • исполнительная система; • система энергоснабжения; • механика робота (скелет).
16 Глава 1 Информационно-измерительная система Информационно-измерительная система — это совокупность органов чувств робо- та. Она отвечает за восприятие роботом внешнего мира. Элементы информационно- измерительной системы называют датчиками или сенсорами. Самым простым из них является датчик касания, который срабатывает от замыкания контактов. Сюда также относятся дальномеры и датчики расстояния, датчики и измерители освещенности, датчики шума, различные магнитные датчики, а также системы машинного зрения, гирокомпасы, акселерометры, температурные датчики и многие другие. Далее мы рассмотрим основные электронные и электрические элементы робота и их схемати- ческие обозначения. Программа Fritzing При подготовке книги для рисования электрических схем использовалась программа Fritzing, специально разработанная для среды Arduino. Поэтому большинство схем, приве- денных в книге, нарисованы с использованием этой программы. Fritzing является програм- мой свободно распространяемой и может быть получена с одноименного сайта. Датчик касания Рассмотрим наиболее распространенные органы чувств робота более подробно. На рис. 1.1 изображены датчик касания и его принципиальная схема. Датчик реализо- ван в виде нефиксируемой кнопки с рычажком, при нажатии на который одна пара контактов замыкается, а другая размыкается. Рис. 1.1. Датчик касания
Основные составные части робота 17 Датчик температуры На рис. 1.2 показан датчик температуры — принцип его работы основан на измене- нии сопротивления при изменении температуры, что приводит к изменению выход- ного напряжения, которое и служит для замера температуры. VCC TEMP SENSORADJ GND Рис. 1.2. Датчик температуры Датчик освещенности На рис. 1.3 изображен пороговый датчик освещенности, который срабатывает по достижении освещенностью определенного значения. Пороговое значение срабаты- вания датчика можно регулировать. Основой датчика служит фоторезистор, сопро- тивление которого изменяется при изменении освещенности. Рис. 1.3. Датчик освещенности Датчик препятствия Датчик препятствия (рис. 1.4) состоит из инфракрасного светодиода, излучающего в невидимом человеку инфракрасном диапазоне, и фототранзистора. Светодиод све- тит на препятствие, фототранзистор реагирует на отраженный свет, величина тока фототранзистора зависит от уровня освещенности. За счет подстройки можно из- менять пороговый уровень срабатывания датчика и тем самым менять расстояние срабатывания. Недостатком датчика является реакция на сторонние источники ин- фракрасного света.
18 Глава I Рис. 1.4. Датчик препятствия Ультразвуковой датчик расстояния Более сложным, но и более точным, чем инфракрасный датчик препятствия, являет- ся ультразвуковой датчик расстояния (рис. 1.5). Он излучает ультразвуковую волну и принимает отраженный сигнал, расстояние определяется по времени распростра- нения сигнала до препятствия и обратно. При этом точность датчика составляет не- сколько миллиметров. Однако на определение расстояния требуется некоторое вре- мя, которое робот должен провести неподвижно. Дальномер1 HC-SR04 HEAD STUDIO Рис. 1.5. Ультразвуковой датчик расстояния Оптический рефлекторный датчик расстояния Интересным устройством является оптический рефлекторный датчик расстояния, иногда также называемый инфракрасным датчиком расстояния (рис. 1.6). В основе его работы лежит триангуляционный принцип измерений.
Основные составные части робота 19 Датчик состоит из передатчика, излучающего прямо вперед, и приемника, отстоя- щего от него на известном (базовом) расстоянии. Вместе с отражающим объектом они образуют прямоугольный треугольник. Чем дальше объект, тем больше угол в основании прямоугольника. Зная угол и базу, легко вычислить расстояние триго- нометрически. Следует заметить, что датчик имеет нелинейный выход — при изменении расстояния до объекта сигнал на аналоговом выходе датчика изменяется непропорционально, поэтому для расчета применяется специальная формула. ш ш lib* 1 Ш ИИ ^ш Vcc Vout чч GND Рис. 1.6. Оптический рефлекторный датчик расстояния Детектор шума На рис. 1.7 показан детектор шума на конденсаторном микрофоне, срабатывающий на заданный уровень звука. Порог его срабатывания можно плавно регулировать. Рис. 1.7. Детектор шума
20 Глава 1 Энкодер Энкодером называют датчик угла поворота — устройство, предназначенное для пре- образования угла поворота вращающегося вала в электрические сигналы, позволяю- щие определить величину этого угла. Энкодер, изображенный на рис. 1.8, представ- ляет собой модифицированный переменный резистор. R1 100kQ Рис. 1.8. Эн кодер Датчик движения Датчик движения (рис. 1.9) состоит из приемника, реагирующего на инфракрасный свет, и линзы Френеля, обеспечивающей большие углы обзора. Конструкция датчи- ка такова, что он не срабатывает на излучение от неподвижных объектов, но сраба- тывает, когда объект начинает двигаться. Рис. 1.9. Датчик движения с линзой Френеля
Основные составные части робота 21 Датчик газа Датчик газа (рис. 1.10) реагирует на увеличение концентрации углекислого и угар- ного газов. Его можно использовать при разработке пожарной сигнализации. Если в помещении увеличивается концентрация угарного газа, человек этого не почувству- ет, а датчик сработает и предупредит о грозящей опасности. Gas Sensor Breakout Board Рис. 1.10. Датчик угарного газа Датчик влажности Датчик влажности грунта основан на изменении электрического сопротивления почвы в зависимости от уровня ее влажности. Такой датчик можно с успехом при- менять в системах полива растений. Полив растений будет проходить тогда, когда влажность почвы уменьшится до определенного предела. Рис. 1.11. Датчик влажности
22 Глава 1 Видеокамера Информационно-измерительная система роботов может включать видеокамеру, ко- торая состоит из проецирующей линзы и фоточувствительной матрицы (рис. 1.12). Изображение проецируется на матрицу, каждый элемент матрицы генерирует сигнал, соответствующий цвету и освещенности определенной точки объекта. Полученная информация, закодированная числами (в случае цифрового сигнала), передается на обработку. Следует отметить, что контроллеры Arduino, используемые в про- стых проектах, не подходят для обработки видео и фото. Фотокадр размером 640 на 480 точек при 256 значениях освещенности (для черно-белого кадра) потребует 300 килобайт оперативной памяти, чего в большинстве контроллеров Arduino по- просту нет. Рис. 1.12. Видеокамера Система принятия решений Информация, полученная от датчиков, должна быть обработана и проанализирова- на — этим занимается система принятия решений (внутреннего управления). Она содержит правила поведения робота в зависимости от времени и информации, по- ступающей от других систем. Включение робота приводит к тому, что он начинает действовать согласно этим правилам. Под действием понимается управление своими механизмами, включение или отключение моторов, передача и получение информа- ции по системам связи. Правила поведения роботов содержатся в его памяти в машинных кодах. Но перед этим они создаются людьми сначала в виде алгоритмов, а затем в виде программы на
Основные составные части робота 23 языке программирования. Роботы сами не способны изменять правила своего по- ведения. Система принятия решений является «компьютером» робота и может быть реализо- вана на схожих с ним компонентах. Эту систему можно также назвать центральной нервной системой робота. Функции системы принятия решений в роботах выполняют микроконтроллеры. Микроконтроллер — это микросхема, включающая в себя несколько устройств: • процессор выполняет все логические и арифметические операции и управляет выполнением программы робота; • постоянная память (постоянное запоминающее устройство) выполняет роль «жесткого диска» робота, хранит программы и данные, не стирается при выклю- чении питания; • оперативная память (оперативное запоминающее устройство) является памятью с быстрым доступом, используется контроллером при работе для хранения про- грамм и данных; • аналого-цифровые преобразователи преобразуют уровни напряжения в числовую форму; • широтно-импульсные генераторы предназначены для генерации электрических импульсов с определенной частотой и шириной и служат для управления внеш- ними устройствами — например, скоростью вращения двигателя постоянного тока. Микроконтроллер Микроконтроллеры функционально схожи с современными компьютерами, но го- раздо слабее их (рис. 1.13). Частота работы микроконтроллера: 8-32 МГц, размер оперативной памяти: 1-16 Кбайт, емкость постоянной памяти: 1-32 Кбайт. Контроллер Arduino Проект, который существенно упростил разработку несложных роботов, зародился в Италии в 2005 году и, благодаря открытой документации, распространился по все- му миру. Его разработчики назвали свое устройство Arduino. Arduino — это не только плата, содержащая микроконтроллер, стабилизаторы пи- тания и удобно расположенные контактные площадки для подключения внешних устройств. В проект Arduino входит простая и оригинальная программная оболочка, позволяющая относительно легко создавать и модифицировать программы, а также огромное количество программных библиотек для подключения датчиков, моторов и других устройств.
24 Глава 1 ,'PCINT19'OC28'INT1) FD3 L" iPCINT20'XCK.70>PD4>: GNDC VCC r GNDL' VCC Г iPCINT6,XTAL1fT0SC1) PBti Г (PCINT7/XTAL2TOSC2) РБ7 С -J PC1 (ADC1 PCJNT9) П PCO iADC0'PCIN78) Л АЭС7 11 GND j ADC6 J A7CC jPBSiSCK/PCINTSi Рис. 1.13. Микроконтроллер ATmega328 RESET DCVRX RE3ET2 D1/TX AREF D? iOREF D3 PWM D4 АО D5 PWM A1 06 PWM a2 Arduino d? A3 UnO D8 icsp moss (Rev3) do pwm A5/SCI ICSP D10 PWM/SS D11 PWM'MOS! D12/M«SO D13/SCK Рис. 1.14. Плата контроллера Arduino UNO на основе микроконтроллера ATmega328P Фактически, Arduino — это электронный конструктор. На рис. 1.14 представлен контроллер Arduino UNO. Номерами 0-13 обозначены цифровые порты, А0-А5 — порты, которые могут анализировать уровень сигнала и преобразовывать его в чис- ловую форму. На плату может быть подано напряжение от 6 до 12 вольт, при этом стабилизаторы питания преобразуют его в требуемые уровни.
Основные составные части робота 25 Система связи Когда требуется скорректировать работу робота либо получить дополнительную ин- формацию о его состоянии, следует использовать системы связи. Система связи служит для организации взаимодействия робота с другими устрой- ствами и «хозяином». Вмешательство «хозяина» требуется, когда автономная (само- стоятельная) работа невозможна или нецелесообразна. Так, робот может попасть в условия, правила действия в которых не описаны в его программе, или условия тре- буют принятия решения человеком, или робот жестко запрограммирован так, что любые действия совершаются только после получения команды от «хозяина». Системы связи могут использовать следующие каналы: • проводные каналы, когда робот соединен с пультом управления проводами; • радиоканалы, когда информация передается радиоволнами; • инфракрасные каналы, когда информация передается световыми импульсами; • аудиоканалы, когда робот напрямую воспринимает речевые команды человека и сам может сообщить ему некоторую информацию; • визуальные каналы, когда сообщения выводятся на различные информационные мониторы робота. Инфракрасный приемник Управляющие команды можно посылать на инфракрасный (IR) приемник, уста- новленный на роботе (рис. 1.15). Это удобно, когда команд не много, и между вами и роботом нет преград. Так, например, можно управлять движением робота. в© ©©© ©о© 00© 00© ©0© IR1 оит VCC GND Рис. 1.15. IR-приемник на плате (слева); IR-пульт (в центре); схема выводов {справа)
26 Канал Bluetooth Глава 1 Удобный способ общения с роботом предоставляет канал Bluetooth. Существует мас- са программ для управления роботами посредством телефонов на операционной системе Android. Модули Bluetooth для роботов (рис. 1.16) также не являются ред- костью. В одной из практических глав мы рассмотрим этот вопрос подробнее. Bluetooth Mate Silver Рис. 1.16. Приемопередатчик Bluetooth Канал Wi-Fi Радиоканалы связи не ограничиваются только Bluetooth, существуют и широко применяются модули Wi-Fi (рис. 1.17), при помощи которых роботами можно управлять посредством бес- проводных компьютерных сетей. Роботы при этом становятся частью большой компьютер- ной системы. Рис. 1.17. Приемопередатчик Wi-Fi
Основные составные части робота 27 Дисплей К средствам связи можно также отнести и различные виды дисплеев для вывода ин- формации. Основная проблема подключения обычных дисплеев к Arduino заключа- ется в большом количестве задействованных портов ввода/вывода, но современные дисплеи (рис. 1.18), использующие 12С-шину, этой проблемы лишены. Рис. 1.18. Дисплей с управлением по шине I2C Исполнительная система Исполнительная система отвечает за все движения робота и определяет возможно- сти робота выполнять другие физические действия. К исполнительной системе отно- сятся манипуляторы, ходовая часть, устройства позиционирования рабочих элемен- тов. Основой большинства исполнительных механизмов являются электрические двигатели (рис. 1.19). Рис. 1.19. Электрические двигатели
28 Глава 1 Электрический двигатель постоянного тока Электрические двигатели различаются мощностью и количеством оборотов в мину- ту. Выбирать электрический двигатель нужно, исходя из конкретной задачи. Если мощность мала, применяют редукторные передачи, которые снижают количество оборотов на выходном валу, но увеличивают мощность. На рис. 1.20 изображен двигатель постоянного тока с установленным на нем редуктором с передаточным числом 48. Рис. 1.20. Двигатель постоянного тока с редуктором Редукторные передачи этого дви- гателя показаны на рис. 1.21. Вал двигателя вращается быстро, а колеса робота — в 48 раз мед- леннее, но в 48 раз мощнее. Это позволяет роботу преодолевать препятствия и двигаться в гору. Конечно, размер колеса также имеет значение. Рис. 1.21. Редуктор двигателя
Основные составные части робота 29 Сервомотор Другим распространенным видом привода для робота является сервомотор (рис. 1.22). Его отличие от двигателя постоянного тока с установленным редуктором состоит в том, что основная задача сервомотора — обеспечить определенный угол поворота вала, который задается управляющим сигналом. Сервомоторы применя- ются в манипуляторах, поворотных механизмах, при создании шагающих роботов, везде, где требуется точность позиционирования угла поворота. Рис. 1.22. Сервомотор Внутри сервомотора, как правило, установлен двигатель постоянного тока и понижа- ющий редуктор. Там же могут находиться схема управления и энкодер. На рис. 1.23 изображен разобранный сервомотор (сервопривод). Рис. 1.23. Сервомотор: двигатель постоянного тока {слева); энкодер (в центре); редуктор {справа)
30 Шаговый двигатель Глава 1 Еще одним распространенным видом приводов является шаговый двигатель (рис. 1.24). Он поворачивает свой вал небольшими дискретными значениями — «ша- гами». Шаговые двигатели широко используются в станках с числовым программ- ным управлением для организации точного движения обрабатывающего инстру- мента. Рис. 1.24. Шаговый двигатель: плата управления {слева); собственно шаговый двигатель (в центре); схема {справа) Система энергоснабжения Система энергоснабжения несложного робота основана на электричестве. В нее вхо- дят элементы питания, стабилизаторы питания, различные генераторы электроэнер- гии — например, солнечные батареи. Электропитанию роботов посвящена глава 3 книги. Механика робота Механика робота, ее скелет, представляет собой совокупность элементов конструк- ции, к которым крепятся и с которыми соединяются все рассмотренные ранее состав- ляющие. Конструкция колес, ног, корпуса робота определяет его внешний вид и во многом функциональность. Естественно, что для робота, выполняющего физические движения, механика не менее, а нередко и более сложна, чем электроника. В главе 6 мы рассмотрим ходовую часть робота. Вспомогательные элементы Кроме уже рассмотренных компонентов, в схемах могут встречаться простые эле- менты — например, резисторы, светодиоды и пр.
Основные составные части робота 31 Резистор _Л Л Л Л РеЗИСТОр (рИС. 1.25) Играет рОЛЬ ОГраНИЧИТеЛЯ 'Штшттй у у у ^тттттт тока и роль дополнительной нагрузки. Рис. 1.25. Резистор Светодиод Светодиод (рис. 1.26) служит для подсветки объектов и индикации. Рис. 1.26. Светодиод Выключатель Выключатель, или тумблер (рис. 1.27), служит для включения/выключения робота. Выключатели ставятся в цепь электропитания робота, разрывая соединение поло- жительного контакта с элементом питания. Рис. 1.27. Выключатель
32 Глава 1 Выводы В краткой форме мы рассмотрели здесь основные системы робота: информационно- измерительную, принятия решений, связи, исполнительную, энергоснабжения, а также механику робота и вспомогательные элементы. Особенности работы с ними будут раскрыты более подробно в процессе выполнения соответствующих проектов. Следующая же глава посвящена проводам робота и их соединению.
ГЛАВА 2 ПРОВОДА И ИХ СОЕДИНЕНИЯ Виды проводов Электрические элементы робота соединяются друг с другом посредством проводни- ков электрического тока. Если элементы расположены на специальной подложке — плате, то проводниками являются ее медные «дорожки». Если элементы разнесены, используют провода. Провода различают по типу металла, из которого они состоят, по толщине (сечению) и количеству жил. Для роботов используют медные провода. Медные провода являются основой соединений в бытовой электронике из-за малого сопротивления электрическому току, хорошей теплопроводности и гибкости, а так- же возможности качественной пайки. Одножильные Одножильные провода (рис. 2.1) могут применяться в соединениях, которые не будут подвергаться смещениям относительно друг друга. Если такие провода перегибать, то они быстро ломаются и перестают работать. Рис. 2.1. Одножильный провод
34 Глава 2 Многожильные Многожильные провода (рис. 2.2) отличаются тем, что хорошо переносят изгибы (не ломаются), благодаря чему используются в роботостроении для соединения под- вижных частей. Рис. 2.2. Многожильный провод Способы соединений проводов Так как создание робота подразумевает самостоятельное соединение проводов, то разобраться, как это можно сделать качественно, будет не лишним. Рассмотрим основные способы электрических соединений, которые можно применять при кон- струировании роботов. Рис. 2.3. Этапы соединения скруткой: провода и бокорезы {слева); зачищенные и распушенные провода (в центре сверху); скрутка (в центре внизу); изолирование скрутки {справа вверху); изолированная скрутка {справа внизу)
Провода и их соединения 3 5 Скрутка Соединение скруткой (рис. 2.3) применяется тогда, когда требуется создать контакт временно, или условия, в которых вы работаете, не позволяют применить другой тип соединений. Для соединения скруткой потребуются бокорезы или нож. Без нажима зажимаем бокорезами изоляцию проводов в месте, по которое нужно снять изоля- цию, и дергаем. Если все сделано правильно, изоляция оторвется, а жилы проводов останутся нетронутыми. Распушим жилы и скрутим провода друг с другом. Место скрутки обязательно нужно заизолировать. Следует помнить, что медь очень бы- стро окисляется, покрываясь непроводящей электрический ток пленкой, что через некоторое время сделает соединение неработоспособным. При первой возможности соединение скруткой нужно пропаять. Соединение клеммами Соединение клеммами широко применяется при быстром монтаже радиодеталей, но провода с клеммами высокого качества стоят дорого, а дешевые не лишены не- достатков, что, впрочем, компенсируется скоростью монтажа. Недостатки клемм- ных соединений заключаются в окислении контактов и потере соединения, а также в разрыве соединения при небольшом случайном усилии. Платы Arduino содержат или комплектуются клеммными разъемами, подобными разъемами комплектуется и большинство дополнительных электронных модулей (датчики, драйверы двигате- лей). Эти типы клемм называются Dupont (рис. 2.4). Для соединения проводов, питающих устройства большой мощности, — например, двигателей, применяются клеммы с болтовым зажимом. Рис. 2.4. Клеммные соединения
36 Глава 2 Пайка и ее основы Наиболее качественным соединением электронных компонентов является пайка. Пайкой называется процесс соединения двух металлических поверхностей путем введения между ними низкотемпературного расплава, который спаивает обе поверх- ности между собой. При этом спаиваемые поверхности не повреждаются. Оборудование и материалы Нам потребуются: • паяльник; • припой; • паяльный флюс или канифоль. Для комфортной работы еще будут нужны: • острый перочинный нож или бокорезы; • стальная губка для быстрой очистки жала паяльника от гари; • пинцет; • подставка для паяльника. Набор оборудования и материалов для пайки приведен на рис. 2.5. Рис. 2.5. Принадлежности для пайки: катушка с припоем (1); проволочный припой с сердцевиной из кани- фоли (2); губка для очистки жала паяльника (3); пинцет (4); канифоль (5); паяльник (6); бокорезы (7); острый нож (8); плоскогубцы (9)
Провода и их соединения 37 Этапы пайки Пайка проводов (рис. 2.6) состоит из следующих этапов: 1. Зачищаем бокорезами кончики проводов от изоляции. Для многожильного провода скручиваем жилы в одну косичку. 2. Лужение провода. Если попробовать спаять нелуженые провода, то, скорее всего, пайка будет некачественной, потому что на поверхности медных жил находится окись, препятствующая прилипанию припоя. Для лужения помещаем кончик жала паяльника в канифоль, и пока расплавленная канифоль не испарилась с жала, переносим ее на зачищенный кончик провода. Теперь повторяем ту же операцию с припоем: берем на кончик паяльника каплю припоя, а затем переносим ее на кончик провода. Капля припоя должна растечься, и оголенный кончик провода приобретет цвет припоя, при этом жилки провода прочно спаяются между собой. Операция лужения перед пайкой обязательна. 3. Соединяем спаиваемые концы проводов между собой и дотрагиваемся паяльником с капелькой припоя до места соединения — капля растечется по Рис. 2.6. Процесс пайки: обрезка края проводов (1); зачистка (2); лужение (3); готовые к пайке концы (4); спаянные провода (5)
38 Глава 2 проводам и, после охлаждения, прочно спаяет провода. Долго паяльник держать не нужно, для тонких проводов достаточно долей секунды. 4. После охлаждения место спайки необходимо изолировать изолентой или трубкой ПВХ. Начинающие небрежно относятся к изоляции, что в дальнейшем может привести к порче электроники вашего проекта. Выбор паяльника Выбор паяльника зависит от цели его использования. Для удобной пайки тонких проводов и контактов электронных схем требуется паяльник с тонким жалом и мощ- ностью 20-30 ватт. Я рекомендую приобрести отечественный паяльник с медным жалом (рис. 2.7). Рис. 2.7. Паяльник с медным жалом Конечно, он может оказаться дороже импортного паяльника с подобными характе- ристиками, но намного точнее по параметрам. Однажды я приобрел два одинаковых импортных 20-ваттных паяльника, но один из них имел мощность, соответствую- щую номиналу, а другой постоянно перегревался, и им невозможно было паять. Впрочем, высококачественные паяльники зарубежного производства с регулиров- кой температуры, не обгорающими жалами и набором сменных жал разного вида стоят достаточно дорого. Если вы планируете паять толстые провода, то потребуется паяльник мощностью 40-60 ватт, паять им тонкие провода и микросхемы неудобно.
Провода и их соединения 3 9 Уход за паяльником При пайке на жале паяльника посто- янно скапливается нагар, что пре- пятствует смачиванию его припоем. Нагар можно убрать, поместив жало в проволочную губку. Такую губку можно приобрести в магазине ку- хонных принадлежностей, но есть и специализированные — в них губка помещена в специальную баночку (рис. 2.8). Медное жало может обгорать до та- кой степени, что чистка в губке уже не помогает, — в этом случае кон- чик жала зачищают напильником. Напильником также можно при- давать кончику жала удобную для пайки форму. Когда жало полностью сработается, его можно заменить — Запасные Жала Продают В Магазинах Рис. 2.8. Проволочная губка для снятия нагара электроники. Припои Выбор припоя также важен. В качестве припоя применяется легкоплавкий сплав ме- таллов, температура плавления которого может колебаться от 200 до 350 градусов. При монтаже электроники используются оловянно-свинцовые припои. Согласно отечественной маркировке, оловянно-свинцовый пропой обозначается буква- ми ПОС, после которых идет число, обозначающее процентное содержание оло- ва. Температуры плавления различных оловянно-свинцовых припоев в градусах Цельсия: ПОСЗО - 240°, ПОС40 - 210°, ПОС61 - 180°, ПОС90 - 310°. Проволочный припой может содержать внутри себя сердцевину из канифоли для лучшего качества спайки. Флюсы Флюс служит для удаления слоя окисла со спаиваемых поверхностей, предохраня- ет металл от окисления при пайке, а также способствует равномерному растеканию припоя. Флюсы делятся на активные и неактивные. Активные флюсы содержат ак- тивные кислоты и применяются для пайки различных металлов, не только меди. Остатки активных флюсов должны обязательно удаляться после пайки смывкой,
40 Глава 2 иначе они начинают разъедать место пайки. Неактивные флюсы в удалении не нуж- даются, но справляются далеко не со всеми окислами металлов. К неактивным флюсам относится канифоль и ее растворы. Для большинства элек- тронных контактов она подойдет — смачиваем контакт канифолью, а затем паяем припоем. Но, в случаях, когда спаять требуется сталь или алюминий, канифоль бесполез- на. Так, если надо припаять провод к контакту аккумулятора, без активного флю- са не обойтись. Активные флюсы (рис. 2.9) бывают жидкими и желеобразными. Желеобразными флюсами пользоваться удобнее, они не стекают после нанесения на поверхность. Самым распространенным активным паяльным флюсом является паяльная кислота, и ее обязательно нужно смывать после пайки. Хорошо зарекомен- довал себя флюс для алюминия, с ним можно паять почти все металлы. Рис. 2.9. Активные флюсы Выводы Мы рассмотрели здесь виды проводов и соединений, а также — подробно — этапы и особенности пайки, ведь пайка является наиболее качественным соединением для электрических проводов. Если вопросы все же остались, можно обратиться к YouTube — там есть несколько каналов, которые очень доходчиво объясняют и по- казывают, как паять правильно. Следующая глава будет посвящена электрическому питанию роботов, выбору источ- ников электропитания и их особенностям.
ГЛАВА 3 ЭЛЕКТРОПИТАНИЕ Прежде чем начать обсуждать источники электрического питания, которые можно использовать в роботах, следует вспомнить немного теории. Закон Ома Электрический ток измеряется в амперах (А), и в формулах он обозначается бук- вой I. Электрическое напряжение измеряется в вольтах (В), его принято обозначать буквой U. Сопротивление измеряется в омах (Ом) и обозначается буквой R. Связь между ними записывается в виде формулы (закона) Ома: R Электрическая мощность При обсуждении источников электрического тока будет важна еще одна характери- стика — электрическая мощность: Мощность измеряется в ваттах (Вт) и показывает работу, выполненную за 1 секун- ду электрическим током. Для нас будет важна потребляемая роботом мощность. На основании значений потребляемой мощности должен подбираться источник элект- рического питания.
42 Глава 3 Характеристики элементов питания Номинальное напряжение Номинальное напряжение — напряжение, которое будет на клеммах элемента пита- ния при работе его в нормальных условиях. Номинальный ток Номинальный ток — ток, при котором элемент питания будет работать в соответ- ствии с указанными в документации на него параметрами. Емкость Для аккумуляторной батареи важна' ее емкость, измеряемая в ампер-часах. Обозначают ее на аккумуляторах в миллиампер-часах или mAh. Двигатели, которые будут применяться в рассматриваемых моделях роботов, тре- буют напряжения питания от 4 до 7 В и потребляют ток 0,1 А. Максимальный ток при четырех одновременно работающих моторах будет тогда 0,4 А. Электронный контроллер Arduino потребляет порядка 0,05 А. Так что при питании от источни- ка 7 вольт будет потребляться мощность около 3 Вт, а общий ток достигнет 0,45 А. Если емкость используемой батареи 2 ампер-часа (2000 mAh), то робот проработает около 4,5 часа без остановки. Когда робот прекращает движение, его потребление энергии снижается до потребления только контроллером. Форм-фактор Самыми распространенными типоразмерами элементов питания являются стан- дарты АА и ААА с размерами 14,5x50x5 мм и 10,5x44,5 мм соответственно. С по- явлением литий-ионных аккумуляторов стал распространяться типоразмер 18650 (18x66,5 мм). Указанные элементы питания представляют собой цилиндры с полю- сами на концах. Существуют и другие форм-факторы элементов питания, но при по- строении несложных роботов с использованием контроллеров Arduino чаще всего используются батареи АА и 18650. Типы элементов электрического питания Элементы питания можно поделить на перезаряжаемые и не перезаряжаемые. Не перезаряжаемые используются от начала эксплуатации до окончания нормальной работы (обеспечение номинального напряжения и тока), после чего утилизируются.
Электропитание 43 Перезаряжаемые элементы принято называть аккумуляторами, они заряжаются спе- циальными зарядными устройствами, накапливают электрический заряд, затем ис- пользуются, а после использования и разряда снова заряжаются. Так как моторные роботы потребляют относительно много электрической энергии, использование в них аккумуляторных батарей является предпочтительным. Солевые батареи Солевые батареи — это самые недорогие не перезаряжаемые источники питания. Они могут быть использованы только тех в роботах, где отсутствуют мощные по- требители электроэнергии, — такие как двигатели, мощное освещение, работа по радиоканалу. Имеют малую емкость и нестабильное напряжение. Номинальное на- пряжение для формата АА — 1,5 В. Алкалиновые батареи Алкалиновые батареи (также называются щелочными) имеют увеличенный по срав- нению с солевыми срок службы и хранения. Маркируются надписью «Alkaline». Могут быть использованы в роботах с мощными потребителями электроэнергии. Номинальное напряжение для формата АА — 1,5 В. Никель-металлогидридные аккумуляторы Самым распространенным типом акку- муляторов являются никель-металлогид- ридные (рис. 3.1), их номинальное напря- жение — 1,2 В (формат АА), и емкость от 900 до 3000 mAh. Для электропитания ро- бота на основе платы Arduino потребует- ся 6 подобных аккумуляторов, соединен- ных последовательно, что даст на выходе напряжение 7,2 В. Этого будет достаточно как для питания платы Arduino (6-12 В), так и для моторной части робота. Следует учитывать, что при последовательном соединении емкости батарей не склады- ваются, поэтому для продления их жизни следует применять совместно аккумуля- торы с одинаковой емкостью. Рис. 3.1. Никель-металлогидридные аккумуляторы формата АА
44 Глава 3 Литий-ионные аккумуляторы Если в моменты пиковой нагрузки робот останавливается и перезагружается, значит, были выбраны элементы питания недостаточной мощности, которые не в состоя- нии вырабатывать требуемый роботу ток. При этом напряжение питания падает, что и приводит к отключению электроники. Этого можно избежать, если параллельно примененному источнику питания подключить другой, что увеличит максимальную отдаваемую мощность. Можно также запитать электронику робота от отдельного ис- точника, не забыв в этом случае объединить отрицательные полюса обоих источни- ков питания. Еще одним выходом из подобной ситуации является использование более мощных батарей — например, литий-ионных (рис. 3.2). Для них стандартным номинальным напряжением является значение 3,7 В. Производятся литий-ионные аккумуляторы как в виде круглых батарей формата 18650, так и в виде пластин, их широко при- меняют в планшетах и сотовых телефонах. Емкость аккумуляторов формата 18650 составляет 1500-4000 mAh. Рис. 3.2. Литий-ионные аккумуляторы: слева — цилиндрический; справа — плоский Стабилизация электропитания Важным моментом в электротехнике является наличие прочного контакта в цепи источников питания — особенно это касается подвижных роботов, рывки и толчки которых могут приводить к разрыву питающей цепи. Для того чтобы разрывов питающей цепи не происходило, следует использовать подпружи- ненные контакты и специальные боксы с подоб- ными контактами (рис. 3.3). Электронные компоненты — такие как контрол- леры, датчики, приемопередающие устройства — очень чувствительны к скачкам в цепи электро- питания. Аккумуляторы хоть и промаркирова- ны номинальным напряжением, НО реальное Рис. 3.3. Бокс для элементов питания
Электропитание 45 напряжение на них колеблется в зависимости от уровня заряда в широких пределах. Решением вопроса стабилизации электрического питания занимаются специальные приборы — стабилизаторы питания. Стабилизация напряжения Самым доступным понижающим стабилизатором напряжения питания является микросхема КР142ЕН5А или ее аналог L7805CV. Схема подключения L7805CV пока- зана на рис. 3.4: на вход поступает нестабилизированное напряжение 7 В или выше, а на выходе получаем стабильное постоянное напряжение 5 В. 6,5-12 В In (вход) GND ("земля") 78-128 12V IC2 | 5в стабилизированное Рис. 3.4. Стабилизация питания при помощи микросхемы L7805CV: схема соединений (вверху); электрическая схема {внизу)
46 Глава 3 Имеются подобные стабилизаторы и на другое напряжение, существуют также на- страиваемые стабилизаторы. Платы Arduino UNO и Nano включают в себя, как ми- нимум, один стабилизатор напряжения на 5 В и на 3,3 В. В робототехнике иногда применяются импульсные стабилизаторы. В последнее вре- мя стали популярны импульсные понижающие стабилизаторы китайского производ- ства с настройкой выходного напряжения на основе микросхемы LM2596 (рис. 3.5). Рис. 3.5. Понижающий импульсный стабилизатор на основе микросхемы LM2596 Импульсные стабилизаторы экономичны, их КПД достигает 95%. Существуют также повышающие импульсные стабилизаторы. Они могут, имея на входе 3,7 В, преобразовать это напряжение в нужные для питания электроники ро- бота 5 В. Визуально они мало отличаются от понижающих стабилизаторов напряже- ния, но работают на микросхеме XL6009 (рис. 3.6). Рис. 3.6. Повышающий импульсный стабилизатор на микросхеме XL6009
Электропитание 47 Стабилизация электрического тока В некоторых случаях может потребоваться получить не стабильное напряжение, а стабильный ток, — например, при подключении светодиодов. В этом случае исполь- зуются стабилизаторы тока. Стабилизатор тока несложно построить на микросхеме LM317T (рис. 3.7). Значение стабилизируемого тока зависит от величины сопротив- ления R1. LED1 U2 V1 С1 Lm317t -ЛЛЛЛг- fout=l,2/Rl; Рис. 3.7. Источник тока на базе LM317Т Выводы Мы рассмотрели здесь различные источники электропитания, в том числе наиболее эффективные никель-металлогидридные или литий-ионные аккумуляторы, которые и рекомендуется использовать для питания роботов. Рассмотрен также ряд наиболее распространенных схем стабилизаторов питания — от них следует запитывать кон- троллеры, датчики, приемопередающие устройства и другие чувствительные к пи- танию устройства. Далее будут рассмотрены основы программирования для контроллера Arduino, на котором строится система принятия решений робота, его «компьютер».
ГЛАВА 4 ОСНОВЫ ПРОГРАММИРОВАНИЯ ARDUINO Для того чтобы робот начал решать какую-либо задачу, собрать его недостаточно, потребуется создать и поместить в него специальную программу (план действий). Подобные программы называются компьютерными. Компьютерная программа Компьютерная программа — это четко формализованный план, состоящий из ко- манд для контроллера (системы принятия решений). Контроллер поочередно чи- тает команды и исполняет. Стоит указать, что команды внутри любого цифрового устройства, коим и является контроллер Arduino, закодированы нулями и единица- ми, которые называются двоичным представлением чисел, то есть вся информация перед поступлением в контроллер перекодируется из привычной для нас десятичной системы счисления в двоичную. Таким образом, при выполнении логических или арифметических операций контроллер сравнивает, делит, вычитает, выполняет про- чие действия именно над двоичными числами. Эти числа хранятся в последователь- ных ячейках памяти, имеющих определенные адреса. При поступлении на контроллер Arduino электрического питания автоматически на- чинается выполнение той программы, которая была в него загружена, если же про- грамма отсутствует или написана некорректно, то происходит сбой, который либо останавливает выполнение команд, либо приводит к зависанию программы (пере- ходу ее в бесконечный цикл). Номер выполняемой команды хранится в специаль- ной ячейке памяти, которая называется счетчиком команд. Этот номер изменяется на следующий при выполнении арифметических операций, но может измениться и на любой адрес, если выполнялась логическая команда, результатом которой стал переход на некоторый пункт плана, отличный от следующего по порядку.
50 Главой Алгоритм Для визуального представ- ления компьютерных про- грамм используют их гра- фическую запись, называе- мую блок-схемой алгоритма. Алгоритм, не имеющий ло- гических блоков и выпол- няемый строго по пунктам от начала и до конца, назы- вается линейным (рис. 4.1). Если алгоритм после дости- жения последнего пункта подразумевает бесконечное повторение, его называ- ют циклическим (рис. 4.2). При наличии в алгоритме анализа некоторого значе- ния и принятия решения в результате такого анализа, этот алгоритм называется разветвляющимся (рис. 4.3). Алгоритмы легко анализи- ровать и создавать — для этого нужен только лист бумаги и карандаш. При по- мощи алгоритмов можно описывать не только ком- пьютерные программы, но и любые планы — напри- мер, планировать бизнес- процесс. 1 свернуть напра на 10 градусов Рис. 4.1. Линейный алгоритм Рис. 4.2. Циклический алгоритм Да Нет i Рис. 4.3. Разветвляющийся алгоритм
Основы программирования Arduino 51 Алгоритмы можно записывать и в простой текстовой форме: 1. Ехать вперед 10 секунд. 2. Повернуть направо на 10 градусов. А для разветвляющегося и циклического алгоритмов: 1. Получение информации о наличии препятствия с датчика. 2. Если препятствие есть, то перейти на пункт 5. 3. Ехать вперед 10 секунд. 4. Перейти на пункт 6. 5. Повернуть направо на 10 градусов. 6. Перейти на пункт 1. Текстовая форма алгоритма более похожа на компьютерную программу, но визуаль- но воспринимается хуже, в ней труднее найти логические ошибки, особенно если переходов много. Для того чтобы создать компьютерную программу, необходимо ясно понять, что она должна делать, и главное, как она это будет делать. Если некоторые вопросы вами еще не проработаны, а вы уже сели за написание серьезной программы, то, скорее всего, она не будет работать, как вы рассчитываете. Поэтому нужно идти от простого к сложному, разбивать программы на маленькие простые блоки, добиваться их ра- ботоспособности, а только затем собирать из них полную программу для робота. Среда разработки Arduino IDE Перейдем к практике. В основу языка программирования, используемого в проектах Arduino, положен язык C++ — один из самых широко используемых языков про- граммирования, поддерживающий как работу с низкоуровневыми командами, так и построение сложных объектов. Программирование контроллеров Arduino удобно осуществлять в специальной среде Arduino IDE, поскольку в нее включен основной функционал для работы с ними. Установка Arduino IDE Arduino IDE можно скачать в Интернете по адресу основного сайта проекта: www. arduino.cc/en/Main/Software, программное обеспечение бесплатное, но если есть желание помочь проекту, то это можно сделать, нажав кнопку CONTRIBUTE & DOWNLOAD, для простого же скачивания нажмите кнопку JUST DOWNLOAD (рис. 4.4).
52 Глава 4 Рис. 4.4. Окно скачивания программы Arduino IDE Выберите вариант и скачайте на компьютер программу инсталля- ции Arduino IDE — в настоящий момент это файл arduino-1.6.8-windows.exe. Его надо запустить на выполнение с административными полномочиями, принять условия лицензии GNU LESSER GENERAL PUBLIC LICENSE и согласиться с предложенным вариантом установки. На все предупреждения Windows в процессе установки следует отвечать утверди- тельно (продолжать установку). Когда установщик предложит установить драйверы порта, также ответить утвердительно. Начало работы с Arduino IDE При запуске установленной Arduino IDE откроется окно (рис. 4.5), в котором уже со- держится заготовка программы. Она состоит из двух функций: setup и loop. Функция setup содержит команды, выполняемые один раз при включении Arduino, — это установка номеров портов ввода/вывода для управления моторами и установка ско- рости обмена данными между Arduino и компьютером. Функция loop выполняется бесконечное число раз — до тех пор, пока мы не отключим питание, фактически она зациклена, алгоритмически это изображено на рис. 4.6.
Основы программирования Arduino 53 Рис. 4.5. Окно Arduino IDE (заготовка программы) Рис. 4.6. Типовой алгоритм программы в Arduino IDE
54 Глава 4 Подключение контроллера Arduino к ПК Теперь можно подключить контроллер Arduino к компьютеру. В зависимости от того, какой контроллер Arduino используется, могут потребоваться разные кабели: • для Arduino UNO R3 и Mega — это кабель с разъемом под USB-принтер с одной стороны и стандартным USB-разъемом с другой (рис. 4.7); • для контроллера Nano требуется кабель с разъемом mini-USB (рис. 4.8); • для Arduino Micro - это micro-USB, а для программирования контроллера Arduino Mini и Pro Mini потребуется программатор (рис. 4.9), так как у него отсутствует стандартный интерфейс для подключения его к компьютеру. Рис. 4.7. Кабель для Arduino UNO и Arduino Mega Рис. 4.8. Кабель для Arduino Nano Рис. 4.9. Программатор и Arduino Mini Некоторые контроллеры требуют для своей работы нестандартный драйвер. Так, я встречал контроллеры Arduino, которые требуют установки отдельного драйвера, не входящего в комплект Arduino IDE, — его название ch34iser.exe. Найти его не трудно, после установки драйвера проблема будет решена. Физически подключив контроллер к ПК, следует установить связь между ним и обо- лочкой Arduino IDE. Для этого нужно задать номер порта, к которому подключен кон- троллер (рис. 4.10). Если портов много, и найти нужный сложно, рекомендуется за- помнить все имеющиеся, а затем физически отсоединить Arduino от кабеля, и снова проанализировать список портов, — тот, который исчез, и есть нужный. Подключайте снова контроллер и выбирайте появившийся порт — для этого нужно установить соот- ветствующий ему флажок. Иногда для появления порта в списке требуется некоторое время, за которое операционная система компьютера анализирует и проверяет под- ключенное устройство, так что подождите немного до завершения этого процесса.
Основы программирования Arduino 55 Рис. 4.10. Выбор порта У пользователей Windows XP может возникнуть проблема, а именно — драйвер пор- та контроллера Arduino не установится автоматически. Решение этой проблемы опи- сано на сайте Arduino по адресу: http://arduino.ru/Guide/Windows. На следующем шаге выберем тип контроллера Arduino. На рис. 4.11 можно видеть, что выбран Arduino Nano, если же у вас Arduino Uno, то выбирайте пункт Arduino/ Genuino Uno. Рис. 4.11. Выбор контроллера Arduino
56 Глава 4 Если контроллер выбран системой автоматически, проверьте правильность этого выбора. Для некоторых контроллеров необходимо еще выбрать микроконтроллер, на котором реализована плата Arduino. Название микроконтроллера можно найти на самой его микросхеме — это, как правило, самая большая микросхема платы и расположена она в ее центре. Мигаем светодиодом Загрузить написанную в Arduino IDE программу в контроллер, даже если она пустая, можно, нажав на кнопку со стрелкой вправо И (см. рис. 4.5). Оболочка проверит программу на наличие ошибок, а затем переведет ее в двоичный код данных и ко- манд выбранного микроконтроллера и запишет в Arduino. Если после появления слова Загрузка в нижней строке окна Arduino IDE замига- ли светодиоды ТХ и RX на плате Arduino, то загрузка программы в плату началась успешно. Если после этого фраза Загрузка завершена не появилась, то, скорее все- го, не правильно выбран тип платы Arduino. Если же диоды ТХ и RX не замигали вообще, то проблемы заключаются в выборе порта платы Arduino. Если же все пойдет штатно, появится надпись Загрузка завершена, и программа ав- томатически начнет выполняться. Если загружена пустая программа, то ничего и не произойдет, — пустой код будет бесконечно повторяться, пока к плате подключено электропитание. Немного усложним программу, заставив Arduino мигать встроенным светодиодом на 13-м порту (листинг 4.1). Диод — это электронный элемент, который пропускает электрический ток только в одном направлении, а вот светодиод — это диод, который начинает светиться при протекании по нему тока. На плате контроллера Arduino, как правило, уже установлен один светодиод — именно на 13-м порту (ножке). Листинг 4.1. Программа мигания светодиодом void setup() // Настройка { // Переводим 13-й порт в состояние вывода информации pinMode(13, OUTPUT); } // Основная программа void loop ()
Основы программирования Arduino 5 7 { digitalWrite(13, 1); // Включает светодиод на плате, delay(1000); // Ждет 1 сек. digitalWrite(13, 0); // Выключает светодиод. delay(lOOO); // Ждет 1 сек. } Электронный архив Напомню, что электронный архив с материалами к этой книге можно скачать с FTP-сервера издательства «БХВ-Петербург» по ссылке ftp://ftp.bhv.ru/9785977537414.zip или со страницы книги на сайте www.bhv.ru. Все необходимые листинги расположены там в пап- ках с номерами, соответствующими их номеру в тексте книги (см. приложение 3). Цифровые порты могут получать и передавать информацию только в виде последо- вательности нулей и единиц. В приведенном примере как раз и передается на порт 13 подобная последовательность — визуально это отслеживается по морганию свето- диода на плате контроллера. Когда светодиод горит, на порту высокое электрическое напряжение 5 В, а когда потушен — низкое (0 В). Мониторинг работы программы Научим контроллер общаться с компьютером во время выполнения программы и за- пишем для этого в функции setup команду serial .begin (9600), которая указывает, с какой скоростью происходит обмен информацией с ПК. Для обмена информацией требуется, чтобы приемник и передатчик осуществляли обмен на одинаковой скоро- сти, а так как контроллер Arduino достаточно медленный, то наиболее подходящей для обмена с ним является скорость 9600 бод. Обмен информацией на более высоких скоростях также возможен, но задействует большее количество ресурсов контрол- лера, при этом чаще происходят прерывания текущей программы, и основной код может выполняться медленнее. Команда serial, print in о передает с контроллера на ПК значение, указанное в скобках. Здесь это значение, возвращаемое функцией minis о, которая возвраща- ет время работы в миллисекундах. Программа и результат ее работы приведены на рис. 4.12. Для получения на экране компьютера полученных результатов после запу- ска программы потребуется еще открыть вкладку Инструменты | Монитор порта и, возможно, скорректировать скорость порта (в программе это 9600 бод) — в окне Монитор порта скорость задается в правом нижнем углу выбором из всплывающе- го списка.
58 Глава 4 ШШшЩ :2Э99 ;5000 7000 :Э000 ['11000 13000 15001 19001 .21002 ;23002 25003 ■29003 31003 ^33003 • 35004 '37Q04 ■39Q05 "41005 ,43004 .^45005 :Ч7005 |49006 §51006 Рис. 4.12. Протокол загрузки программы и результат работы Переменные Важной составляющей синтаксиса языков программирования являются перемен- ные. Переменные — это поименованная память, в которую можно вносить данные и из которой можно брать данные. До начала работы с переменными их нужно объ- явить. В C++ переменные можно объявлять практически в любых местах програм- мы, но важно знать о зоне видимости переменных — они видны лишь внутри того блока, в котором объявлены.
Основы программирования Arduino 5 9 Листинг 4.2. Объявление переменных. Зоны видимости. Сообщение об ошибке // Переменные будут видны везде в программе int exl; float ex2; void setup() // Настройка // Переменная будет видна только внутри функции setup, int ехЗ; ехЗ=8; // Устанавливаем скорость порта связи Arduino - ПК. Serial.begin(9600); // Значение exl изменится на 8*2. exl=ex3*2; } // Основная программа void loop() { // Следующая строка содержит ошибку, // переменная ехЗ не может быть видна за пределами функции setup. ex3=exl+5; delay(exl*100); // Ждет 8*2*100 миллисекунд. // Передает на компьютер время работы в миллисекундах. Serial.println(millis()); delay(1000); // Ждет 1 сек. Листинг 4.2 в демонстрационных целях содержит специально добавленную в него ошибку объявления переменной, и при попытке его скомпилировать об этой ошибке будет выведено сообщение: fex3f was not declared in this scope. Переменные могут отличаться по типу данных, для хранения которых созданы (табл. 4.1).
60 Глава 4 , Обозначение i в программе boolean char byte int long ! Название Логический Символьный Таблица 4.1. Типы данных i float- Короткое беззнаковое целое Целое число |Длинное I целое число [Число _[_с плавающей точкой Принимаемые значения True/false, 1/0 -128/+127 0-255 -32768/32767 | -2147483648/2147483647 -3,4028235-1038/3,4028235-1038 Размер в памяти 1 байт 1 байт 1 байт 2 байта 4 байта 4 байта При работе с переменными следует понимать, что они не являются идеальным хра- нилищем информации — так, например, целочисленные переменные могут перепол- няться. Это происходит в тех случаях, когда значение, которое следует записать в переменную, больше максимально возможного для этого типа данных. Переменные с плавающей точкой подвержены другой проблеме — они округляют свои значе- ния при сложении большого числа с малым. Например, сложение 1,1 -1025 и 10 даст 1,1-102\ а число 10 просто потеряется. Также Arduino IDE не всегда корректно рабо- тает с преобразованием типов данных. Рассмотрим небольшую программу, осуществляющую получение данных от ком- пьютера через порт ввода/вывода (листинг 4.3). Листинг 4.3. Получение данных от компьютера через порт ввода/вывода void setup () // Настройка { // Устанавливаем скорость порта связи Arduino - ПК. Serial.begm(9600) ; } // Основная программа void loop () char charl; // если поступили данные, if (Senal. avail able () > 0)
Основы программирования Arduino 61 // считываем символ. charl = Serial.read(); // отсылаем то, что получили, обратно на ПК. Serial.println(charl); Скомпилируйте и загрузите эту программу. Введите в верхней части окна Монитор порта слово ПРИВЕТ! и нажмите кнопку Отправить. Программа отправит слово ПРИВЕТ! обратно на ПК посимвольно. Результат будет виден в нижней части окна: П Р И В Е Т Условные операторы Условные операторы мы уже немного использовали, а теперь рассмотрим их подробно. Оператор If ...else Оператор if ... else графически, в виде блок-схемы алгоритма, представлен на рис. 4.13, а в виде фрагмента кода — в листинге 4.4. Рис. 4.13. Представление условного оператора
62 Глава 4 Листинг 4.4. Применение оператора If ... else при управлении движением робота if (distance < 10) { // Если дистанция до препятствия меньше 10 см. Povorot(Right,10); // Поворот вправо на 10 градусов. else // Иначе, если расстояние больше 10 см. { VperedO; // Едем вперед 10 секунд. delay(10000); } Как можно видеть, в этом фрагменте не раскрывается суть измерения расстояния, или как наш робот будет двигаться, — это скрыто во внешних функциях. Создадим программу (листинг 4.5), которая изменяет частоту моргания встроенно- го светодиода на 13-м порту (рис. 4.14) в зависимости от посланной с компьютера команды. Блок-схема алгоритма этой программы представлена на рис. 4.15. Программа не завершается, пока есть электропитание, в ней присутствуют три услов- ных блока: один проверяет наличие данных на порту ввода/вывода, а последующие Светодиоды ввода/вывода Светодиод 13 порта данных подключены / обозначен буквой L к портам 0 и 1 \^ Светодиод наличия питания Рис. 4.14. Светодиоды на плате Arduino UNO
Основы программирования Arduino 63 два сравнивают полученный символ с условиями, в зависимости от которых изменя- ют величину переменной timepick, задающую время задержки при мигании свето- диода. Листинг 4.5. Программа управления миганием светодиодом с ПК int time_pick; // Переменная для хранения времени свечения светодиода. void setup() // Настройка { // Устанавливаем скорость порта связи Arduino - ПК. Serial.begin(9600); // Переводим 13-й порт в состояние вывода информации pinMode(13, OUTPUT); time_pick=200; // Период свечения светодиода. } // Основная программа. void loop () { char charl; // если поступили данные, if (Serial.available() > 0) { // считываем символ, charl = Serial.read(); if(charl=='V ) I/ Если нажата "Iм. {time_pick=1000;} // Задержка мигания 1 сек. else { // Если нажата "2". // Задержка мигания 0,5 сек. if (charl='2') { time_pick=500;} // Если нажато что-то другое. else {time_pick=100;}} // Задержка мигания ОД сек.
64 Глава 4 diqitalWrite(13, 1) ; delay(time pick) ; digitalWnte(13, 0); deJay(time pick); // Включает светодиод на плате. // Ждет // Выключает светодиод. // Ждет I -Нет- Да Нет 4 Да Нет Рис. 4.15. Алгоритм изменения частоты мигания светодиода
Основы программирования Arduino 65 Оператор switch... case Следующий оператор switch ... case позволяет сделать выбор из набора опреде- ленных значений, программа с его использованием выглядит намного проще, ее легче анализировать. Перестроим предыдущую программу, сохранив ее смысл (ли- стинг 4.6). Листинг 4.6. Программа управления миганием светодиодом с ПК с использованием оператора switch . . . case int time pick; // Переменная для хранения времени свечения светодиода. void setup() // Настройка { // Устанавливаем скорость порта связи Arduino - ПК. Serial.begin(9600); // Переводим 13-й порт в состояние вывода информации pinMode(13, OUTPUT); time_pick=200; // Период свечения светодиода. } // Основная программа, void loop () { char charl; // если поступили данные, if (Serial.available() > 0) { // считываем символ, charl = Serial.read(); switch (charl) { case '1': time_pick=1000; break; case '2': time_pick=500; break; default: time_pick=100; digitalWrite(13, 1); // Включает светодиод на плате, delay(time_pick); // Ждет digitalWrite(13, 0); // Выключает светодиод. delay(time_pick); // Ждет
66 Глава 4 Операторы циклов while и for Очень удобными также являются операторы организации циклов. Рассмотрим два оператора: while и for. Цикл while продемонстрируем на примере программы из листинга 4.1, заменив функ- цию ожидания delay () на оператор цикла по условию (листинг 4.7). Воспользуемся при этом функцией miiiiso, возвращающей количество миллисекунд от старта программы. В результате работы этой программы светодиод включается на 1 сек. и выключается на 1 сек. Листинг 4.7. Программа управления миганием светодиодом с ПК с использованием оператора цикла while void setup() // Настройка. { // Переводим 13-й порт в состояние вывода информации. pinMode(13, OUTPUT); } // Основная программа, void loop () { unsigned long time_l; unsigned long time_2; unsigned long time_3; time_l = millisO/ // Начальное значение - количество миллисекунд //от включения программы. time_2=time_l+1000; // +1 секунду. time_3=time_l+2000; // +2 секунды, while(time_l<time_2) { digitalWrite(13, 1); // Включает светодиод на плате. time_l = millisO; // Текущее время в time_l. } while(time l<time_3) { digitalWrite(13, 0); // Выключает светодиод на плате. time_l = millisO; // Текущее время в time_l.
Основы программирования Arduino 67 Оператор цикла for хорошо подходит тогда, когда требуется выполнить определенное ко- личество повторений. При построении алго- ритмов в виде блок-схем для него есть отдель- ная фигура (рис. 4.16). Для примера в листин- ге 4.8 светодиод моргает 300 раз с увеличением времени свечения на 1 миллисекунду каждый повтор. Листинг 4.8 демонстрирует программу, управ- ляющую миганием встроенного в плату свето- диода на 13-м порту, при этом частота мигания уменьшается по мере приближения к концу цикла. Затем все начинается сначала. 1 Рис. 4.16. Представление оператора for Листинг 4.8. Пример использования оператора цикла for (на 300 повторений) void setup() // Настройка { // Переводим 13-й порт в состояние вывода информации. pinMode(13, OUTPUT); } // Основная программа, void loop () { int i; for(i=0;i<300;i++) digitalWrite(13, 1); // Включает светодиод на плате, delay(i); // Ждет i миллисекунд. digitalWrite(13, 0); // Выключает светодиод. delay(i); // Ждет i миллисекунд.
68 Глава 4 Функции Функции являются поименованными блоками команд, которые по их имени можно вызывать из любого места программы. Функции нужно применять там, где суще- ствует необходимость одинаковый программный код повторять много раз, или если нагромождение команд в основной программе делает ее нечитаемой. Существуют встроенные функции — они уже присутствуют в библиотеке функций Arduino IDE — и функции, созданные в рамках текущей программы. Также суще- ствуют библиотеки, которые можно подключать к текущей программе и пользовать- ся имеющимися в них функциями. Подключаются библиотеки из пункта оболочки Скетч | Подключить библиотеку. После подключения той или иной библиотеки можно использовать содержащиеся в ней готовые программные решения, написан- ные для различных устройств и датчиков. В листинге 4.9 приведен пример написания и использования простой функции — она сравнивает два числа и возвращает наибольшее из сравниваемых. Для функций, ко- торые могут возвращать значения, при их описании в строке перед именем функции устанавливается тип возвращаемого значения, в нашем случае — это целое число: int. Для возврата значения из функции используется ключевое слово return, за ко- торым следует возвращаемое значение. При описании функций, не возвращающих значения, в строке перед их именем долж- но СТОЯТЬ СЛОВО void. Действия, производимые функцией, заключаются в фигурные скобки и называются телом функции. Листинг 4.9. Пример написания и использования функции void setup() { } void loop () { int х=10; int y=25; // Вызов функции sravnenie(). int s=sravnenie(x,у); // Определение функции sravnenie ()
Основы программирования Arduino 69 // Указываем тип возвращаемого значения, имя функции и информацию о фомальных аргументах int sravnenie(int a, int b) // Далее идет тело функции { if(a<b) return b; else return a; Элементы объектно-ориентированного программирования Язык C++, который составляет основу для программирования в проекте Arduino, является объектно-ориентированным. Объекты — это сложные структуры, которые имеют оригинальное название, могут включать в себя как переменные, так и функ- ции. Фактически, объекты созданы для удобного обращения к сложным структурам. Например, когда мы программно подключаем сервомотор, то подключаем сначала библиотеку (#include <Servo . h>), а Затем СОЗДаеМ объект servomotor (ЛИСТИНГ 4.10). Рис. 4.17. Подключение сервомотора к контроллеру Arduino UNO
70 Глава 4 Естественно, что при этом управляющий контакт сервомотора должен быть физиче- ски подключен к порту Arduino, и на мотор подано электропитание (рис. 4.17). Листинг 4.10. Пример управления сервомотором // Подключаем библиотеку для управления сервомоторами. #include <Servo.h> // Создаем объект сервомотор. Servo servomotor; void setup() { // Присоединяем сервомотор к 12 пину Arduino. servomotor.attach(12); } void loop() { servomotor.write(10); // Поворачиваем вал сервомотора в положение 10°. // Угол сервомотора увеличивается по часовой стрелке. delay(500);// Задержка нужна, чтобы сервомотор успел повернуть. servomotor.write(150);// Поворачиваем вал сервомотора в положение 150°. delay(500);// Задержка на поворот. Выводы Начальное знакомство с языком программирования Arduino C++ завершено. Более детальную информацию можно получить из тематической литературы и на сайте arduino.ru в разделе Программирование. Далее в книге также будут рассмотрены типичные программы функционирования роботов: управления двигателями постоянного тока, измерения расстояния датчи- ком-дальномером, взаимодействия с электронным компасом и др. А в следующих двух главах мы познакомимся с конструкциями роботов и соберем свою базовую модель.
ГЛАВА 5 ХОДОВАЯ ЧАСТЬ Типы ходовых частей Ходовая часть — это комплекс узлов и агрегатов, с помощью которых возможно пе- редвижение робота. Выбор ходовой части для робота, конечно, важный вопрос. При этом можно исходить либо из поставленных перед роботом задач, либо из имеющих- ся ресурсов, а если основная задача робота — это знакомство с робототехникой, то немаловажным критерием становится доступность деталей ходовой части и просто- та ее изготовления. Рассмотрим некоторые виды ходовых частей. Ноги Ходовую часть робота можно организовать на основе ног (шагающий робот). Бывают они как двуногие (рис. 5.1), так и многоногие (рис. 5.2-5.4). Двуногие роботы при- меняются там, где требуется уподобить робота человеку, их тогда называют челове- коподобными, или андроидами. Двуногим роботам требуется большое количество высокоточных моторов — так, для робота, показанного на рис. 5.1, в создании ног задействовано 10 сервоприводов, а это усложняет управление ими, поскольку вращение всех моторов нужно синхрони- зировать. Кроме того, потребуется научить робота держать равновесие, а при паде- нии он должен уметь вставать на ноги. Так что, поскольку мы только знакомимся с робототехникой, временно отложим создание и использование подобной ходовой части. Роботы, ходовые части которых состоят из четырех и более ног, более устойчивы и могут не содержать механизмов балансировки, так как падение их почти
72 невозможно. Ноги подобных роботов проще в реализации и управлении, да и содержат они по три (см. рис. 5.2) или даже по два (см. рис. 5.3) сервопривода. Количество сервоприводов для разных ног может различаться — например, ро- бот на рис. 5.4 имеет по три сервопривода на передних ногах и по два на задних. Конечно, есть возможность создавать шагающих роботов и с меньшими затра- тами на моторы. Так, робот на рис. 5.5 обходится двумя моторами для организа- ции движения шести ног. К таким маши- нам относится и стопоходящая машина П. Л. Чебышева, реализовать движения которой можно при помощи одного дви- гателя. Но подобным «упрощенным» ша- гающим роботам сложно повернуть или преодолеть небольшое препятствие, что, безусловно, является серьезным их недо- статком. Глава 5 Рис. 5.1. Двуногий шагающий робот Рис. 5.2. Четырехногий робот на 12 сервомоторах (по 3 на ногу) Рис. 5.3. Шагающий робот на 8 сервомоторах (по 2 на ногу)
Ходовая часть 73 Рис. 5.4. Шагающий робот на 10 сервомоторах Рис. 5.5. Шагающий робот на двух сервомоторах (по 3 на передних ногах, по 2 на задних) (по одному на три ноги каждой стороны) Гусеницы Гусеничная ходовая часть (рис. 5.6) весьма широко распространена в робототехнике благодаря простой реализации и высокой проходимости роботов, построенных на ее основе. Все, что будет описываться в практических главах, относится и к ходовой части, реализованной на основе гусениц. Если у вас есть под рукой гусеничная ходовая часть, например, от сломанной радио- управляемой модели, смело можете использовать ее для создания робота по прин- ципам управления, описываемым далее. Рис. 5.6. Гусеничная ходовая
74 Глава 5 Колеса с дифференциалом Колесная ходовая часть с дифференциалом часто встречается в радиоуправляемых моделях машин. Как правило, в них задействовано два мотора постоянного тока: на дифференциал задних колес и на рулевую тягу (рис. 5.7). Чтобы воспользоваться ма- териалом практических глав для создания робота на таком ходу, вам придется суще- ственно изменить функции, реализующие движения и повороты. Рис. 5.7. Ходовая с дифференциалом на заднем мосту Колеса на моторах Колесные ходовые части с мотором на каждое колесо бывают двух видов: с двумя моторными колесами и одним опорным роликом (рис. 5.8) и с четырьмя моторными колесами (рис. 5.9). Существенных различий между ними нет, кроме того, что четырехколесный робот более мощный и устойчивый. Поэтому именно четырехколесная ходовая будет ис- пользована в проектах, представленных в главах 10-13. Но, если вам по душе робот, имеющий ходовую с двумя моторами, смело берите ее за основу. Особенности задей- ствованной в проектах электроники позволяют применять все примеры программ без каких-либо изменений.
Ходовая часть 75 Рис. 5.8. Ходовая с двумя ведущими колесами Рис. 5.9. Ходовая с четырьмя ведущими колесами Подобные ходовые части можно приобрести в специализированных магазинах и на сайтах интернет-магазинов, занимающихся продажей конструкторов для роботов. Летающие роботы Раз уж мы начали говорить о ходовых, нельзя не упомянуть роботов, которые уме- ют летать или плавать. Когда вы изучите практические главы и поймете принципы управления моторами и программную логику роботов, то реализация более экзоти- ческих конструкций для полетов и плавания перестанет быть для вас проблемой. В настоящее время широкое распространение получили радиоуправляемые квадро- коптеры (рис. 5.10), и наиболее продвинутые из них уже можно отнести к классу ро- ботов, поскольку в них ре- ализованы функции про- граммного управления, а также использования ! компаса и GPS-навигации для планирования марш- рута полетов. Конечно, управление ле- тающим роботом слож- нее, но вполне по силам даже начинающему кон- структору. Рис. 5.10. Квадрокоптер с установленной видеокамерой
76 Глава 5 Выбор двигателей Итак, когда структура ходовой выбрана, следует определить, какие двигатели будет использовать наш робот. Конечно, исходить при этом надо из наличия соответству- ющих комплектующих и/или поставленных задач, поэтому вам предстоит выбор между двигателями постоянного тока с редуктором, сервомоторами постоянного вращения и шаговыми двигателями. Их различия представлены в табл. 5.1. Таблица 5.1. Сравнительные параметры различных типов двигателей Сравниваемые параметры Количество задействованных портов микроконтроллера для управления Скорость реакции на поступившую команду, сек. Скорость вращения (с учетом понижающего редуктора), об/мин Стоимость (за единицу принята стоимость двигателя постоянно- го тока с редуктором), сравниваются двигатели, равные по мощности Минимальное количество портов управления ходовой частью для проекта колесного робота с 4-мя ведущими колесами Двигатель постоянного тока с понижающим редуктором 2-3 -1/1000 20-240 1 4 (при отказе от управления мощ- ностью и параллель- ном управлении дву- мя правыми и двумя левыми моторами) Сервомотор постоянного вращения 1 -1/10 1-60 5 2 (при параллель- ном управлении двумя правыми и двумя левыми моторами) Шаговый двигатель 4 -1/1000 1-60 3 8 (при параллель- ном управлении двумя правыми и двумя левыми моторами) Как можно видеть, наиболее быстрая реакция у двигателя постоянного тока, у него также и самая низкая стоимость. Сервомотор превосходит его за счет задействова- ния меньшего количества портов Arduino. Шаговый двигатель при использовании в ходовой части не дает особых преимуществ, хотя если количество сделанных ро- ботом оборотов колес нужно считать и строго дозировать, то это неплохой выбор. Сервомоторами хорошо регулируется скорость движения робота, если скорость ко- лес нужно менять постоянно и держать в точно заданных пределах. Скорость обо- рота колеса, вращаемого сервомотором, зависит только от установленного на пор- ту значения, и при увеличении сопротивления (когда, например, робот движется в гору) практически не меняется, в то время как двигатель постоянного тока изменя- ет скорость своего вращения в зависимости от нагрузки.
Ходовая часть 77 Шаговым двигателем также можно держать постоянную скорость, но технически ре- ализовать это несколько сложнее из-за большего количества задействованных пор- тов Arduino. Так, роботу, имеющему 4 ведущих колеса, потребуется 16 портов управ- ления, правда правые и левые колеса можно подключить к управлению параллельно, и тогда количество портов уменьшится до 8, что, однако, тоже избыточно. Тем не менее, все три вида двигателей применяются в ходовых частях колесных ро- ботов, и выбор зависит от требований, предъявляемых к роботу. Далее будет рассма- триваться ходовая с двигателями постоянного тока, снабженными редукторами, так как строгих требований к скорости и мощности робота мы предъявлять не станем. Драйверы двигателей Платы Arduino, кроме специализированных, не поддерживают возможностей управ- ления двигателями постоянного тока напрямую, и для этого приходится применять специализированные микросхемы, называемые драйверами двигателей. Наиболее распространенные из них приведены в табл. 5.2. Таблица 5.2. Специализированные микросхемы драйверов двигателей Характеристики Максимальный ток на канал, А Количество каналов Встроенная диодная защита от паразитных токов L293D 0,6 4 Есть L293B 1 4 Нет L298N 3 4 Нет Здесь рассмотрены три микросхемы драйверов, которые подходят для управления направлением вращения и мощностью двигателей постоянного тока. Они же могут применяться и для управления шаговыми двигателями. Микросхему L293D можно использовать без дополнительных доработок, более того — для повышения максимального тока эти микросхемы иногда применяются парами и снабжаются радиаторами. Микросхемы L298N и L293B должны быть уста- новлены вместе с защитными диодами, которые предохраняют от перегрузок. Если вы не боитесь пайки, то можно приобрести две микросхемы L293D, установить их друг на друга и спаять ножки, а к средним ножкам припаять дополнительный ра- диатор — например, кусок толстой медной проволоки. Теперь это изделие можно ис- пользовать в качестве драйвера для нашей модели (рис. 5.11). Однако с целью сохранения простоты сборки в проектах будет использована схемная реализация на основе микросхемы L298N (рис. 5.12). Она довольно мощная, имеет хороший запас по максимальному току (ЗА на канал), на плате уже установлены огра- ничительные диоды, и имеется дополнительный стабилизатор напряжения на 5 В.
78 Глава 5 Рис. 5.11. Спаренная микросхема L293D с радиатором из проволоки {слева); назначение контактов микро- схемы {справа) Удаление перемычки отключит внутренний стабилизатор 5В (не трогать!) \ Микросхема L298N на радиаторе ч OUT3 hOUT4 подключаются к двигателю В OUT1 и OUT2 подключаются к двигателю А "^^ От положительного (+) контакта источника питания От отрицательного (-) ^у^ у' у/ контакта источника ^^ / питания ^^ // Выход +5 В для Вход включения/ электропитания отключения, датчиков управления скоростью и пр. устройств двигателя А / \ IN1, 1Ы2-управление направлением вращение двигателя А Перемычка между данным выходом и ENB или ENA / позволяет подключать двигатели без регулировки скорости Вход включения/ отключения, управления скоростью двигателя В \ IN3, IN4 -управление направлением вращение двигателя В Рис. 5.12. Специализированная плата драйвера на микросхеме L298N
Ходовая часть 79 Порядок подключения микросхем, показанных на рис. 5.11 и 5.12, одинаков. Если не требуется обеспечивать двустороннее вращение двигателя, то можно использовать схему, приведенную на рис. 5.13. В этом случае к каждому контакту OUT (1, 2, 3, 4) можно подключить по двигателю. Высокий сигнал на In 4 включит мотор Ml, а высо- кий сигнал на In 3 — мотор М2. Постоянным колебанием сигнала на Enable 2 можно изменять скорость вращения и мощность, отдаваемую в двигатели, — фактически Enable 2 может быстро включать и отключать электропитание двигателей Ml и М2, что приводит к указанному эффекту. Такое явление называется широтно-импулъсной модуляцией (ШИМ), Arduino на некоторых портах поддерживает ШИМ, такие пор- ты отмечены на плате волнистой линией. Для Arduino UNO порты с ШИМ имеют номера 3, 5, 6, 9, 10, 11. В эти порты при использовании их как ШИМ может быть записано число от 0 до 255, при этом 0 — соответствует полному отсутствию сигнала (низкий сигнал), 255 — генерации импульсов нет, на выходе постоянно установлен высокий сигнал, 123 — соответствует генерации импульсов, у которых полтакта сиг- нал высокий, а полтакта — низкий. Рис. 5.13. Подключение двигателей для одностороннего вращения В табл. 5.3 приведены значения сигналов на входах и показана соответствующая ре- акция двигателя. Таблица 5.3. Значения сигналов на входах и соответствующая реакция двигателя In 4 0 0 1 1 1 Enable 2 0 1 1 0 ШИМ Ml (направление вращения условное) Отключен Отключен Вал вращается по часовой стрелке Отключен Вал вращается по часовой стрелке (мощность зависит от величины положительного импульса ШИМ)
80 Глава 5 Широтно-импульсная модуляция Рассмотрим подробнее, как работает широтно-импульсная модуляция. В режиме ШИМ В Соответствующий ПОрт КОМанДОЙ analogWrite (Порт, Значение) ЗаПИСЫВЭ- ется определенное число. В зависимости от этого числа на выходе порта с частотой около 490 Гц генерируется последовательность импульсов, вид которой зависит от записанного числа. Эта зависимость показана на рис. 5.14. На время положительного фронта включается двигатель — соответственно, чем шире положительный фронт, тем дольше подключен двигатель, тем больше его мощность и скорость вращения. 1 =25 0,5 0 1,5 1 *- 0,5 0 1.5 0,5 0 1,5 1 0,5 О =125 =240 =255 Рис. 5.14. Принцип работы ШИМ Вращение в обе стороны Если вал двигателя должен вращаться в обоих направлениях, нужно использовать схему, приведенную на рис. 5.15. Она позволяет подключать только два независимых двигателя, но параллельное подключение двигателей является допустимым. Значения сигналов на входах и соответствующая реакция двигателя приведены в табл. 5.4.
Ходовая часть 81 L293 (непосредственно) - L298 (на плате) bnabtei +V| la 1 In 41 Out 1 { Controlled by Enable 1 ) Out 4 ( Controlled hy Enable ^ )| ov ' игдзо ov| ov gv| Out I i. Controlted by £nabie 1 } Out I {forrtrolsed by fnabie 2 >| 7.2B .58 5 x M1 Рис. 5.15. Подключение двигателя для обеспечения двустороннего вращения Таблица S.4. Значения сигналов на входах и соответствующая реакция двигателя In 4 0 0 1 1 1 0 1 0 In3 0 1 0 1 1 0 0 1 Enable 2 0 1 1 0 1 1 шим шим Состояние двигателя Ml (направление вращения условное) Отключен Вал вращается против часовой стрелки Вал вращается по часовой стрелке Отключен Отключен (на обоих контактах двигателя напряжение питания) Отключен (оба контакта двигателя заземлены) Вал вращается по часовой стрелке (мощность зависит от вели- чины положительного импульса ШИМ) Вал вращается против часовой стрелки (мощность зависит от величины положительного импульса ШИМ) Подключение второго двигателя осуществляется аналогично — с другой стороны драйвера на порты Out 1 и Out 2. На рис. 5.16 приведена схема подключения к Arduino двигателей постоянного тока посредством драйвера L298N. При использовании показанной на рис. 5.12 платы пи- тание логической части (стабилизированные 5 В) на драйвер подавать не нужно, по- скольку на плате присутствует собственный стабилизатор напряжения. Более того,
82 Глава 5 сама плата может использоваться как стабилизированный источник напряжения на 5 В для внешних устройств. Рис. 5.16. Подключение Arduino UNO для управления двигателями постоянного тока Выводы Итак, тип ходовой выбран — это колесная ходовая часть с четырьмя (или двумя) ве- дущими колесами. Выбран и используемый тип двигателей — это двигатель постоян- ного тока с понижающим редуктором. Рассмотрен способ управления двигателями посредством специального драйвера. Определен порядок подключения и управле- ния двигателями. Следующий шаг — сборка базовой модели робота.
ГЛАВА б СБОРКА БАЗОВОЙ МОДЕЛИ Сборка робота — процесс не сложный, но требует внимания, так как неправильное подсоединение проводов может привести к порче электронных компонентов. А не- правильное крепление двигателей — например, сильная затяжка винтов, может при- вести к заклиниванию. Минимальный комплект В этом примере использованы стандартные комплектующие, которые легко приоб- рести. Выбрана база с 4-мя моторами постоянного тока с редукторами и колесами под эти редукторы (рис. 6.1), корпус из пластика и необходимые крепежные элемен- ты (винты и гайки). Робот состоит из двух уровней: • нижний: двигатели, колеса, драйвер двигателей; • верхний: источники электропитания, выключатель, плата Arduino, голова с датчиком на сервомоторе (рис. 6.2). Небольшие изменения в структуре корпуса робота и даже количество двигателей (два или четыре) не имеют принципиального значения и не требуют внесения из- менений в схему. Примечание В папке korpus сопровождающего книгу электронного архива (см. приложение 3) вы найдете вспомогательные материалы, с помощью которых детали корпуса базовой модели робота будет изготовить совсем несложно (см. также главу IS).
84 Глава 6 Колеса — 4 шт Двигатели — 4 шт Т-образные элементы для установки двигателей в корпус — 4 шт Винты Пластины корпуса (нижняя и верхняя) — 4 шт с гайками — 8 шт. Рис. 6.1. Набор деталей и комплектующих нижнего уровня: колеса (1); двигатели (2); Т-образные элементы для установки двигателей в корпус (3); нижняя и верхняя пластины корпуса (4); винты и гайки (5)
Сборка базовой модели 85 Сервомотор Плата Arduino Плата драйвера двигателей Ультразвуковой датчик измерения расстояния Бокс для батареек/ аккумуляторов Детали крепления УЗ датчика измерения расстояния Выключатель Источники электропитания Рис. 6.2. Набор деталей и комплектующих верхнего уровня
86 Глава 6 Элементы питания В качестве элементов питания в проекте используются два литиевых аккумулятора формата 18650 (рис. 6.3). Они подключаются последовательно и дают напряжение питания 7,2-8,4 вольта в зависимости от степени заряда. Но можно использовать и 6 батареек или аккумуляторов формата АА (рис. 6.4), при этом будет получено на- пряжение 7,2-9 вольт. Рис. 6.3. Плата драйвера двигателей (слева); литий- Рис. 6.4. Плата драйвера двигателей (слева) и ионные аккумуляторы (в центре); бокс для двух аккуму- бокс для четырех батарей/аккумуляторов фор- ляторов формата 18650 (справа) мата АА (справа) Двигатели Перед установкой двигателей на ходовую часть следует припаять к контактным пло- щадкам двигателей провода (рис. 6.5). Лучше использовать для этого гибкие много- жильные провода разного цвета. Провода должны быть достаточной длины, чтобы не только достать до платы драйвера двигателей, но и быть аккуратно уложенными. Оставьте для них длину 12-15 см, при монтаже к плате драйвера лишнее можно бу- дет отрезать. При пайке, если контакты двигателя сильно окислились и не поддаются лужению, их следует немного почистить острым ножом — это ускорит процесс пайки. Но не пере- старайтесь, контакты можно сломать! Рис. 6.5. Двигатель с припаянными проводами
Сборка базовой модели 87 Я настоятельно рекомендую при креплении проводов к двигателю использовать именно пайку, но если она для вас недоступна, можно снять изоляцию с конца про- вода, конец без изоляции тщательно скрутить и продеть в ушко контакта двигателя, после чего продетый конец обмотать вдоль той неизолированной части провода, ко- торая осталась до ушка контакта. Для исключения электромагнитных наводок, которые возникают при работе дви- гателей и могут стать причиной сбоев в работе электроники робота, следует между контактами каждого электрического двигателя впаять керамический конденсатор (рис. 6.6). Электромагнитные наводки могут влиять на радиоприем — например, если поднести радиоприемник к работающему двигателю, то ничего, кроме помех, слышно не будет. Конденсатор же, благодаря своим свойствам, поглощает подобные высокочастотные скачки электрического напряжения. Для напряжения 5-12 В и ис- пользуемых маломощных моторов достаточно конденсатора емкостью 100 нФ. Для установки двигателей в корпус робота применяются Т-образные элемен- ты (рис. 6.7), которые устанавливаются снизу корпуса в пазы (рис. 6.8). Каждый Рис. 6.6. Двигатель с припаянными проводами и конденсатором 4 I Рис. 6.7. Монтажный комплект двигателя: пластина корпуса робота (1); Т-образный элемент (2); двигатель (3); крепежные винты и гайки (4)
88 Глава 6 двигатель можно закрепить как на одном, так и на двух Т-образных элементах (пред- почтительнее все же на двух). Этапы установки двигателя на одном Т-образном эле- менте показаны на рис. 6.9-6.13. Двигатели, как можно видеть, крепятся двумя бол- тами в специальные крепежные отверстия Т-образного элемента. Рис. 6.8. Установка Т-образных креплений в паз пластины корпуса робота Рис. 6.9. Монтаж двигателя- этап I
Сборка базовой модели 89 Рис. 6.10. Монтаж двигателя: этап II Рис. 6.11. Монтаж двигателя: этап III Рис. 6.12. Монтаж двигателя завершен
90 Глава 6 Рис 6.13. Все двигатели смонтированы Драйвер двигателей После установки двигателей следует установить плату, содержащую драйвер двига- телей (типа L298N). Плата крепится двумя болтами в отверстия на корпусе (рис. 6.14 и 6.15).
Сборка базовой модели 91 Рис. 6.14. Монтаж платы драйвера: установка %. Рис. 6.15. Монтаж платы драйвера: крепление
92 Глава 6 Соединение платы драйвера и двигателей Пояснения к установке и настройке платы драйвера L298N представлены на рис. 6.16. Внимание! Важно соблюдать указанный на рис. 6.16 порядок подключения! Все программы управле- ния движением робота, приведенные в этой книге, ориентированы именно на такую схему. Если вы при монтаже поменяете местами двигатели и контакты управления, вам придется самостоятельно вносить изменения в управляющие программы по всей книге, что может привести к путанице. OUT1 и OUT2 подключаем к двигателям правой стороны робота, OUT3 и OUT4 - к двигателям его левой стороны. Клемма +12V подключается к основному электро- питанию робота, клемма GND («земля») — к отрицательному выводу источника питания (в дальнейшем для всех используемых приборов контакты GND должны быть объединены). Клемма +5V будет использована для электропитания датчиков OUT1 и OUT2 подключаются к двигателям правой стороны OUT3 и OUT4 подключаются к двигателям левой стороны От положительного (+) контакта источника питания (+7,2- 12В) Перемычки следует разомкнуть От отрицательного (-) контакта источника питания (земля - GND), этот контакт можно использовать для подключения GND датчиков и иных внешних устройств Выход +5В, (VCC) отсюда будем питать датчики и пр дополнительные устройства требующие электропитания 5В Вход включения/ отключения управления скоростью двигателей правой стороны IN1.IN2- управление направлением вращение двигателей правой стороны Вход включения/ отключения, управления скоростью двигателей левой стороны IN3, IN4- управление направлением вращение двигателей левой стороны Рис. 6.16. Вид платы драйвера L298N с пояснениями
Сборка базовой модели 93 и других маломощных, но требующих стабилизированного электропитания устройств, от нее рекомендуется вывести провод, чтобы не разбирать робота каж- дый раз, когда требуется подключить питание к новому устройству. Перемычки ENA и ENB включают или отключают двигатели, а также при помощи широтно-импульс- ной модуляции через них можно управлять скоростью вращения колес. Проверка правильности подключения платы драйвера и двигателей Такую проверку для уверенности лучше расписать по шагам: 1. Прежде всего убедитесь, что установлены перемычки ENA и ENB, разрешающие включение двигателей. 2. Подайте питание от БП на плату драйвера: «плюс» — на +12V, «минус» — на GND. Должен загореться светодиод. 3. Отдельным проводом (удобно использовать провод от тестера) кратковременным прикосновением подайте «плюс» от БП на OUT1 — правые двигатели должны начать вращаться. Если что-то пошло не так, проверьте соединения и контакты. Двигатели также должны вращаться в одном направлении. Если вращение про- исходит в разных направлениях — проверьте правильность объединения пра- вых двигателей в пару и объедините правильно. Кроме того, обратите внимание, что при подаче «плюса» на OUT1 колеса должны вращаться назад, а при подаче «плюса» на OUT2 — вперед. Если происходит об- ратное — поменяйте местами подводимые к колесам провода. 4. Так же проверьте и настройте левые двигатели. При подаче «плюса» на OUT4 левые колеса должны вращаться вперед, а при подаче «плюса» на OUT3 — назад. 5. Снимите перемычки ENA и ENB — в дальнейшем мы будем подавать разрешение на включение двигателей программно с платы Arduino. Контакты INI, IN2, IN3, IN4 управляют подачей электропитания на соответствую- щие по номерам выводы OUT1, OUT2, OUT3, OUT4. Например, подача логическо- го нуля на IN1 подключит OUT1 на «землю» (GND), а подача логической единицы на IN2 подключит OUT2 к положительному контакту электропитания (обозначен на рис. 6.16 как +12V). Это вызовет вращение подключенного двигателя, если же на IN1 подать логическую единицу, а на IN2 — ноль, то вал двигателя начнет вращаться в противоположную сторону (подробнее об этом см. в главе 5). Провода от двигателей соединяются с платой драйвера через винтовой зажим (рис. 6.17).
94 Глава 6 Учтите также, что каждый выход L298N будет управ- лять сразу парой двигателей, подключенных параллель- но, и, перепутав полярность, можно получить колеса, вра- щающиеся в разные стороны! Для соблюдения полярности рекомендую к контактным площадкам, расположенным ближе к корпусу, припаять по черному проводу, а к верх- ним — по белому. Контактные площадки передних и задних двигателей перевернуты от- носительно друг друга (это видно на рис. 6.15), поэто- му следует при подключении к драйверу черный и белый провода от разных двигателей одной стороны объединить (см. рис. 6.17). Порядок подключения прово- дов от первой пары двигате- лей к контактам OUT1-OUT2 и OUT3-OUT4, конечно, име- Рис. 6.17. Провода от двигателей присоединены к плате драйвера ~ ет значение. В нашем случае: • верхний контакт переднего правого двигателя и нижний контакт заднего правого двигателя следует подключить к OUT1; • нижний контакт переднего правого двигателя и верхний контакт заднего правого - к OUT2; • верхний контакт переднего левого двигателя и нижний контакт заднего левого двигателя следует подключить к OUT3; • нижний контакт переднего левого двигателя и верхний контакт заднего левого — к OUT4. Важно! Обратите внимание - контактные площадки всех двигателей должны быть направлены к центру ходовой части. Чтобы провода не болтались, удобно прикрепить их к корпусу клеем (клеевым пи- столетом) либо стяжками.
Сборка базовой модели 95 Подключение платы драйвера к контроллеру Arduino Теперь, согласно схеме, изображенной на рис. 6.16, надо соединить драйвер и кон- троллер Arduino (можно также воспользоваться схемой соединений на рис. 6.18 — соединение драйвера и Arduino показано здесь разноцветными проводами). Сначала присоедините провода к плате драйвера двигателей. Используйте для соеди- нения провода разного цвета, как показано на рис. 6.18. После соединения запишите для себя на бумаге, какого цвета провод к какому контакту платы драйвера подклю- чен, — это поможет избежать путаницы. Провода можно паять или использовать Правая пара Левая пара двигателей робота двигателей робота Порядок подключения к Arduino соответствует программной реализации Рис. 6.18. Соединение Arduino и платы драйвера
96 Глава 6 клеммы. Перемычки ENA и ENB должны сейчас быть разомкнуты — если оставить их замкнутыми, управление скоростью двигателей при помощи ШИМ станет невоз- можным. Если вы еще не очень хорошо паяете, то рекомендую использовать провода с клеммами, которые быстрее в монтаже. Присоединив провода к плате драйвера, можно приступать к монтажу верхней части корпуса. А сами провода через технологические отверстия пластины корпуса выве- сти наверх, так как они должны быть подсоединены к плате Arduino, которая монти- руется позже. Верх корпуса Соберите верхнюю часть корпуса — она потребуется для размещения элементов питания, платы Arduino и различных дополнительных элементов. Чтобы избежать частой разборки корпуса для доступа к плате драйвера двигателей, можно заранее присоединить три провода к клеммам платы драйвера 12V, GND и 5V, на клемму 12V подать красный провод, на GND —черный. 5V используется для электропитания сервоприводов, датчиков и иных дополнительных устройств. Плата Arduino имеет преобразователь на 5 вольт, но использовать его крайне рискованно, так как можно его перегрузить или закоротить, что приведет к выходу из строя всей платы. Крепление верхней части корпуса осуществляется с помощью бронзовых стоек, за- крепляемых на винты (рис. 6.19-6.22). На верхнюю часть корпуса монтируется плата Arduino (рис. 6.23). Прикрепить ее к корпусу можно либо парой винтов, либо стяж- ками. Рис. 6.19. Установка стойки
Сборка базовой модели 97 Рис. 6.20. Низ корпуса с установленными стойками Рис. 6.21. Установка верхней части корпуса на стойки
98 Глава 6 Рис. 6.22. Вид корпуса с установленным верхом Рис. 6.23. Монтаж платы Arduino UNO на корпус робота
Сборка базовой модели 99 Выключатель Выключатель электропитания устанавливается защелкиванием в соответствующее (подходящее) отверстие корпуса (рис. 6.24). Рис. 6.24. Монтаж выключателя Бокс для элементов питания Бокс для элементов питания прикручивается винтами с потайной головкой к отвер- стиям в корпусе (рис. 6.25-6.26). Если подобных винтов нет, можно воспользоваться клеем. Рис. 6.25. Монтаж бокса для элементов питания 18650
100 Глава 6 Рис. 6.26. Вид корпуса с установленным боксом для элементов питания Драйвер двигателя Рис. 6.27. Электропитание Arduino и платы драйвера двигателей
Сборка базовой модели 101 Подключение электропитания Для правильного подключения электропитания положительный контакт от бокса элементов питания должен быть подключен через выключатель (рис. 6.27). Полная схема электропитания робота приведена на рис. 6.28. Для питания дополнительных элементов, таких как датчики, следует задействовать контакт 5 В платы драйвера двигателей L298D. Если провода электропитания еще не подключены к плате драйвера двигателей, тре- буется сделать это прямо сейчас, а если подключать электропитание окажется не- удобно, не поленитесь и демонтируйте верхнюю часть корпуса, — в процессе экспе- риментов с роботом эту операцию придется делать регулярно. Теперь пришло эремя подвести питание и управление к плате Arduino (см. рис. 6.18, 6.27 и 6.28). Нестабилизированное электропитание к контроллеру Arduino можно S1 Arduino Arduino Uno (Rev3) ICSP Элемент питания 12 Рис. 6.28. Схема электропитания Arduino и драйвера двигателей
102 Глава 6 подключить клеммами (как показано на рис. 6.27) или пайкой, подпаяв положитель- ный провод от тумблера (выключателя) к центральному контакту разъема питания Arduino (Arduino UNO), а отрицательный — к боковому его контакту (рис. 6.29). Для Arduino UNO можно также использовать и специальный разъем питания (рис. 6.30). положительный контакт отрицательный контакт Рис. 6.29. Места для монтажа пайкой электрического питания для Arduino UNO Рис. 6.30. Контактный разъем электропитания для платы Arduino UNO
Сборка базовой модели 103 Укладка проводов Когда к роботу полностью подведено питание и управление, он покрывается воро- хом незакрепленных проводов. Болтающиеся провода, как правило, зацепляются, что приводит к их отсоединению или обрыву. Во избежание таких проблем провода нужно объединять и укладывать. Это удобно делать при помощи маленьких стяжек или изоленты (рис. 6.31). Можно также использовать термоклей — для этого на кор- пус переносится капля термоклея, а затем в нее утапливаются провода. Если потом провода потребуется освободить, то термоклей нужно нагреть до 200 градусов. Рис. 6.31. Укладка проводов стяжками
104 Глава 6 Выводы Робот собран. Теперь следует сделать его контрольный осмотр, проверить, нет ли оторванных проводов, надеть колеса (рис. 6.32) и приступать к написанию первой программы, крторая научит робота пользоваться моторами, совершать прямолиней- ное движение и повороты, а также выявит все неустраненные ошибки сборки, чем мы и займемся в следующей главе. Про поиск и устранение ошибок сборки написано в главе 9, и вы можете изучить ее до установки вращающейся головы робота, которой посвящена глава 8. Рис. 6.32. Базовая модель робота в сборе
ГЛАВА 7 СХЕМА УПРАВЛЕНИЯ ДВИЖЕНИЕМ Сборка робота закончена, но для того чтобы заставить его двигаться, нам нужно со- здать программу, отвечающую за его движения. Переменные и функции управления моторами Для управления моторами надо включить в нашу программу 6 целочисленных гло- бальных переменных (табл. 7.1) — они будут отвечать за включение и отключение моторов, а также за направление вращения колес. Таблица 7.1. Переменные управления моторами Переменная motor L1 motor L2 input L motor Rl motor_R2 input R Назначение (3 - IN4) (4 - IN3) ШИМ левого двигателя (11 - ENB) (7 - IN2) (8 - INI) ШИМ правого двигателя (10 - ENA) Создадим также следующие базовые функции: • setupmotorsystem — для присвоения глобальным переменным значений с номерами портов Arduino и перевода используемых портов в режим вывода данных; • setspeed — для удобного управления скоростью и мощностью с помощью ШИМ.
106 Глава 1 Функции движений Для управления роботом нам также потребуются функции, управляющие его движе- нием. Дадим им названия и закрепим за ними определенные действия (табл. 7.2). Функция forward() forward left() forward right () backward() _stop() Назначение Включает движение вперед Поворот налево с бло- кировкой левых колес Поворот направо с бло- кировкой правых колес Включает движение назад Остановка Таблица 7.2. Функции движений Выставляемые значения на портах motor L1 1 0 1 0 0 motor_L2 0 0 0 1 0 motorRl 1 1 0 0 0 motor_R2 0 0 0 1 0 Первая поездка Для проверки работоспособности собранного робота нужно записать в него простую программу с определенной последовательностью движений. Созданные нами функ- ции только включают моторы с заданными параметрами, но не позволяют управ- лять длительностью процесса. Поэтому нам следует позаботиться о том, чтобы после включения какой-либо функции, например forward о, прошло некоторое время до включения следующей. За это время робот, отрабатывая поданную на него команду, каким-то образом сместится. Естественно, что от времени, в течение которого вы- полняется движение, зависит величина самого движения: если это поворот, то уве- личение времени увеличит угол поворота, а если это движение вперед, то увеличится пройденное расстояние. Алгоритм Рисунок 7.1 демонстрирует небольшой линейный (в нем нет условных операторов) алгоритм тестовых движений робота. Согласно этому алгоритму, робот начинает двигаться, совершает повороты и проезды, а после выполнения всех команд начи- нает все сначала.
Схема управления движением 107 ▼ 1 ▼ 1 1 i * 1 Рис. 7.1. Линейный алгоритм тестовых движений робота Программа Напишем в соответствии с приведенным алгоритмом небольшую тестовую програм- му (листинг 7.1), которая осуществляет в цикле несколько видов движений. Ее цель — проверить, что все сделано правильно, и колеса вращаются в нужном направлении.
108 Глава 7 Листинг 7.1. Тестовая программа движений робота // Объявляем переменные для хранения состояния двух моторов. int motor LI, motor L2, input L; int motor_Rl, motor_R2, input_R; void setup() { // Переменные - номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели остановлены. setspeed(0, 0); } // Основная программа, void loop () { // Пример движения робота задан жестко в программе //и повторяется в цикле. setspeed(255, 255); // устанавливает макс, скорость колес, forward(); // едет вперед 1 секунду. delay(lOOO); forward_left(); // поворачивает налево 0,5 секунд, delay(500); forward(); // едет вперед 0,5 секунд, delay(500); forward_right(); // поворачивает направо 0,5 секунд, delay(500); _stop() ; delay(500); backwardO; // движется назад 0,8 секунд, delay(800); } // Функция инициализации управления моторами. void setup_motor_system(int LI, int L2, int iL, int Rl, int R2, int iR) { // Заносятся в переменные номера контактов (пинов) Arduino. motor_Ll=Ll; motor_L2=L2; input_L=iL; // Для левых и правых моторов робота. motor_Rl=Rl; motor_R2=R2; input_R=iR; // Переводятся указанные порты в состояние вывода данных.
Схема управления движением 109 pinMode(motor_Ll, OUTPUT); pinMode(motor_L2, OUTPUT); pinMode(input_L, OUTPUT); pinMode(motor_Rl, OUTPUT); pinMode(motor_R2, OUTPUT); pinMode(input_R, OUTPUT); } // Функция задает скорость двигателя, void setspeed(int LeftSpeed, int RightSpeed) { // Задает ширину положительного фронта от 0 до 255. analogWrite(input L, LeftSpeed); analogWrite(input_R, RightSpeed); // Чем больше, тем интенсивнее работает мотор. } // Движение вперед, void forward() { // Если двигатель будет работать не в ту сторону, // поменять на нем контакты местами. digitalWrite(motor_Ll, HIGH); digitalWrite(motor_L2,LOW); digitalWrite(motorJRl, HIGH); digitalWrite (motor__R2, LOW) ; } // Поворот налево с блокировкой левых колес, void forward_left() { // блокировка вращения левых колес. digitalWrite(motor_Ll, LOW); digitalWrite(motor_L2, LOW); // правые колеса вращаются. digitalWrite(motor_Rl, HIGH); digitalWrite(motor_R2, LOW); } // Поворот направо с блокировкой правых колес, void forward_right() { // левые колеса вращаются. digitalWrite(motor_ LI, HIGH);
110 Глава 1 digitalWrite(motor_L2, LOW); // блокировка вращения правых колес. digitalWrite(motor_Rl, LOW); digitalWrite(motor_R2, LOW); } // Включаем движение назад, void backward() { // Смена направления вращения двигателей. digitalWrite(motor_L2, HIGH); digitalWrite(motorJLl,LOW); digitalWrite(motor_R2, HIGH); digitalWrite(motor_Rl,LOW); void _stop() { // Блокировка всех колес. digitalWrite(motor_L2, LOW) digitalWrite(motorJLl,LOW); digitalWrite(motor_R2, LOW) digitalWrite(motor_Rl,LOW); Выводы Робот научился исполнять команды, позволяющие ему двигаться и поворачивать. Таким образом, нами создана универсальная программа, на основании которой до- вольно просто сделать программу движений любой сложности, чередуя этапы вклю- чения определенных двигательных функций и времени, в течение которого они ра- ботают. Однако недостатком нашего робота является то, что он никак не реагирует на изме- нение внешней обстановки — не может обходить препятствия и не умеет что-либо анализировать. Причина этого в том, что анализировать ему пока нечего. И чтобы у него появился материал для анализа, требуется оснастить его хотя бы одним каким- либо датчиком. И станет этим датчиком ультразвуковой датчик расстояния, работу с которым мы рассмотрим в главе 9. Но прежде нам следует научиться управлять роботом дистанционно, опираясь на материал главы 8.
ГЛАВА 8 ДИСТАНЦИОННОЕ УПРАВЛЕНИЕ РОБОТОМ В этой главе мы научимся управлять роботом дистанционно, решая следующие за- дачи: • определение способов дистанционного управления роботами на плате Arduino; • обоснование выбора системы дистанционного управления; • подбор элементной базы и разработка схемы соединений; • подключение робота к системе дистанционного управления и тестирование его работы. Способы дистанционного управления Удаленное управление подвижным роботом возможно по разным каналам. В гла- ве 1 уже были упомянуты способы управления через инфракрасный канал, радио- канал с использованием стандарта Bluetooth и радиоканал на основе стандарта Wi- Fi. Возможно также управление роботом посредством специализированной системы управления, подобной используемой в качественных моделях летающих аппаратов (рис. 8.1). Нам необходимо выбрать решение не дорогое, но в то же время довольно эффек- тивное и не требующее сложного этапа проектирования и настройки. Дело в том, что при использовании дешевых систем радиоуправления можно столкнуться с про- блемой, когда недорогие радиоуправляемые модели путаются в командах из-за того, что воспринимают сигналы управления, направленные как к ним, так и к другим по- добным устройствам.
112 Глава8 Пулы управления Блок связи помещается в робота Рис. 8.1. Профессиональный пульт дистанционного управления спортивным роботом Выделим два приемлемых решения: управление по инфракрасному каналу (ИК/IR) и управление по Bluetooth. Управление по IR-каналу самое простое, и реализовать его можно, имея только IR-приемник (рис. 8.2), а в качестве пульта управления вос- пользоваться любым IP-пультом — например, от телевизора. Но IR-прием работает только в пределах прямой видимости, что делает управление роботом не очень эф- фективным. Управление роботом по Bluetooth лишено этого недостатка, но требует создания дополнительного устройства. Рис. 8.2. Инфракрасный приемник
Дистанционное управление роботом 113 Управление роботом по каналу инфракрасной связи Рассмотрим для начала пример управления роботом при помощи IR-пульта. Готовый набор IR-компонентов для использования с Arduino-роботами представлен на рис. 8.3. Подойдет нам также и любой инфра- красный пульт от телеви- зора или другой бытовой техники. Для приема инфракрас- ного сигнала требуется IR-приемник. Он мо- жет быть смонтирован на плате (рис. 8.4, а) — в этом случае у нас будет возможность визуально следить за приемом сиг- нала по миганию инди- катора. Можно также ис- пользовать IR-приемник без платы (рис. 8.4, б). Следует обратить внима- Рис. 8.3. IR-пульт {слева); плата IR-приемника {справа вверху); соединительные провода {справа внизу) ние' что контакты платы IR-приемника и контакты IR-приемника без платы не совпадают. . Выходной сигнал (на Arduino) VCC Напряжение питания 5В GND Отрицательный контакт питания (земля) \ Индикатор наличия сигнала Рис. 8.4. а — плата IR-приемника; б — IR-приемник без платы Выходной сигнал (на Arduino) VCC Напряжение питания 5В "~ GND Отрицательный контакт питания (земля)
114 Глава 8 Схема подключения Пример подключения IR-приемника, уже установленного на плате, приведен на рис. 8.5. Питание подано от платы Arduino, но можно подать его и от другого источ- ника стабилизированного электропитания 5 В. На плате приемника (см. рис. 8.4, а) левый контакт обозначен символом «-» — это «земля» (GND), правый контакт обо- значен символом «S» — это сигнальный контакт (Data), средний контакт на плате не обозначен — это напряжение питания (Vcc = 5 В). Рис 8.5. Подключение IR-приемника к Arduino UNO Рекомендации по установке Располагаться IR-приемник должен таким образом, чтобы быть в прямой видимости от пульта управления. На роботе это место не должно ничем перекрываться. В случае использования IR-приемника без платы рекомендуется для уменьше- ния помех и ложного срабатывания установить дополнительный фильтр питания (рис. 8.6).
Дистанционное управление роботом 115 [На контроллер^»— Рис. 8.6. Фильтр помех для IR-приемника Установка расширенной библиотеки С Arduino IDE уже поставляется библиотека для работы с IR-приемником, но она не содержит примеров. Чтобы посмотреть и попробовать типичные примеры работы с IR-приемником, нужно установить расширенную библиотеку. Для этого следует выполнить ряд действий: 1. Зайти на компьютере в папку, куда установлена программа Arduino. 2. В ЭТОЙ папке зайти В папку Libraries И удалить ИЗ нее папку RobotlRremote. 3. С сайта https://github.com/z3tO/Arduino-IRremote скачать ZIP-архив, содер- жащий обновленную библиотеку IRRemote.h. 4. Через меню Arduino IDE Скетч | Подключить библиотеку | Добавить .zip би- блиотеку выбрать загруженный В П. 3 файл Arduino-IRremote-master.zip. Если примеры работы с IR-приемником вам не интересны, можно использовать и встроенную библиотеку. При ЭТОМ следует удалить файлы IRemoteTools.cpp и IRemoteTools.h из папки RobotiRremote/src, иначе компиляция программы заканчивается ошибкой.
116 Глава 8 Получение кодов кнопок для используемого пульта После установки расширенной библиотеки у вас появятся примеры для управления роботом с помощью Ш-пульта. Выберите пример IRrecvDemo (рис. 8.7) — этот пример также приведен в листин- ге 8.1. Замените в коде примера строку int RECVPIN = 7; На int RECVPIN = 12;, поскольку наш IR-приемник подключен к 12-му порту (см. рис. 8.5). Теперь нужно запустить программу, открыть порт для просмотра кодов кнопок пульта и дополнить полученными кодами табл. 8.1. Для пульта, изображенного на рис. 8.3, коды кнопок приведены в табл. 8.2. Рис. 8.7. Выбор примера программы для тестирования IR-приемника Листинг 8.1. Проверка кодов кнопок пульта // Подключение библиотеки IRremote.h tinclude <IRremote.h> // Порт Arduino для приемника. int RECV_PIN = 12; // Создаем объект IR-приемник. IRrecv irrecv(RECV_PIN); // Создаем структуру результата приема данных IR-канала. decode results results;
Дистанционное управление роботом 117 void setup () // Устанавливаем скорость порта связи с ПК. Serial.begin(9600); // Запуск IR-приемника. irrecv.enablelRIn(); } void loop() { // Если пришли данные. if (irrecv.decode(^results)) { // Послать полученные данные на ПК в 16-ом представлении. Serial.println(results.value, HEX); // Готов к приему. irrecv.resume(); delay(lOO); Таблица 8.1. Функции движения робота и их назначение №п/п 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Функция forward() forward left () forward right() left() right() backward() backward left () backward right() setspeed(sL, sR) _stop () Назначение Движение вперед Поворот налево с блокировкой левых колес. Поворот применя- ется при движении вперед, при переключении от движения впе- ред к этому виду поворота не требуется остановка Поворот направо с блокировкой правых колес. Поворот приме- няется при движении робота вперед, при переключении от дви- жения вперед к этому виду поворота не требуется остановка Поворот налево на месте. Правые колеса вращаются вперед, левые назад Поворот направо на месте. Правые колеса вращаются назад, левые вперед Движение назад Поворот налево с блокировкой левых колес. Поворот применя- ется при движении задним ходом, при переключении от движе- ния назад к этому виду поворота не требуется остановка Поворот направо с блокировкой правых колес. Поворот приме- няется при движении задним ходом, при переключении от дви- жения назад к этому виду поворота не требуется остановка Функция задает скорость вращения колес, sL — для левых ко- лес, sR — для правых колес. Значения могут изменяться от 0 до 255.0 — полная остановка, 255 — полная мощность Остановка, при этом заданная ранее скорость вращения колес функцией setspeed () останется в памяти робота
118 Глава 8 Таблица 8.2. Соответствие кнопок пульта, изображенного на рис. 8.3, действиям робота Название кнопки пульта Стрелка вверх Стрелка влево Стрелка вправо «Ok» Стрелка вниз « 1 » « 2 » « 3 » «4» « 5 » « 6 » « 7 » «8» «9» «0» « * » « # » Код кнопки FF629D FF22DD FFC23D FF02FD FFA857 FF6897 FF9867 FFB04F FF30CF FF18E7 FF7A85 FF10EF FF38C7 FF5AA5 FF4AB5 FF42BD FF52AD Действие Двигаться вперед Поворот влево Поворот вправо Стоп Двигаться назад Поворот влево при движении вперед Двигаться вперед Поворот вправо при движении вперед Поворот влево Стоп Поворот вправо Поворот влево при движении назад Двигаться назад Поворот вправо при движении вперед Стоп Стоп Стоп Вызываемая функция forward() left() rightO _stop() backward() forward left() forward() forward right() left() _stop() rightO backward left 0 backward() backward rightO _stop () _stop() _stop() Программа Программа для робота предусматривает, что данные принимаются с Ш-датчика, коды, генерируемые пультом при нажатии той или иной кнопки, взяты из табл. 8.2, принятые коды анализируются на совпадение, и при совпадении запускается та или иная функция (см. табл. 8.1). Текст программы приведен в листинге 8.2. Обратите внимание, что в этом листин- ге представлены все функции управления моторами. В рассматриваемых далее лис- тингах функции управления моторами приводиться не будут — их следует брать из листинга 8.2. Следует учесть, что если кнопки не нажаты, пульт не генерирует никакого сигнала, и эту ситуацию требуется обработать. Робот отслеживает время последнего нажатия кнопки и останавливается через 0,3 секунды, если кнопка не нажата повторно. Если коды кнопок вашего пульта отличаются от приведенных в программе, их следует скорректировать (они записаны после ключевых слов case).
Дистанционное управление роботом 119 Листинг 8.2. Программа управления роботом с помощью IR-пульта #include <IRremote.h> // Порт для IR-приемника. mt RECV_PIN =12; // Создание IR-приемника. IRrecv irrecv(RECV_PIN); // Переменная для результатов IR-приемника. decode_results results; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor_Rl, motor_R2, input_R; // Хранит время последнего нажатия кнопки. unsigned long _time; void setup () { // Заносим в переменные номера контактов (пинов) Arduino // для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели запущены. setspeed(255, 255); // Запуск IR-приемника. irrecv.enablelRIn(); _time = millis(); _stop() ; } // Основная программа, void loop () { if (irrecv.decode(&results)) { _time = millisO; switch (results.value) { // Вперед case 0xFF629D:
120 Глава 8 forward(); break; // Назад case 0xFFA857: backward () ; break; // Влево case 0xFF22DD: left(); break; // Вправо case 0xFFC23D: right(); break; // Вперед case 0xFF9867: forward(); break; // Назад case 0xFF38C7: backward () ; break; // Влево case 0xFF30CF: left(); break; // Вправо case 0xFF7A85: right(); break; // Прямо и влево case 0xFF6897: forward_left(); break; // Прямо и вправо case 0xFFB04F:
Дистанционное управление роботом 121 forward_right(); break; // Назад и влево case OxFFlOEF: backward_left() ; break; // Назад и вправо case 0xFF5AA5: backward_right(); break; // Стоп case 0xFF02FD: _stop() ; break; case 0xFF18E7: _stop(); break; case 0xFF4AB5: _stop(); break; case 0xFF42BD: _stop() ; break; case 0xFF52AD: _stop(); break; } irrecv.resume(); } // Если никакая клавиша не нажата более 0.3 сек., то остановка, if((millis()-_time)>300) {_stop();}; } / / // Функция инициализации управления моторами. void setup_motor system(int LI, int L2, mt iL, int Rl, int R2, int iR)
122 Глава 8 // Заносим в переменные номера контактов (пинов) Arduino. motor_Ll=Ll; motor_L2=L2; input_L=iL; // Для левых и правых моторов машинки. motor_Rl=Rl; motor_R2=R2; input_R=iR; // Переводим указанные порты в состояние вывода данных. pinMode(motor_Ll, OUTPUT); pinMode(motor_L2, OUTPUT); pinMode(input_L, OUTPUT); pinMode(motor_Rl, OUTPUT); pinMode(motor_R2, OUTPUT); pinMode(input_R, OUTPUT); } // Функция задает скорость двигателей, void setspeed(int LeftSpeed, int RightSpeed) { // Задаем ширину положительного фронта от 0 до 255. analogWrite(input_L, LeftSpeed); analogWrite(input_R, RightSpeed); // Чем больше, тем интенсивнее работает мотор. } // движение вперед, void forward() { // Если двигатель будет работать не в ту сторону, // поменять на нем контакты местами. digitalWrite(motor_Ll, HIGH); digitalWrite(motor_L2,LOW); digitalWrite(motor_Rl, HIGH); digitalWrite(motor_R2,LOW); } // Поворот налево с блокировкой левых колес, void forward_left() { // блокируем вращение левых колес. digitalWrite(motor_Ll, LOW); digitalWrite(motor_L2, LOW);
Дистанционное управление роботом 123 // правые колеса вращаются. digitalWrite(motor_Rl, HIGH); digitalWrite(motor_R2, LOW); } // Поворот налево, void left() { // левые колеса вращаются назад digitalWrite(motor_Ll, LOW); digitalWrite(motor_L2, HIGH); // правые колеса вращаются. digitalWrite(motor_Rl, HIGH); digitalWrite(motor_R2, LOW); } // Поворот направо с блокировкой правых колес, void forward_right() { // левые колеса вращаются. digitalWrite(motor_Ll, HIGH); digitalWrite(motor_L2, LOW); // блокируем вращение правых колес. digitalWrite(motor_Rl, LOW); digitalWrite(motor_R2, LOW); } void right() { // левые колеса вращаются. digitalWrite(motor_Ll, HIGH); digitalWrite(motor_L2, LOW); // правые колеса вращаются назад. digitalWrite(motor_Rlt LOW); digitalWrite(motor_R2, HIGH); } // Включаем движение назад, void backward ()
124 Глава 8 // Меняем направление вращения двигателей. digitalWrite(motor_L2, HIGH); digitalWrite(motor_Ll,LOW); digitalWrite(motor_R2, HIGH); digitalWrite(motor_Rl,LOW); } void backward_left() { // Меняем направление вращения двигателей. digitalWrite(motor_L2, LOW); digitalWrite(motor_Ll,LOW); digitalWrite(motor_R2, HIGH); digitalWrite(motor_Rl,LOW); } void backward_right() { // Меняем направление вращения двигателей. digitalWrite(motor_L2, HIGH); digitalWrite(motor_Ll,LOW); digitalWrite(motor_R2, LOW); digitalWrite(motor_Rl,LOW); } void _stop() { // Блокируем все колеса. digitalWrite(motor_L2, LOW); digitalWrite(motor_Ll,LOW); digitalWrite(motor_R2, LOW); digitalWrite(motor Rl,LOW); //=
Дистанционное управление роботом 125 Управление роботом по каналу Bluetooth Для связи с роботом по Bluetooth потребуется установить на него контроллер Bluetooth. Тогда управлять роботом можно будет со смартфона на операционной си- стеме Android. В магазине приложений для Android-устройств Google Play Маркет есть достаточное количество бесплатных приложений, реализующих функции управ- ления колесными роботами (рис. 8.8). Рис. 8.8. Программы управления роботами на Google Play Маркет (смартфоны на Android) Подбор элементной базы В качестве Bluetooth-контроллера робота мы применим недорогой модуль НС-05 (рис. 8.9). Питание 5 В подается на его контакты VCC и GND. Для работы на переда- чу и прием используются контакты RXD и TXD, на плате Arduino робота потребуется задействовать для работы с этим Bluetooth-контроллером два свободных порта.
126 Глава 8 Индикатор состояния у- , STATE контакт индикации состояния Индикатор питания / TXD контакт последовательной шины / / RXD контакт последовательной шины /у GND Отрицательный контакт питания (земля) ^— VCC Напряжение питания 3,6 -5В "^■^ EN контакт включение/выключение модуля Рис. 8.9. Модуль НС-05 приемопередачи по Bluetooth 34 контакт Рис. 8.10. Подключение контроллера Bluetooth НС-05 к Arduino UNO с контактом для модификации имени
Дистанционное управление роботом 127 Подключение к Arduino Обычно модуль НС-05 подключается на стандартные входы последовательного пор- та DO и D1 — на плате Arduino они обозначены как RX и ТХ. Но эти же входы исполь- зуются при программировании робота, поэтому каждый раз при проведении про- цедуры программирования вам придется отсоединять Bluetooth-контроллер, иначе он будет мешать обмену информацией между компьютером и Arduino. Поэтому пра- вильнее использовать специальную библиотеку эмуляции последовательного порта и подключить контроллер на любые свободные входы Arduino (D2-D12 или АО-АЗ). Выберем D2 и D12. Подключение должно быть перекрестным: RXD контроллера подключается к ТХ Arduino, a TXD контроллера — к RX Arduino. Контакты RXD и RX читают данные, a TXD и ТХ их передают, — соответственно, в паре соединенных кон- тактов один должен быть передающим, а другой — читающим. Это нужно будет учесть при создании последовательного порта в программе робота. Порядок соединения I приведен на рис. 8.10, а схема — на рис. 8.12. Так как приемопередат- чик НС-05 потребля- ет относительно много энергии, электропита- ние для него следует получать от отдельного источника, — в нашем случае это стабилизатор платы драйвера двигате- лей (рис. 8.11). Теперь, если включить робота, на смартфоне появит- ся новое Bluetooth- устройство - оно будет называться НС-05. Рис. 8.11. Электропитание контроллера Bluetooth НС-05
128 Глава 8 7 2V RESET RESET2 AREF IOREF АО A1 A2 A3 A4 A5 N/C Arduino Uno (Rev3.0) о о DO/RX D1/TX D2 D3PWM D4 D5PWM D6PWM D7 D8 D9PWM D10PWM/SS D11 PWM/MOSI D12/MISO D13/SCK ICSP2 MISO ICSP2 SCK ICSP2 MOSI 5V Рис. 8.12. Принципиальная схема подключения контроллера Bluetooth HC-05 к плате Arduino Смена имени робота НС-05 — не очень оригинальное название, но оно прошито внутри модуля НС-05, и его можно изменить. Перепрошивка НС-05 возможна только при наличии логи- ческой единицы на его 34-м контакте. Для подачи такой логической единицы по- требуется присоединить к контакту 34 НС-05 (см. рис. 8.10) свободный порт кон- троллера Arduino — пусть это будет порт АО. Согласно инструкции на Arduino UNO, порты А0-А7 являются аналоговыми приемниками, но А0-А5 могут также работать и в двоичном режиме как для чтения, так и для вывода информации. Контакт 34 рас- положен довольно близко к 33-му контакту — паяйте осторожно! После изменения имени робота контакт 34 можно будет освободить. Программа переименования робота для описанных настроек (используемых пор- тов) приведена в листинге 8.3. Новое имя присваивается роботу в строке BTSeriai.
Дистанционное управление роботом 129 printin («AT+NAME=MaxiBot»), здесь это имя MaxiBot. Придумайте и задайте имя сво- ему роботу латинскими буквами без пробелов. Проверьте результат прошивки, проведя поиск новых устройств Bluetooth на смарт- фоне. Листинг 8.3. Переименование робота и проверка работы Bluetooth // Подключаем библиотеку для работы с Serial через дискретные порты tinclude <SoftwareSerial,h> // Создаем последовательный порт на пинах 12 и 2 SoftwareSerial BTSerial(12, 2); // RX, TX // Переменная для приема данных по Bluetooth char bt_input; // Настройка void setup () { // Устанавливаем скорость передачи данных по Bluetooth BTSerial.begin(9600); // Переключаем АО в двоичный режим работы, на передачу pinMode(14, OUTPUT); // Переводим НС-05 в режим АТ-команд digitalWrite(14,l); // Присваиваем НС-05 новое имя - MaxiBot BTSerial.printin("AT+NAME=MaxiBot"); // Устанавливаем скорость передачи данных по кабелю Serial.begin(9600); // Переводим НС-05 в нормальный режим работы digitalWrite(14, 0); } void loop() { // Если пришли данные по Bluetooth if (BTSerial.available()) { // Записываем, что пришло по Bluetooth в переменную bt_input bt_input = (char)BTSerial.read(); Serial.printin(bt_input);
130 Глава 8 Настройка смартфона Для управления роботом по каналу Bluetooth вам потребуется смартфон на опера- ционной системе Android и программа удаленного управления. Неплохим выбором может стать программа Arduino Bluetooth RC Car. Она хорошо документирована и неплохо зарекомендовала себя в тестах. Установите ее с Google Play Маркет на смартфон. Интерфейс программы приведен на рис. 8.13. Рис. 8.13. Главное окно программы Arduino Bluetooth RC Car Чтобы подключиться к роботу, следует нажать на кнопку в виде шестеренки, акти- вировать Bluetooth, после чего выбрать пункт Connect (рис. 8.14). Если робот уже прописан в устройствах смартфона, нужно будет выбрать его из меню, в противном случае произвести новое сканирование и подключить робота. Пароль по умолчанию у НС-05 «1234», — это может потребоваться! Рис. 8.14. Выбор Bluetooth-устройства
Дистанционное управление роботом 131 Когда робот соединится со смартфоном, интерфейс программы изменится: серая лампочка слева вверху станет зеленой, а в верхнем правом углу появится имя робота, к которому подсоединен смартфон (рис. 8.15). Рис. 8.15. Соединение установлено Устранение радиопомех Когда речь идет о работе по радиоканалу, возникают проблемы, связанные с элек- тромагнитной совместимостью. В главе 6 уже рассматривался вопрос защиты робо- тов от помех, создаваемых собственными электромоторами. И здесь установка мо- дуля НС-05 рядом с сервомотором головы, создающим радиопомехи, может приво- дить к частым обрывам связи. Лучше всего, если модуль НС-05 будет расположен на небольшой антенне и подальше от двигателей. При этом, если на все моторы будут установлены рекомендованные в главе 6 защитные конденсаторы, радиус связи ва- шего робота значительно увеличится, и обрывы связи сократятся. Программа Программа управления роботом по каналу Bluetooth весьма проста: робот посто- янно проверяет наличие на последовательном порту НС-05 команд. Если команды есть — изменяет свои действия в зависимости от того, какой байт пришел. Если ни- какие кнопки на смартфоне не нажимать, он все равно отправляет команду, а именно букву «S», которую наш робот интерпретирует как остановку. Приведенная в листинге 8.4 программа позволяет роботу поворачивать на полном ходу, используя принцип блокировки колес со стороны поворота. Если же робот сто- ит, то он поворачивает всеми колесами, — при этом правые и левые вращаются в разные стороны. Робот может поворачивать и при езде задним ходом. Кроме того,
132 Глава 8 программа Arduino Bluetooth RC Car дает возможность управлять роботом посред- ством изменения ориентации смартфона в пространстве. Кроме заявленных функций, программа Arduino Bluetooth RC Car позволяет, напри- мер, включать и отключать фары, если включение фар предусмотрено конструкцией робота. Подробнее прочитать о том, какие символы-команды посылает смартфон роботу, можно на странице помощи в программе управления на смартфоне. Листинг 8.4. Управление роботом по Bluetooth-каналу // Подключаем библиотеку для создания дополнительных последовательных (Serial) портов. #include <SoftwareSerial,h> // Создаем последовательный порт на пинах 12 - чтение и 2 - передача. SoftwareSerial BTSerial(12, 2); // RX, TX // Переменная для приема данных по Bluetooth. char bt_input; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor Rl, motor R2, input R; void setup() { // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели запущены. setspeed(255, 255); // Устанавливаем скорость передачи данных для НС-05 (Bluetooth-модуль) BTSerial.begin(9600) ; // Переключаем АО в двоичный режим работы, на передачу. pinMode(16, OUTPUT); // Устанавливаем скорость передачи данных по кабелю. // Порт компьютера Serial.begin(9600); // переводим НС-05 в нормальный режим работы. digitalWrite(16, 0);
Дистанционное управление роботом 13 3 // Основная программа. void loop () { if (BTSerial.available()) { // Читаем команды и заносим их в переменную, char преобразует // код символа команды в символ. bt_input = (char)BTSerial.read(); // Отправляем команду в порт, чтобы можно было //их проверить в "Мониторе порта". Serial.println(bt_input); switch (bt_input) { // Вперед case fF': forward(); break; // Назад case 'B': backward(); break; // Влево case 'L': left(); break; // Вправо case 'R': right(); break; // Прямо и влево case 'G1: forward_left(); break; // Прямо и вправо case 'Г: forward_right(); break; // Назад и влево case 'H1:
134 Глава 8 backward_left(); break; // Назад и вправо case 'J1: backward right (); break; // Стоп case 'Sf: __stop() ; break; // Скорость 01 case '01: setspeed(0, 0); break; // Скорость 10°о case '1': setspeed(25, 25); break; // Скорость 20% case '2': setspeed(50, 50); break; // Скорость 30°э case f3f : setspeed(75, 75); break; // Скорость 40е- case '4': setspeed(100, 1C0); break; // Скорость 50o case '5': setspeed(125, 125); break; // Скорость 60 о case '6': setspeed(150, 150); break;
Дистанционное управление роботом 13 5 // Скорость 70% case '7 ' : setspeed(175, 175); break; // Скорость 80% case f8': setspeed(200, 200); break; // Скорость 90% case '91: setspeed(225, 225); break; // Скорость 100% case 'qf: setspeed(255, 255); break; case 'X': //switch rejim = 1; break; case 'x1: //switch_rejim = 0; break; case 'D': _stop(); //switch_rejim = 0; break; / / // Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2. Основные проблемы, которые могут возникнуть при подключении контроллера Bluetooth, связаны с электромагнитной несовместимостью и невнимательностью. Если контроллер Bluetooth НС-05 не изменяет свое имя с первого раза, следует сде- лать повторную попытку.
136 Глава 8 Принцип управления роботом по каналу Bluetooth теперь должен быть вам понятен. Здесь не рассмотрен вопрос обратной передачи информации от робота и связи двух роботов между собой, но если вы успешно собрали и испытали рассмотренного до сих пор робота, то добьетесь остального самостоятельно. Выводы В этой главе проанализированы способы дистанционного управления роботами на платформе Arduino. Подробно рассмотрено управление роботом с помощью IR- канала и канала Bluetooth. Подобрана элементная база, разработаны схемы подклю- чения и программы управления как для Bluetooth, так и для IR-канала, — теперь ро- ботом можно управлять удаленно с любого IR-пульта (помните, что разные пульты генерируют разные последовательности). В следующей главе мы установим на нашего робота поворотную голову с датчиком расстояния до препятствия.
ГЛАВА 9 ПОВОРОТНАЯ ГОЛОВА Сделаем робота более интеллектуальным, поместив на него дальномер и научив реа- гировать на изменение его показаний. Ультразвуковой дальномер HC-SR04 Чтобы робот мог определять расстояния до препятствий, причем в разных направ- лениях (а это может потребоваться при их объезде), мы оснастим его распростра- ненным, простым и надежным ультразвуковым дальномером HC-SR04 (рис. 9.1), установив его на сервомотор с углом поворота 0-180 градусов. В этой задаче мы задействуем на плате Arduino три свободных порта: один для управ- ления сервоприводом и два для определения расстояния посредством датчика НС- SR04. Рис. 9.1. Ультразвуковой дальномер HC-SR04 и детали для его крепления
138 Глава 9 Схема подключения Принципиальная схема подключения сервомотора и дальномера приведена на рис. 9.2. Рис. 9.2. Принципиальная схема подключения сервомотора и дальномера Питание 5 вольт для сервомотора и дальномера следует взять с контакта +5V платы драйвера двигателей (рис. 9.3). Под дальномер HC-SR04 на плате Arduino будут заняты два порта: D5 (Trig) и D6 (Echo). Управление сервомотором, поворачивающим голову, будет производиться с порта D9 платы Arduino (рис. 9.4).
Поворотная голова 13 9 Рис. 9.3. Монтажная схема цепей питания сервомотора и дальномера Рис. 9.4. Монтажная схема цепей управления сервомотором и дальномером
140 Глава 9 Измерение расстояния Ультразвуковой дальномер посылает импульс, этот импульс отражается от препят- ствия и возвращается через некоторое время. Время между импульсом и его возвра- том, умноженное на скорость звука и поделенное на два, даст расстояние. Но самостоятельно эти вычисления производить не потребуется, так как существу- ет специализированная библиотека ultrasonic.h, в которой все такие вычисления предусмотрены. Примечание Если в вашей оболочке эта библиотека отсутствует, ее можно найти в Интернете по запросу: ultrasonic-HC-SR04.zip или в папке ultrasonic-HC-SR04 сопровождающего книгу элек- тронного архива. Скопируйте файлы uitrasoniccpp и uitrasonic.h в текущий каталог с вашей программой И Добавьте В Нее Строку #include <Ultrasonic . h>. Пример из листинга 9.1 создает дальномер и назначает порты 5 и 6 для управле- ния им. Далее создается связь с ПК, в основной программе с периодом 0,5 секунды измеряется расстояние до препятствия, полученное значение передается в порт ПК. В оболочке Arduino IDE следует открыть монитор порта, тогда в окне монитора будет отображаться расстояние (рис. 9.5). Листинг 9.1. Программа измерения расстояний // Подключаем библиотеку, управляющую дальномером. #include <Ultrasonic.h> // Инициализируем дальномер, // контакт Trig соединен с 5 портом, Echo с б портом. Ultrasonic sonar(5, 6); void setup() { // При инициализации задаем скорость порта для связи с ПК. Serial.begin(9600); } void loop()
Поворотная голова 141 { //В цикле loop отправляем значение, полученное с дальномера, //в порт. Через 0,5 сек. // получаем дистанцию в сантиметрах. double prepyatstvie = sonar.Ranging(CM); Serial.print("Distance="); // оформляем вывод. // выводим дистанцию. Serial.print(prepyatstvie); Serial .printIn ("cm. ") ; // оформляем в,ывод. // приостанавливаем программу. delay(500); U.00 Ы.оо 46 CO "*" - СО "6.00 €.00 13,00 5.00 S. 00 .5.00 э.00 ^6.00 **£, j0 "".00 ''"„GO Рис. 9.5. Отображение измеренного расстояния в окне монитора порта Управление сервомотором Сервомотор требуется, чтобы робот поворачивал голову на шее. Для работы с серво- моторами в Arduino IDE также имеется отдельная библиотека, при помощи которой порт контроллера может генерировать программную ШИМ на любом порту с ча- стотой 50 Гц. Принцип работы контроллера (в режиме генерации ШИМ с частотой 50 Гц) очень похож на рассмотренный в главе 5, но для генерации ШИМ не требу- ются порты с аппаратной ШИМ, — подойдет любой цифровой порт, так как гене- рация ШИМ будет производиться программно. От длины положительного фронта импульса при широтно-импульсной модуляции зависит угол поворота сервомотора.
142 Глава 9 Простейшая программа, реализующая поворот головы робота в разные стороны, представлена в листинге 9.2. Голова поворачивается рывками по 10 градусов сначала в одну, а затем в другую сторону. Задеиствуются значения углов поворота от 10 до 170 градусов. Внимание! Сервомоторы SG90 имеют довольно хрупкие шестерни. Не следует вращать вал сервомото- ра руками — это может привести к разрушению шестерней! Сервомоторы с металлическими редукторами таких недостатков лишены. Листинг 9.2. Программа поворота головы робота в разные стороны // Подключаем библиотеку управления сервомоторами. #include <Servo.h> // Создаем сервомотор поворота головы. Servo neck; void setup() { // Инициализируем сервомотор, управление 9 портом. neck.attach(9); void loop() { mt 1; // Создаем цикл для равномерного поворота головы. for(1=10; i<=170; i=i+10) { // Поворачиваем вал на угол i. neck.write(i); // приостанавливаем программу. delay(lOO); } // Возвращаем голову назад. for(i=170; i>=10;i=i-10) { // Поворачиваем вал на угол i. neck.write(i); // приостанавливаем программу, delay(100);
Поворотная голова 143 Монтаж головы Если голова еще не сидит на роботе, то пора ее установить (рис. 9.6-9.10), — для это- го можно использовать крепления, поставляемые с сервомотором (рычажки и 2-мм шурупы), а также крепление для ультразвукового дальномера. Если у вашего робота не предусмотрено стандартного крепления головы, то подключите фантазию и вы- режьте его, например, из кусочка жести или пластиковой линейки. Установку головы следует проводить в следующем порядке: 1. Прикрутить к голове шурупами рычажок сервомотора (рис. 9.6 и 9.7). 2. Программно (neck.write (90);) установить сервомотор в срединное положение (листинг 9.3). 3. Надеть голову на сервомотор таким образом, чтобы после установки в срединное положение робота голова смотрела вперед (рис. 9.8 и 9.9). Помните, что вал мо- тора вращать руками нельзя ни в коем случае. 4. Закрепить голову на сервомоторе специальным винтом. 5. Установить в голову дальномер HC-SR04, совместив его датчики с отверстиями головы. 6. Установить сервомотор с дальномером в голове на корпус робота (рис. 9.10- 9.12). 7. Подключить сервомотор к электропитанию 5 В. Возможно, для этого потребу- ется отрезать стандартную клемму сервомотора. Поскольку сервомотор являет- ся мощным потребителем электроэнергии, электропитание следует производить от разъема 5 В платы драйвера двигателей: красный провод идет на питание +5 В, черный/коричневый — на «землю» (на минус). Используйте клеммы или пайку. 8. Подключить или припаять желтый провод (управление) сервопривода к порту D9 Arduino. 9. Подключить контакт Vcc дальномера HC-SR04 к питанию +5 В, контакт GND — к «земле» (на минус), контакт Echo — к порту D6 Arduino, контакт Trig — к порту D5. Для этого удобно использовать провода с клеммами. Так как даль- номер не является мощным устройством, то его электропитание можно получать и непосредственно с соответствующих разъемов платы Arduino (+5V и GND). Но рекомендуется, если есть такая возможность, использовать питание от внешнего стабилизатора, — например, от стабилизатора 5 В платы драйвера двигателей. 10. Провода от дальномера полезно стянуть стяжками в один пучок. Стянутые в пуч- ки провода реже подвергаются изгибам и реже переламываются.
144 Листинг 9.3. Установка сервомотора в срединное положение // Подключаем библиотеку управления сервомоторами. tinclude <Servo.h> // Создаем сервомотор поворота головы. Servo neck; void setup() { // Инициализируем сервомотор, управление 9 портом. neck.attach(9); } void loop() { // Поворачиваем вал на угол 90. neck.write(90); // приостанавливаем программу. delay(lOO); Глава 9 Рис. 9.6. Монтаж рычажка сервомотора к голове Рис. 9.7. Голова с прикрепленным к ней рычаж- ком сервомотора
Поворотная голова 145 Рис. 9.8. Монтаж головы на сервомотор Рис. 9.9. Голова установлена на сервомотор Рис. 9.10. Монтаж сервомотора с головой к корпусу робота
146 Глава 9 Рис. 9.11. Сервомотор головы закреплен на корпусе робота винтами \ Ч v \]\ Рис. 9.12. Робот с головой в сборе
Поворотная голова 147 Если что-то пошло не так. Неисправности во время сборки могут возникать по разным причинам: отсутствие внимания, плохое освещение, неправильное понимание схемы соединений и пр. Главное — не паниковать, составить схему действий и проверять все потенциально неисправные узлы последовательно. Так, основной проблемой может стать отказ дальномера показывать расстояние. Для ее устранения выполните следующие шаги: 1. Загрузите в робота программу, которая только определяет расстояние и передает его в порт компьютера (см. листинг 9.1). 2. Подключите робота к компьютеру, в Arduino IDE откройте порт. Как можно ви- деть, через порт поступают нулевые значения. 3. При включенном роботе проверьте наличие электропитания на дальномере НС- SR04 (между контактами Vcc и GND). 4. Скорее всего, при проведении измерений вы обнаружите, что на контакте даль- номера Trig всегда высокое напряжение, чего быть не должно, — напряжение на этот контакт поступает небольшими импульсами. 5. Отключив электро- ~. питание робота, из- • | мерьте сопротивле- | 7 ¥ ние между контакта- Г---; vjf:.', -.:-.,•;•.- •„. .L "•" -: - # ••' - ми Vcc и Trig — будет Ш^^-^'-^:^:>''' - •-" •>:.-•■§' .. ~ найдено короткое за- г мыкание (рис. 9.13). ^w^. £ШШ -ЛТШ *~ Устраняется это тща- ЩШ0 ЩЩШ^' '^^ '* 4:'^Ф& Шф§& гр?Т'.' тельной пропайкой ^6^* <*-^^ контактов и изоля- / / цией. '"" V.-') _ у ;^ _ \\ г ;■ 6. Все, неисправность ^-У " " ^, устранена, дально- ' ?f ^ / Ч; мер HC-SR04 начал работать правильно. с Рис. 9.13. Мультиметр при определении короткого замыкания
148 Глава 9 Выводы В этой главе подробно рассмотрен процесс установки на робота поворотной головы на основе сервомотора с ультразвуковым дальномером HC-SR04, а также порядок подключения этих компонентов. Теперь робот имеет возможность объезжать препятствия, но пока в нем нет про- граммы, которая анализирует информацию о расстоянии до препятствия и дает ро- боту соответствующие команды, проделанная нами работа мало полезна. Пора пере- ходить к ходовым испытаниям: составить алгоритм, написать по нему программу, а затем произвести настройку параметров, чем мы и займемся в следующей главе.
ГЛАВА 10 ХОДОВЫЕ ИСПЫТАНИЯ — ОБХОД ПРЕПЯТСТВИЙ Программа проверки и настройки основных функций робота После устранения явных неисправностей следует перейти к проверке правильности работы и тонкой настройке основных функций робота. Для этого подойдет програм- ма, которая позволяет роботу объезжать препятствия. Придумаем простой и понятный алгоритм объезда препятствий: 1. Вращаем головой и измеряем расстояние до препятствий слева, справа и впе- реди. 2. Сравниваем расстояния, выбираем наибольшее. 3. Туда и едем. 4. Если ехать нельзя, тупик — разворачиваемся. Подробная схема алгоритма приведена на рис. 10.1. Реализуем этот алгоритм в виде программы (листинг 10.1), опираясь на опыт разра- ботки программ в главах 7-9. Листинг 10.1 снабжен комментариями и соответствует алгоритму, приведенному на рис. 10.1. Следует заметить, что наша программа не яв- ляется идеальной программой обхода препятствий — в частности, ее эффективность
150 Глава 10 зависит от размеров робота. Программа тестировалась на роботе размером 17x14 см. Возможно, что большой робот будет застревать, заезжая в узкие проходы. В этом случае стоит самостоятельно поэкспериментировать с программой — например, до- бавить в нее проверку на возможность разворота, а если окажется, что разворот не- возможен, научить робота включать задний ход. В программу заложено условие, раз- решающее движение, если расстояние до препятствия превышает 10 см. Попробуйте это расстояние увеличить до 20-30 см. Подойдите к процессу тестирования робота и программирования его настроек творчески! Г 1 I Да * Да -Да- Нет, ! Да ~Да" ~Нет~ Рис. 10.1. Алгоритм программы обхода препятствий роботом
Ходовые испытания — обход препятствий 151 Листинг 10.1. Программа обхода препятствий роботом // Подключаем библиотеку управления сервомоторами. #include <Servo.h> // Подключаем библиотеку, управляющую дальномером. #include <Ultrasonic.h> // Инициализируем дальномер // Контакт Trig соединен с 5 портом, Echo с б портом. Ultrasonic sonar(5, б); // Создаем сервомотор поворота головы. Servo neck; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor_Rl, motor_R2, input_R; // Константы - постоянные значения для уточнения углов. const int left_ang=160; const int front_ang=90; const int right ang=20; // Временные константы служат для точного задания времени на поворот, разворот, движение вперед //в миллисекундах, const int time_90=390; const int time_180=750; const int time_10cm=220; void setup () { // Инициализируем сервомотор, управление 9 портом. neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели остановлены. setspeed(O, 0);
152 Глава Ю // Основная программа. void loop () { setspeed(255, 255); _stop(); // Создаем переменные для хранения трех дистанций: слева, впереди, справа. int Dist_left, Dist_front, Dist_right; // Поворачиваем голову налево. neck.write(left_ang); // Ждем, так как поворот занимает небольшое время. delay(150); // Записываем расстояние до препятствия слева. Dist_left = sonar.Ranging(CM); // Поворачиваем голову прямо вперед. neck.write(front_ang); // Ждем, так как поворот занимает небольшое время. delay(150); // Записываем расстояние до препятствия впереди. Dist_front = sonar.Ranging(CM); // Поворачиваем голову направо. neck.write(right_ang); // Ждем, так как поворот занимает небольшое время. delay(150); // Записываем расстояние до препятствия справа. Dist_right = sonar.Ranging(CM); neck.write(left_ang); // Если расстояние до препятствия слева наибольшее. if((Dist_left>Dist_front)&&(Dist_left>Dist_right)) { left(); // поворачиваем налево 0,5 секунд, delay(time_90); if(Dist_left>10) { forward(); // едем вперед 0.5 секунды, delay(time_l0cm);
Ходовые испытания — обход препятствий 15 3 else if(Dist_right>Dist_front) { right(); // поворачиваем направо 0,5 секунд, delay(time_90); if(Dist_right>10) { forward(); // едем вперед 0.5 секунды, delay(time_l0cm); else { if(Dist_front>10) { forward(); // едем вперед 0.5 секунды, delay(time_l0cm); } else { right(); // разворачиваемся, delay(time_180); // Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2. / / Примечание В папке listingjojm сопровождающего книгу электронного архива вы найдете модифици- рованную (альтернативную) версию этой программы — она немного отличается логикой.
154 Глава 10 Константы и постоянные времени Для тонкой настройки программы нам потребуется экспериментально определить ряд значений: 1. Значения углов поворота сервомотора для прямого, правого и левого взглядов. Довольно сложно установить голову на вал точно прямо, но можно эксперимен- тально подобрать и задать в программе нужный угол. Правый и левый поворо- ты — это повороты головы направо и налево на 60-75 градусов, чего достаточно, чтобы робот смог определить расстояние до препятствия справа и слева соот- ветственно. Высокая точность здесь не нужна, поскольку луч сонара довольно широкий, — около 30 градусов. Поверните сервомотор программно на 90 гра- дусов. Если при этом робот смотрит прямо, примите значение угла для прямого взгляда f ront_ang равным 90 градусов. В противном случае уточните значение f rontang экспериментально. 2. Значения времени, за которые робот поворачивает на 90 градусов и на 180 гра- дусов. Здесь экспериментально определяется время, за которое робот выполняет эти движения. На разных типах поверхности это время может быть различным. 3. Время, за которое с места робот проезжает 10 сантиметров. Полученные значения заносятся в программу как константы с интуитивно понятны- ми названиями (табл. 10.1). Таблица 10.1. Переменные и константы для программы обхода препятствий №п/п 1. 2. 3. 4. Переменная или константа left ang front ang right ang time 90 Назначение Угол поворота сервопривода головы робота для поиска препятствий слева — 70° от прямого положения Угол поворота сервопривода головы робота для поиска препятствий прямо по ходу робота Угол поворота сервопривода головы робота для поиска препятствий справа — 70° от прямого положения Время, за которое робот поворачивает на 90° из состояния покоя Содержимое функции loop() setspeed(255, 255); neck.write(left ang); delay (1000); setspeed(255, 255); neck.write(front ang); delay (1000); setspeed(255, 255); neck.write(right ang); delay(1000)/ setspeed(255, 255); left() ; delay(time 90); _stop() ; delay(10000);
Ходовые испытания — обход препятствий 155 Таблица 10.1 (окончание) №п/п 5. 6. Переменная или константа time 180 time 10cm Назначение Время, за которое робот поворачивает на 180° из состояния покоя Время, за которое робот из состояния покоя преодолевает расстояние 10 см и полностью останавливается Содержимое функции loop () setspeed(255, 255); left () ; delay(time 180); _stop () ; delay (10000); setspeed(255, 255) ; forward(); delay(time 10cm); _stop () ; delay (10000); Значения функции loop о, содержащей основные действия программы из листин- га 10.1, можно для своего робота уточнить, если удалить из этой функции все строки, а затем поочередно вставлять в нее строки, представленные в 4-м столбце табл. 10.1. Изменяя в программе значения указанных параметров, нужно добиться удовлетво- рительного результата. Например, если команда neck. write (f rontang) приводит к тому, что робот смотрит немного вбок, то следует, понемногу увеличивая или уменьшая значение const int f ront_ang=90, добиться того, чтобы робот смотрел прямо. Полученное значение мо- жет отличаться от 90, и его следует запомнить и применить в программе. Аналогично надо поступить для поворота головы влево и вправо. Для поворотов робота на 90 градусов нужно определить время, за которое робот со- вершает поворот на указанный угол. Стоит заметить, что это время будет отличаться для разного вида поверхностей, по которым движется робот. Если робот поворачи- вается на угол больший, чем 90°, следует это время уменьшать, а если угол поворота мал, то увеличивать. В программе используется поворот на 90 градусов, но можно использовать и меньшие значения углов. Время движения вперед/назад на заданное расстояние определяется аналогично. В программе это расстояние задано величиной 10 см, но вы можете его увеличить.
156 Глава 10 Отладка программы Проверку правильности функционирования робота рекомендуется производить в следующием порядке: 1. Снять с робота колеса. 2. Загрузить программу из листинга 10.1 и дополнить ее следующими тестовыми командами согласно листингу 10.2 (требуемые изменения в листинге 10.2 выде- лены полужирным шрифтом): ♦ в разделе setup о организовать вывод в порт; ♦ в основной программе loop о вставить в интересующих нас местах вывод служебной информации. 3. Запрограммировать робота и оставить его соединенным кабелем с ПК. 4. В Arduino IDE открыть окно Монитор порта. 5. Создавая перед роботом различные варианты препятствий, соответствующие определенной ситуации в программе, проверить правильность реакции робота по выводу сообщений в окно Монитор порта и по вращению колес, — робот при этом будет выдавать в порт расстояния до препятствий и этапы работы програм- мы (какой блок выполняется). 6. Если робот действует не верно, проанализировать его работу и внести в програм- му необходимые правки. 7. Можно также скорректировать время, которое требуется роботу для поворота головы (в листинге 10.2 это время сильно увеличено до 1,5 сек.), этого времени должно быть достаточно для поворота головы, но не приводить к простою робо- та. В то же время, если голова еще вращается, а робот уже начал измерять рас- стояние до препятствия, результат измерения окажется неверным. Листинг 10.2. Отладочная (неполная) программа обхода препятствий с выводом в порт void setup() { // При инициализации задаем скорость порта для связи с ПК. Serial.begin(9600); // Инициализируем сервомотор, управление 9 портом. neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino.
Ходовые испытания — обход препятствий 15 7 // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели остановлены. setspeed(0, 0); } // Основная программа, void loop () { setspeed(255, 255); _stop() ; // Создаем переменные для хранения трех дистанций - слева, впереди, справа. int Dist_left, Dist_front, Dist_right; // Поворачиваем голову налево. neck.write(left_ang); // Ждем, так как поворот занимает небольшое время. delay(1500); // оформляем вывод Serial.println(" ") ; Serial.println(" "); // Записываем расстояние до препятствия слева. Dist_left = sonar.Ranging(CM); // оформляем вывод. Serial.print("Dist_left="); // выводим дистанцию. Serial.print(Dist_left); // оформляем вывод. Serial. println (" can. ") ; // приостанавливаем программу. delay(500); // Поворачиваем голову прямо вперед. neck.write(front_ang); // Ждем, так как поворот занимает небольшое время.
158 Глава 10 delay(1500); // Записываем расстояние до препятствия впереди. Dist_front = sonar.Ranging(CM); // оформляем вывод. Serial. print ("Dist_front=") ; // выводим дистанцию. Serial.print(Dist_front); // оформляем вывод. Serial.println(" cm. ") ; // приостанавливаем программу. delay(500); // Поворачиваем голову направо, neck.write(right_ang); // Ждем, так как поворот занимает небольшое время, delay(1500); // Записываем расстояние до препятствия впереди. Dist_right = sonar.Ranging(CM); // оформляем вывод. Serial.print("Dist_right="); // выводим дистанцию. Serial, print (Dis t__right) ; // оформляем вывод. Serial.println(" cm. "); // приостанавливаем программу, delay(500); neck.write(front ang); // оформляем вывод. Serial.println(" ") ; // Если расстояние до препятствия слева наибольшее. if ((DistJLeft > Dist_front) && (Dist_left > Dist_right))
Ходовые испытания — обход препятствий 159 // оформляем вывод. Serial.print (" (Dist_left>Dist_front)&&(Dist_left>Dist_right) ") Serial.println(" POVOROT LEFT"); // приостанавливаем программу. delay(500); left(); // поворачиваем налево 0,5 секунд. delay(time_90); if (Dist_left > 10) { // оформляем вывод. Serial.printin(" Dist_left>10 VFERED 0.5 SEC"); // приостанавливаем программу. delay(500); forward(); // едем вперед 0.5 секунды. delay(time_10cm); else if (Dist_right > Dist_front) { // оформляем вывод. Serial.println(" Dist_right>Dist_front POVOROT RIGHT"), // приостанавливаем программу. delay(500); right(); // поворачиваем направо 0,5 секунд. delay(time_90); if (Dist_right > 10) { // оформляем вывод. Serial.println(" Dist__right>10 VPERED 0.5 SEC");
160 Глава 10 II приостанавливаем программу, delay(500); forward(); // едем вперед 0.5 секунды, delay(time I0cm); else if (Dist_front > 10) { // оформляем вывод. Serial.println(" Dist_front>10 VPERED 0.5 SEC"); // приостанавливаем программу. delay(500); forward(); // едем вперед 0.5 секунды. delay(time_l0cm); } else { // оформляем вывод. Serial.println(" right **********RAZVOROT*************") // приостанавливаем программу. delay(500); right(); // разворачиваемся. delay(time_180);
Ходовые испытания — обход препятствий 161 / / = = — = - --=—= = =^^.= = = = = = = = z= = = = = = = = = = =—= = = z= = = = = = == = = = ==: = ^ = = .= — = =r = — — = = = = z= = = = -— - //Функции инициализации и управления моторами не включены в листинг, // их следует взять из листинга 8.2. //=.=============================-====================== = = = = = = = = = = = = = = = = Пример вывода сообщений в окно монитора приведен на рис. 10.2. I43t_right=83 cat. Pi3t_right:I»i3t_fr3nt POVOROT RIGHT Di3t_nght>10 VPERED 0.5 SEC Pi3t_left=12 cm. t_front=2^ cm. [Ji3tright»15 cm. fist ftnnt>10 VPERED 0.5 Dist_le£t=61 cm. I'i£t_front=14 cm. Pi3r_right*13 cm. (Dist_left">Dist front) a (Dist_leftv>Di3t Lightl POVOPOT LEFT J»ist left>10 VPERED 0.5 SEC I'ist_front=23 cm. I'ist_nght:=I40 сю. (Dist_lef t>r-ist_f Lor.t»fi4 (Dist^lef ri-Di3t_£ight) POVOROT LEFT bift lefr>10 VPEP£D 0.5 SEC Рис. 10.2. Пример вывода сообщений в окно монитора Здесь наглядно видно, что когда слева 12 см, прямо 22 см, а справа 15 см, то самое большое расстояние впереди (и оно больше 10 см), и, соответственно, выполняется команда «Ехать вперед». Удостоверьтесь, что при этом моторы действительно вра- щаются вперед. Когда же слева 61 см, прямо 14 см, а справа 13 см, то самое большое расстояние слева (и оно больше 10 см), и, соответственно, выполняются команды «Повернуть вле- во» и «Ехать вперед». Удостоверьтесь, что при этом моторы вращаются согласно командам.
162 Глава 10 Выводы Нами создана программа проверки и настройки основных функций робота, она же представляет собой простейшую программу, позволяющую роботу двигаться, объез- жая препятствия. Введены специальные константы, отвечающие за параметры робо- та, дан их список и объяснено назначение. Описаны функции движения робота и их назначение. Приведен пример отладки программы. На следующем этапе нам предстоит модернизация собранного робота под решение конкретных задач.
ГЛАВА 11 РОБОТ, НАХОДЯЩИЙ ВЫХОД ИЗ ЛАБИРИНТА В этой главе мы поставим себе следующую цель — создать автономного робота, спо- собного за наименьшее время найти выход из лабиринта. Пример лабиринта пред- ставлен на рис. 11.1, где выход из лабиринта обозначен перечеркнутым кругом. Все проходы лабиринта проходимы по ширине и допускают беспрепятственную возмож- ность разворота робота. В поисках выхода робот не видит лабиринт целиком и не имеет о нем дополнительной информации. Для достижения поставленной цели нам потребуется решить следующие задачи: 1. Разобраться, как можно установить наличие препятствий (с помощью каких дат- чиков и решений). 2. С учетом выбранных датчиков и принятых технических решений создать алго- ритм движения, гарантирующий прохождение лабиринта. 3. На основании созданного алгоритма составить программу, позволяющую роботу преодолеть лабиринт. 4. Реализовать разработанного робота, провести его тестирование и добиться ста- бильной работы.
164 Глава 11 Рис. 11.1. Робот в лабиринте
Робот, находящий выход из лабиринта 165 Способ обхода лабиринта Известен принцип, согласно которому, если при движении в лабиринте придержи- ваться одной его стороны (стенки): левой или правой, то выход обязательно будет достигнут. Это верно для лабиринтов с выходом наружу. Графически возможный путь робота показан на рис. 11.2 (вдоль правой стенки лабиринта) и 11.3 (вдоль его левой стенки). Рис. 11.2. Путь робота вдоль правой стенки Следует обратить внимание, что по пути, показанном на рис. 11.3, робот достиг- нет выхода быстрее, но он не может знать заранее, где выход и какой путь короче. Конечно, это может знать оператор и выбрать для робота выигрышный режим «на- право» или «налево» перед входом в лабиринт. Впрочем, как правило, в соревнова- ниях роботов такая подсказка оператора недопустима.
166 Глава 11 Рис. 11.3. Путь робота вдоль левой стенки Обход лабиринта без модернизации робота Составим алгоритм обхода лабиринта для робота, оснащенного уже знакомым нам ультразвуковым датчиком, установленным на его поворотной голове (рис. 11.4). Пусть робот в этот раз будет совершать обход лабиринта по правой его стороне. При этом он должен всегда держаться на небольшом расстоянии (3-4 см) от правой стен- ки и адекватно реагировать на изменение обстановки. Добавим к этому расстоянию половину ширины робота и получим нижнюю границу DistRight. Робот измеряет расстояния с двух сторон: справа и прямо, затем анализирует полученные резуль- таты, выполняет соответствующие движения и снова останавливается для сбора данных. Если расстояние до препятствия справа находится в пределах от 5 до 7 см,
Робот, находящий выход из лабиринта 167 значит, подворот не нужен, немного проезжаем вперед (если при этом нет препят- ствия спереди). Если дистанция справа стала больше 7 см, значит, робот стал отходить от правой стены, и нужно начать подворот вправо. Если робот уперся в стену, ему следует по- вернуть на месте влево и снова получить данные. 4 Да Нет Да L -Нет Г 1 Нет Рис. 11.4. Алгоритм движения вдоль правой стенки с помощью ультразвукового датчика
168 Глава 11 Программа Соответствующая рассмотренному алгоритму программа представлена в листин- ге 11.1. В ней много настраиваемых значений, которые определяются эксперимен- тально. Это, например, углы поворота головы. Дело в том, что механически устано- вить голову так, чтобы значение 90° соответствовало точно переднему положению головы, довольно трудно, поэтому мы определяем этот угол экспериментально, из- меняя значения, передаваемые на сервомотор, и следя за положением головы робо- та. Временные константы, связанные с движением и поворотами, зависят от дорож- ного покрытия и заряда аккумуляторов. Например, поворот на ковровом покрытии займет больше времени, чем на линолеуме или ламинате, а на гладком и скользком полу возможно инерционное скольжение робота. Следите за зарядом аккумулято- ров — если они сильно разрядятся, робот станет передвигаться медленнее. Не все моторы с редукторами хорошо работают с ШИМ, которую предлагает функ- ция setspeeddnt, int), возможно, это связано с малым соотношением У48 (один оборот вала колеса на 48 оборотов вала двигателя), поэтому программа в листин- ге 11.1 написана без управления мощностью двигателей. Листинг 11.1. Программа движения вдоль правой стенки с помощью ультразвукового датчика // Подключаем библиотеку управления сервомоторами. #include <Servo.h> // Подключаем библиотеку, управляющую дальномером. #include <Ultrasonic.h> // Инициализируем дальномер // Контакт Trig соединен с 5 портом, Echo с б портом. Ultrasonic sonar(5, 6); // Создаем сервомотор поворота головы. Servo neck; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor_Rl, motor_R2, input_R; // Константы — постоянные значения для уточнения углов. const int left_ang=168; const int front ang=102; const int nght_ang=20; // Временные константы служат для точного задания времени на поворот, разворот, движение вперед.
Робот, находящий выход из лабиринта 169 //в миллисекундах, const int time_90=390; const int time_180=750; const int time_10cm=220; const int time_7cm=120; void setup() { // Инициализируем сервомотор, управление 9 портом. neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели остановлены. setspeed(0, 0); neck.write(front_ang); delay(150); setspeed(255, 255); _stop() ; } // Основная программа, void loop() { setspeed(255, 255); // Создаем переменные для хранения двух дистанций до препятствий спереди, справа. int Dist_left, Dist_front, Dist_right; _stop() ; // Ждем, так как поворот занимает небольшое время. delay(250); // Записываем расстояние до препятствия впереди. Dist_front = sonar.Ranging(CM); // Поворачиваем голову направо. neck.write(right_ang); // Ждем, так как поворот занимает небольшое время. delay(250); // Записываем расстояние до препятствия впереди.
170 Глава II Dist_right = sonar.Ranging(CM); neck.write(front_ang); // Если условия позволяют двигаться прямо if ( (Dist_nght>=8) && (Dist_right<=15) && (Dist_front>=15) ) { forward(); // едем вперед, delay(time_10cm); } else {// если появился поворот направо if(Dist_right>15) { // если абсолютно уперлись в стену! // узкий правый поворот, if(Dist_front<5) { right(); // поворачиваем направо, delay(time_90); } else // нормальный правый поворот. { // поворот направо в движении. rightO ; delay(time_90/3); forward(); // едем вперед 7 см. delay(time_90/3); else // если уперлись в стену. if(Dist_front<15) { left(); // поворачиваем налево. delay(time_90);
Робот, находящий выход из лабиринта 171 else { // подворот налево в движении. left (); delay (time_90/3) ; forward(); // едем вперед 5 см. delay(time_90/3); / / //Функции инициализации и управления моторами не включены в листинг, // их следует взять из листинга 8.2. / / Сравнение и выбор датчиков Как можно видеть, наш робот, определяя расстояния с помощью ультразвукового датчика расстояния HC-SR04, часто останавливается и находит выход из лабиринта относительно медленно. Что ж, можно попытаться ускорить его работу, задейство- вав дополнительные датчики. В качестве таких датчиков могут быть использованы кратко рассмотренные в гла- ве 1 детекторы препятствия (см. рис. 1.4) и инфракрасные датчики расстояния (см. рис. 1.6). Ультразвуковой датчик HC-SR04 Взглянем еще раз на используемый нами сейчас ультразвуковой датчик HC-SR04 (подробно он рассматривался в главе 9). Как там и отмечалось, для управления им должно быть задействовано два порта Arduino. Датчик определяет расстояние от 2 до 400 сантиметров, а библиотека его располагает двумя функциями: Ranging (int) и Timing о. Функция Ranging (int) возвращает расстояние в сантиметрах (Ranging (I)/ Ranging (CM)) ИЛИ В ДЮЙМаХ (Ranging (0)/ Ranging (INC) ). ФуНКЦИЯ Timing о возвращает расстояние в относительных единицах, которые затем нужно разделить на 58 для получения сантиметров. Чтобы получить большую точность измерений, лучше использовать функцию Timmg (), так как при измерении с помощью функции Ranging (int) мы получаем це- лые числа, и дробная часть сантиметров может потеряться. Время, которое требуется
172 Глава 11 для измерения, изменяется от 1 до 200 миллисекунд и увеличивается с увеличением измеряемого расстояния. Между последовательными измерениями для подавления эхо-эффекта требуется время в 50 миллисекунд. В итоге минимальное количество замеров в секунду — 4, максимальное — 19. Это не много, особенно с учетом того, что для каждого измерения роботу приходится останавливаться, а для измерения расстояния до разных сторон еще и вращать головой. Прохождение лабиринта при этом будет довольно медленным. Инфракрасный детектор препятствия Инфракрасный датчик (детектор) препятствия, показанный на рис. 1.4, определяет наличие препятствия по интенсивности отраженного света: если она выше пороговой, на выходе появляется низкий уровень напряжения, если препятствия нет, то уровень напряжения на выходе высокий. Это важно не перепутать! Датчик не информирует о расстоянии до препятствия, он только сбрасывается в ноль при его наличии. Расстояние до препятствия, на котором срабатывает датчик, можно регулировать в диапазоне от 3 до 80 см, вращая бегунок переменного резистора (в центре датчика). Плата снабжена двумя информационными светодиодами, красный — наличие пита- ния, зеленый — наличие препятствия. В передней части платы датчика расположены инфракрасный излучатель и приемник (рис. 11.5). Недостатком этого детектора является зависимость расстояния срабатывания от цве- та объекта. Фактически, это говорит нам о том, что датчики нужно подстраивать под цвет проходимого лабиринта. Также датчик практически не работает (показывает постоянно наличие препятствия) при наличии посторонних источников инфракрас- ного освещения — к таковым относятся прямой или отраженный от близлежащих объектов солнечный свет. Фототранзистор Настройка расстояния реакции датчика Светодиод наличия электропитания (красный) Напряжение питания 5В Светодиод инфракрасного спектра (свет невидим глазом) VCC GND Светодиод индикатор срабатывания датчика (горит зеленым при обнаружении препятствия) Отрицательный контакт питания (земля) 44 Выход датчика (при обнаружении препятствия 0, иначе 1) Рис. 11.5. Инфракрасный детектор препятствия
Робот, находящий выход из лабиринта 173 Инфракрасный датчик Sharp GP2Y0A21YK Инфракрасный датчик расстояния Sharp GP2Y0A21YK, показанный на рис. 1.6, от- личается от прочих тем, что выдает данные о расстоянии в виде аналогового сигна- ла (выходное напряжение изменяется в зависимости от расстояния). При этом из- меряемое расстояние лежит в диапазоне от 10 до 80 см. Для измерений требуется подключить датчик к питанию 5 вольт, а его выход - к аналоговому входу Arduino, например, АО. Следует учесть, что зависимость показаний датчика от расстояния не- линейная, поэтому для расчета расстояния в сантиметрах нужно использовать спе- циальную функцию обработки. Пример такой функции приведен в листинге 11.2. Время, которое требуется для измерения, составляет около ОД миллисекунды, паузы между замерами не нужны. Максимальное количество замеров в секунду — около 10 000. Основные недостатки таких датчиков заключаются в их относительно высо- кой стоимости и малом диапазоне измеряемых расстояний. Листинг 11.2. Функция обработки показаний датчика расстояния Sharp GP2Y0A21YK int IR_Ranging(int nk) { if((nk>13)&&(nk<22)) { int vole=analogRead(nk); if(vole<18) vole=18; return 5461/(vole - 17) - 2; } else return 1000; Обоснование выбора датчика препятствия В связи с тем, что ультразвуковой датчик уже используется в проекте, а инфракрас- ные детекторы препятствия примерно в 10 раз дешевле, чем инфракрасный датчик расстояния Sharp GP2Y0A21YK, то мы воспользуемся ими. Впрочем, датчик Sharp GP2Y0A21YK со счетов мы тоже сбрасывать не станем, по- скольку он практически не дает сбоев, и если стоимость робота не критична, реко- мендуем использовать именно его.
174 Глава 11 Модернизация робота Итак, поскольку наш робот часто останавливается и находит выход из лабиринта относительно медленно, мы попытаемся ускорить его работу, использовав дополни- тельные датчики — детекторы препятствия. Монтаж детекторов препятствия Установим на передний бампер робота три детектора препятствия, чего для наших целей вполне достаточно (рис. 11.6-11.9). У нашего робота два детектора смотрят вперед и один — вправо. Наличие двух детекторов, направленных вперед, улучшает качество определения препятствий спереди, поскольку сектор определения одного детектора не захватывает всю переднюю зону. Крепятся датчики на шасси робота при помощи винтов. Перед установкой датчиков на шасси следует подсоединить или припаять к ним провода. Желательно также защитить сенсоры от ударов, иначе от столкновений с препят- ствиями они быстро погнутся и выйдут из строя. Пример организации подобной защиты приведен на рис. 11.10 — сенсоры установлены на специальной пластине Рис. 11.6. Робот, три детектора препятствия и крепежные винты
Робот, находящий выход из лабиринта 175 и не выступают за бампер. При этом сами излучатель и приемник следует направить (подогнуть) немного вверх (на 15-20 градусов), иначе срабатывание датчика может происходить от самого бампера. Рис. 11.7. Три детектора препятствия размещены на нижней плате шасси Рис. 11.8. Крепление датчиков препятствия винтами
176 Глава 11 Рис. 11.9. Датчики препятствия смонтированы Рис. 11.10. Установка сенсоров на бампере с целью защиты от ударов
Робот, находящий выход из лабиринта 177 Полную схему робота здесь приводить не имеет смысла — она уже была представ- лена в предшествующих главах. Изменения коснулись только порядка подключения детекторов. Электропитание +5V они получают от модуля драйвера двигателей L298N (рис. 11.11, 11.13). «Земля» (контакт GND) берется с любого доступного места — например, от того же L298N. Сигнальные выводы подключаются ко 2, 12 и 13-му портам Arduino (рис. 11.12, 11.13). Получать питание 5 В датчики могут и от Arduino, но на некоторых платах Arduino стоят слабые стабилизаторы напряже- ния, которые не следует перегружать, поэтому 5 В и подается на датчики от L298N. Фронтальные датчики мы подключаем к портам 2 (датчик S1) и 12 (датчик S2), а датчик, расположенный с правой стороны, к 13-му порту (датчик S3). Расположение контактов на датчиках у разных изготовителей может быть различ- ным, поэтому внимательно следите за названиями контактов. Так, питающий кон- такт может иметь обозначе- ние VCC или 5V. Рис. 11.11. Электропитание датчиков После подключения детек- торов следует снять с ро- бота колеса, включить его электропитание и настро- ить расстояние срабатыва- ния детекторов, используя переменные резисторы и зеленые сигнальные свето- диоды, которые загораются при детекции препятствия. S3 s2 S1 Рис 11.12. Подключение датчиков к Arduino UNO
178 Глава 11 Рис 11.13. Принципиальная схема подключения детекторов препятствия Программа для робота с детекторами препятствия Алгоритм движения робота с тремя детекторами препятствия (рис. 11.14) проще, чем алгоритм с ультразвуковым датчиком: проверяется состояние датчиков, и в зависи- мости от полученных данных принимается решение, позволяющее двигаться вдоль правой стены. Загрузите программу (листинг 11.3). Поэкспериментируйте со значениями перемен- ных времени для подбора точных поворотов. Пробуйте управлять моторами с по- мощью ШИМ, изменяя скорость — задавая разные значения в функции setspeed (). Если вам кажется, что можно создать программу лучше, чем та, что приведена в
Робот, находящий выход из лабиринта 179 листинге, смело программируйте и пробуйте. Для тестирования программы не обя- зательно наличие лабиринта — подойдет и любая комната с расставленными пре- пятствиями. Используемые в проекте детекторы препятствия по-разному реагируют на препят- ствия различного цвета — лучшие результаты получаются для белых и светлых пре- пятствий. Детекторы препятствия также не могут работать при наличии солнечного Нет нет J Да -Да- Рис. 11.14. Алгоритм движения робота с тремя детекторами препятствия
180 Глава 11 света и источников сильного инфракрасного излучения — это связано с особенностью используемых светочувствительных элементов (фототранзисторы). Поэтому важно, чтобы препятствия были однородными по цвету, и в комнату не попадал бы прямой солнечный свет (увы, приходится считаться с этими недостатками детекторов). Листинг 11.3. Программа движения робота с тремя детекторами препятствия // Объявляем переменные для хранения состояния двух моторов, int motor_Ll, motor_L2, input_L; int motor Rl, motor R2, input R; // Временные константы служат для точного задания времени на поворот, разворот, движение вперед //в миллисекундах. const int time_90=390; const int time_180=750; const int time_10cm=220; // Номера портов, к которым подключены датчики препятствия. const int Front1=2, Front2=12, Right-13; void setup() { // Инициализируем сервомотор, управление 9 портом. neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // pinMode(Front1, INPUT); pinMode(Front2, INPUT); pinMode(Right, INPUT); // Двигатели запущены. setspeed(255, 255) ; } // Основная программа, void loop()
Робот, находящий выход из лабиринта 181 boolean d_Frontl, d_Front2, d_Right; d_Frontl = digitalRead(Frontl); d_Front2 - digitalRead(Front2) ; d_Right digitalRead(Right); // Если ни один датчик не сработал. if (d_Frontl && d_Front2 && d_Right) { forward_right();// подворот вправо. delay(time_90 / 9); forward(); // едем вперед. delay(time_lОст / 2); else // Если сработал один из передних датчиков и не сработал правый. if ((!d_Frontl) || (!d_Front2)) { // Если не сработал правый датчик. if (d_Right) { // поворачиваем направо на 90 градусов, right(); // поворачиваем направо на 90 градусов, delay(time_10cm); } else { // поворачиваем налево на 90 градусов. left () ; delay (time_10cm) ; else
182 Глава 11 { // Если сработал правый датчик. forward_left();// подворот влево, delay(time_90 / 9); forward(); // едем вперед, delay(time IOcm / 2); / / //Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2. Модернизируем программу Следующий листинг (11.4) демонстрирует модернизированную программу прохо- да лабиринта с использованием датчиков препятствия. Здесь применены повороты в движении (без блокировки колес), что позволило максимально упростить програм- му. Также организовано управление мощностью двигателей, за счет чего и произво- дятся повороты в движении: на стороне, в которую следует подвернуть, уменьшается мощность двигателей — это уменьшает обороты двигателей со стороны поворота, и робот подворачивает, не останавливаясь. Листинг 11.4. Модернизированная программа прохода лабиринта с использованием датчиков препятствия // Объявляем переменные для хранения состояния двух моторов, int motor LI, motor L2, input L; int motor_Rl, motor_R2, input_R; // Временные константы служат для точного задания времени на поворот, разворот, движение вперед //в миллисекундах. const int time_90 = 390; // Номера портов, к которым подключены датчики препятствия. const int Frontl = 2, Front2 = 12, Right = 13;
Робот, находящий выход из лабиринта 183 void setup() { // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); pinMode(Frontl, INPUT); pinMode(Front2, INPUT); pinMode(Right, INPUT); // Двигатели запущены. setspeed(255, 255); } // Основная программа. void loop () { boolean d_Frontl, d_Front2, d_Right; d_Frontl = digitalRead(Frontl); d_Front2 = digitalRead(Front2); d_Right digitalRead(Right); // Если ни один датчик не сработал, if (d_Frontl && d_Front2 && d_Right) { // Замедление правых колес setspeed(255, 15); forward();// подворот вправо. else // Если сработал один из передних датчиков и не сработал правый, if ((!d_Frontl) II (!d_Front2)) { // Максимальная мощность на все колеса. setspeed(255, 255);
184 Глава 11 /I поворачиваем налево на 90 градусов. left (); delay(time_90 / 5); } else { // Если сработал правый датчик. // Замедление левых колес. setspeed(15, 255); forward();// подворот влево. //Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2. / / Замечание В лабиринтах хорошо показывают себя роботы, собранные на сервомоторах постоянного вращения, - они практически не ошибаются в любом лабиринте. Это достигается за счет того, что скорость вращения сервомотора изменяется очень точно и плавно, вследствие чего не нужно использовать вставки с вызовом функции delay о. Также для повышения точности можно использовать датчики расстояния Sharp. Построение такого робота вы- ходит за рамки этой книги, но вы можете заняться подобным усовершенствованием само- стоятельно. Выводы В этой главе рассмотрены различные датчики препятствий, и выбраны ультразву- ковой и инфракрасный. Обсуждены алгоритмы их работы. Составлены соответству- ющие программы. Показаны способы крепления датчиков препятствий на шасси робота. Приведена принципиальная схема подключения детекторов. Даны рекомен- дации по подбору параметров, от которых зависит поведение робота в лабиринте, а также советы по самостоятельной доработке конструкции. Пришло время научить нашего робота играть в кегельринг — искать и выталкивать кегли.
ГЛАВА 12 РОБОТ, ИГРАЮЩИЙ В КЕГЕЛЬРИНГ Цель, которую мы ставим себе в этой главе; — сконструировать робота, выбиваю- щего кегли из круга, очерченного черной линией. Робот должен уметь сортировать кегли по цвету и выбивать кегли только черного или белого цвета, не выезжая при этом за ограничительную линию. Пример кегельринга представлен на рис. 12.1: диа- метр круга - 1 метр, количество кеглей - до 8, возможный цвет кеглей - черный и белый, диаметр кегли — 70 мм, высота — 120 мм. Рис. 12.1. Робот на ринге
186 Глава 12 Для достижения поставленной цели нам потребуется решить следующие задачи: 1. Разработать механизмы поиска кегли и определения ее цвета, модифицировать робота, если необходимо. 2. Определить, как ограничить движения робота черной линией, модифицировать робота, если необходимо. 3. С учетом используемых технических решений создать алгоритм поиска кегли, определения ее цвета и выталкивания за пределы круга. 4. На основании созданного алгоритма составить программу. 5. Реализовать разработанного робота, провести его тестирование и добиться ста- бильной работы. Простой кегельринг В простом варианте кегельринга роботу требуется вытолкнуть из белого круга все кегли. Эта задача может быть решена довольно просто, если заставить робота ехать вдоль черной линии на расстоянии около 15 см от нее и снабдить его косым бампе- ром (рис. 12.2). Рис. 12.2. Робот, выталкивающий все кегли {начало)
Робот, играющий в кегельринг 187 В этом случае робот должен выехать из центра круга, подъехать к ограничительной линии, не доезжая до нее примерно 20 см, и проехать вдоль нее по кругу. Сделав один полный круг, робот гарантированно вытолкнет все кегли (рис. 12.3). Заставить робота двигаться по кругу можно, регулируя скорость вращения правых и левых колес, но если сделать так не получится, то просто чередовать краткие перио- ды движения по прямой линии и краткие повороты влево. Из-за неравномерности движения робота вследствие проскальзывания по поверхно- сти может возникнуть проблема выхода его за пределы ограничительной линии. Для ее решения нужно заставить робота следить за тем, чтобы правый конец его бампе- ра все время находился на этой линии. То есть, он каким-то образом должен отсле- живать, что правый конец — только конец — бампера находится на черной линии, и подворачивать в соответствии с полученной информацией. Например, если бампер сильно углубился в черную линию, то сильнее подвернуть влево, а если бампер эту линию потерял, то подвернуть вправо. Рис. 12.3. Робот, выталкивающий все кегли {окончание)
188 Глава 12 Двухцветный кегельринг Усложним задачу и научим робота выбивать кегли с учетом их цвета: только черные или только белые. Сортировка по цветам — задача решаемая, поскольку существуют датчики определения цвета (например, TCS230). Порядок обхода Поскольку перед роботом поставлена задача выбивать кегли только определенного цвета, логично принять за основу порядок обхода им кегельринга, изображенный на рис. 12.4. Как можно видеть, робот при этом будет поочередно подъезжать к каждой кегле и определять ее цвет, после чего принимать решение, удалять ее или нет. Порядок об- хода кегельринга при выбивании, например, только черных кеглей представлен на рис. 12.5: робот находит кеглю, подъезжает к ней, определяет ее цвет и, в зависимо- сти от цвета кегли, либо выталкивает ее, либо возвращается на середину и продол- жает обход. Рис. 12.4. Порядок поочередной обработки кеглей роботом
Робот, играющий в кегельринг 189 Рис. 12.5. Робот, выталкивающий только черные кегли Обнаружение черной линии Обнаружить черную (ограничительную) линию нам помогут электронные приборы, которые реагируют на изменение освещенности. Рассмотрим четыре таких прибора, наиболее применимых для решения поставленной задачи. Фотодиод Фотодиод (рис. 12.6, а) в темноте ведет себя как обычный диод — пропускает элек- трический ток только в одном направлении, а при освещении генерирует небольшой ток даже без источника питания. При обратном включении фотодиода он, при дости- жении освещенностью определенного уровня, начинает пропускать электрический ток в обратном направлении — это позволяет использовать фотодиоды в качестве датчиков наличия освещенности. Схемы обратного включения фотодиодов приведены на рис. 12.6, би 12.6, в. Сигнал снимается с выхода OUT, при этом для схемы рис. 12.6, б наличие освещенности
190 Глава 12 характеризуется высоким выходным сигналом, а для схемы рис. 12.6, в — низким. Подобные схемы не позволяют измерять уровень освещенности, а лишь фиксируют ее наличие, что говорит о необходимости подключения их к цифровым портам, ко- торые воспринимают только два вида сигналов: высокий — «1» и низкий — «0». 5V 5V Р2 R4 2.2Ш ±5% OUT Р1 OUT а б в Рис. 12.6. Фотодиод {а) и схемы подключения фотодиода в качестве датчика наличия освещенности (6 и в) Чтобы фотодиод мог четко детектировать черную линию, нужно ее область подсве- тить, для чего, как правило, используется светодиод. Исходящий от него свет, отра- жаясь от светлой поверхности пола, попадает на фотодиод, вызывая в нем обратный ток. От черной же линии свет не отражается, что приводит к прекращению обратного ток^ фотодиода. Светодиод и фотодиод размещаются над исследуемой поверхностью так, чтобы отраженный от нее свет светодиода попадал на фотодиод. При этом рас- стояние до поверхности должно быть в пределах 1-2 см. Фотодиоды и светодиоды производятся для разных спектров света, в том числе и не- видимого, — например, инфракрасного диапазона. Фоторезистор Фоторезистор (рис. 12.7, а) под действием света изменяет свое сопротивление. При отсутствии освещения его сопротивление находится в пределах 1-200 МОм, а при освещении — уменьшается на несколько порядков. При этом фоторезистор имеет линейную зависимость сопротивления от освещенности, вследствие чего с его по- мощью удобно измерять освещенность в помещении.
Робот, играющий в кегельринг 191 а б в Рис. 12.7. Фоторезистор (а) и схемы подключения фоторезистора в качестве датчика освещенности (б и в) Недостатками фоторезистора можно назвать достаточно высокое сопротивление и инертность — он не реагирует на изменение освещенности с частотой выше 1 кГц. Но при небольших скоростях движения робота использовать его все-таки можно. Схемы подключения фоторезистора приведены на рис. 12.7, б и 12.7, в. Подсветка фоторезистора светодиодом и размещение их над исследуемой поверхностью орга- низуются таким же образом, как и в случае применения фотодиода. Фототранзистор Фототранзистор (рис. 12.8, а) не только преобразует световой поток в электриче- ский ток, подобно фотодиоду или фоторезистору, но и многократно его усиливает. Визуально фототранзисторы могут не отличаться от фотодиодов, но подключаются и работают иначе. Схемы подключения фототранзисторов приведены на рис. 12.8, б и 12.8, б. Основным преимуществом фототранзистора, как аналогового датчика, пе- ред фотодиодом, представляющим собой пороговый, или цифровой, датчик, являет- ся возможность измерения уровня освещенности, что позволяет при определении цвета объекта фиксировать тона и полутона. Для этого следует подключать анало- говый выход OUT фототранзистора к аналоговым входам контроллера Arduino (А0- А5 или А0-А7 - в зависимости от модели контроллера). При этом робот должен будет экспериментально замерить уровень освещенности на белом фоне и уровень освещенности на черной линии, а затем проанализировать полученные значения в программе.
192 Глава 12 Подсветка фототранзистора светодиодом и размещение их над исследуемой поверх- ностью организуются таким же образом, как и в случае применения фотодиода. а б в Рис. 12.8. Фототранзистор (а) и схемы подключения фототранзистора в качестве датчика освещенности (б и б) Инфракрасный датчик отражения TCRT 5000 В датчике TCRT 5000 (рис. 12.9) использована готовая связка инфракрасного свето- диода и фототранзистора. На его выходах можно получать как аналоговый, так и цифровой сигналы: • цифровой выход датчика можно использовать для определения наличия черной линии, при этом его чувствительность настраивается переменным резистором; • на аналоговом выходе датчика интенсивность отраженного сигнала зависит от типа и цвета поверхности, что также можно использовать для выявления наличия черной линии. При этом надо будет экспериментально замерить уровень освещенности на белом фоне и уровень освещенности на черной линии, а затем проанализировать полученные значения в программе. Цифровой выход датчика TCRT 5000 обозначен на плате «D0», а аналоговый - «АО». Цифровой выход подключается к цифровому порту Arduino D0-D13, а анало- говый — к аналоговому А0-А5/А7. Контакт VCC подключается к питанию 5 В, кон- такт GND — соответственно, к «земле». На плате датчика расположены два светодиода: зеленый, информирующий о нали- чии линии, и красный, информирующий о наличии электропитания.
Робот, играющий в кегельринг 193 Индикатор срабатывания датчика линии (горит зеленым при обнаружении черной линии) Фототранзистор Светодиод инфракрасного спектра (свет невидим глазом) Настройка \ чувствительности датчика Индикатор наличия VCC электропитания Напряжение (красный) питания 5В - GND Отрицательный контакт питания (земля) DO Выход датчика (при обнаружении черного цвета 0, иначе 1) Рис. 12.9. Инфракрасный датчик отражения TCRT 5000 АО Аналоговый выход датчика, напряжение может изменяться от 0 до 5 вольт в зависимости от интенсивности отраженного сигнала Аналоговые порты А0-А7 при программировании в среде Arduino IDE имеют но- мера 14-21. При этом порты А0-А5 могут работать как обычные цифровые порты. Порты А6 и А7 распаяны не на всех платах, и они могут работать только как порты аналогового ввода. В конечном итоге, для определения наличия черной линии мы рекомендуем исполь- зовать именно инфракрасный датчик отражения TCRT 5000, как наиболее удобное и готовое решение. Обнаружение кегли Для обнаружения кегли используется установленный ранее ультразвуковой датчик расстояния на сервомоторе. Предлагается определять только кегли, находящиеся слева от робота, считая, что правая сторона уже исследована или будет исследована после прохождения роботом полного круга. Алгоритм поиска кегли следующий: ро- бот вращает головой влево, постепенно увеличивая угол. После получения данных о препятствии, робот анализирует угол, на который повернута голова, и поворачивает себя на такой же угол, наводясь на кеглю. К сожалению, ультразвуковой сонар имеет широкую диаграмму направленности (около 30 градусов), и его область обнаружения расширяется с увеличением рассто- яния до цели, вследствие чего угол поворота головы не всегда точно укажет на рас- положение кегли. Возможные варианты обнаружения кегли приведены на рис. 12.10,
194 Глава 12 и большинство из них показывают, что объект обнаружен, но, повернув на измерен- ный угол, робот ошибется и проедет мимо (кроме вариантов айв). г д е Рис. 12.10. Варианты обнаружения кегли сонаром Чтобы этого не произошло, потребуется фактически ощупывать кеглю ультразвуко- вым лучом, находить ее края и по краям определять центр цели (рис. 12.11): робот определяет правый край кегли, потом левый, а затем по несложной формуле находит середину. Впрочем, зная расстояние до кегли и ее ширину, можно ограничиться на- хождением одного края цели, - например, правого. Более подробно порядок поиска центра кегли рассмотрен в приведенном далее алго- ритме и реализован в созданной по нему программе (см. разд. «Программа»). Определение цвета кегли Для определения цвета кегли мы воспользуемся датчиком TCRT 5000. Его нужно установить в передней части бампера и направить вперед так, чтобы, подъезжая к кегле, робот имел расстояние между сенсорами датчика и кеглей 2-4 см. Примечание Определять наличие кегли можно было бы детектором препятствия, использованным в гла- ве 11. Принцип его действия позволяет ему реагировать на черные и белые кегли на различном расстоянии — белую он увидит значительно раньше (с большего расстояния), чем черную, что можно использовать при определении цвета кегли: роботу не нужно будет подъезжать к кегле вплотную, и он сможет на расстоянии (возможно, из центра круга) определять, какая перед ним кегля. Это в приведенной здесь программе не реализовано, но может быть ис- пользовано вами при самостоятельной доработке. В подобном случае детектор препятствия должен смотреть вперед и находиться по центру фронтальной плоскости робота.
Робот, играющий в кегельринг 195 / \ / \ / I \ \ [ AngA \ AngB ^ / / / ^ / s' / s' c \ < \ \ Ang^lst ^^*^ \ ^^ \ ^ \ \ \ __J =(AngA+AngB)/2; Рис 12.11. Нахождение центра кегли Коррекция направления движения Из-за неравномерного вращения колес, проскальзывания их на поверхности или торможения кеглей, робота может развернуть, и он после завершения обработки кегли не сможет вернуться в центр круга. Вернее, он не сможет вернуться в центр, если эту ситуацию не проработать. Помочь стабилизировать направление движения робота может черная линия. На рис. 12.12 приведены три возможных варианта на- езда роботом на черную линию: вариант б не требует корректировки, но варианты а и в показывают, что направление робота искажено. Эти искажения покажут и датчи- ки линии: в случае а линию покажет только левый датчик, в случае в — правый. Тогда в варианте а следует поворачивать налево, пока не сработает правый датчик или не перестанет срабатывать левый, а в варианте в следует поворачивать направо, пока не сработает левый датчик или не перестанет срабатывать правый. а б Рис. 12.12. Варианты наезда робота на черную линию
196 Глава 12 Модернизация робота Что ж, датчики выбраны и порядок работы с ними определен — теперь можно при- ступить к модернизации робота для решения поставленных задач. Установка датчиков Этапы установки датчиков показаны на рис. 12.13-12.16. Мы монтируем на робо- та четыре датчика: три датчика TCRT 5000 и один ИК детектор препятствия. Всем датчикам требуется электропитание 5 В и наличие свободного порта в контроллере Arduino. Один центральный датчик TCRT 5000, установленный на верхнем бампере, будет определять цвет кегли, два боковых на нижнем — цвет линии. ИК детектор препят- ствия крепится винтом на нижнем переднем бампере посередине. Справа и слева на этот бампер устанавливаются датчики линии TCRT 5000, их сенсоры (светодиод и фототранзистор) должны быть направлены вниз. Датчики линии, в связи с нестан- дартным их расположением, следует закрепить, используя подручные материалы: изоленту и стяжки или термоклей. Если при электрическом монтаже будет использоваться пайка, то провода к датчи- кам следует припаять предварительно. Клеммные соединения можно произвести и после установки датчиков. Рис. 12.13. Робот и подготовленные датчики
Робот, играющий в кегельринг 197 Рис. 12.14. Установка датчиков Рис. 12.15. Датчики установлены
198 Глава 12 Рис. 12.16. Робот: установлены все четыре датчика Схема соединений На рис. 12.17 представлена схема соединений модернизированного робота, а на рис. 12.18 — принципиальная схема подключения датчиков. Здесь датчики UL1 и UL2 (это датчики TCRT 5000, установленные на нижнем бампере робота) отвечают за обнаружение черной окружности, датчик UL3 (это центральный датчик TCRT 5000, установленный на верхнем бампере робота) определяет цвет кегли. Оставшийся из главы 11 один ИК детектор препятствия UW1 может отвечать за наличие кегли перед роботом и/или определять цвет кегли.
Робот, играющий в кегельринг 199 • Подключение датчиков, работающих в цифровом режиме: UL1 — на 13-й порт Arduino, UW1 — на 12-й порт, UL2 - на 2-й порт. • Подключение датчика, работающего в аналоговом режиме — аналоговый выход АО датчика UL3 нужно подключить к аналоговому порту A3 Arduino, а для ПОЛучеНИЯ ДаННЫХ ИСПОЛЬЗОВаТЬ Команду analogRead (17). Питание датчики берут от модуля драйвера двигателей L298, который содержит ми- кросхему стабилизатора питания на 5 В (рис. 12.19). UL3 UL1 UW1 UL2 Рис. 12.17. Подключение датчиков к Arduino Примечание Вместо датчика UL3 (TCRT 5000) можно использовать простую связку светодиод- фоторезистор, подпаяв к ним пару резисторов. Принципиальная схема подключения такой связки приведена на рис. 12.20. Если датчики линии в вашем арсенале отсутствуют, то их все можно заменить подобными связками или использовать фотодиоды или фототранзисторы по схемам с рис. 12.6 и 12.8.
200 Глава 12 Рис. 12.18. Принципиальная схема подключения датчиков Рис. 12.19. Электропитание датчиков
Робот, играющий в кегельринг 2 О1 Рис. 12.20. Принципиальная схема подключения датчиков (датчик UL3 заменен элементарной сборкой) Программа Алгоритм поиска кегли На рис. 12.21 приведен алгоритм поиска кегли с использованием ультразвукового датчика на поворотной голове.
202 Глава 12 if -Да Нет Нет i I Нет—. Рис. 12.21. Алгоритм поиска кегли
Робот, играющий в кегельринг 203 Робот последовательно перебирает углы с единичным приращением, фиксируя мо- мент, когда цель перестала быть видна для обеих сторон кегли. Затем от этих зна- чений берется среднее. На выходе алгоритма мы получим угол, на который следует повернуться роботу для точного направления на кеглю. Угол i — текущий исследуе- мый, iright — СЛуЖИТ ДЛЯ Хранения угла ПраВОЙ КрОМКИ, ilef t — ЛеВОЙ. Front — угол сервомотора, соответствующий фронтальному направлению. Поскольку дис- танция берется с датчика расстояния, скорость робота должна быть ограниченной, иначе датчик будет сильно ошибаться. Алгоритм взаимодействия с кеглей На рис. 12.22 приведен алгоритм взаимодействия робота с кеглей. Робот получает угол, на который должен повернуть, затем поворачивает, становится напротив кегли, подъезжает к ней и определяет ее цвет. Если кегля черная — возвращается назад. С белой кеглей робот едет до черной ограничительной линии, после чего возвра- щается в центр. Время, затраченное на поездку вперед, фиксируется и используется для определения времени возврата в центр. Конечно, следует помнить, что робот до линии едет в два этапа и имеет некоторое время на торможение и разгон, это время следует учесть дополнительно. Алгоритмы составлены, и можно преобразовать их в программу (листинг 12.1). Листинг 12.1. Программа выбивания кеглей по цвету (белые кегли) // Подключаем библиотеку управления сервомоторами. #include <Servo.h> // Подключаем библиотеку, управляющую дальномером. #include <Ultrasonic.h> // Инициализируем дальномер // Контакт Trig соединен с 5 портом, Echo с б портом. Ultrasonic sonar(5, 6); // Создаем сервомотор поворота головы. Servo neck; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor_Rl, motor_R2, input_R; // Константы - постоянные значения для уточнения углов. const int left_ang = 168;
204 Глава 12 t-Да- -Да-1 Да Рис. 12.22. Алгоритм взаимодействия с кеглей
Робот, играющий в кегельринг 205 const int front_ang = 90; const int right_ang = 28; // Временные константы служат для точного задания времени на поворот, разворот, // движение вперед в миллисекундах. const int time_90 = 390; const mt time_180 = 750; const int time_10cm = 220; // Номера портов, к которым подключены датчики препятствия и линии. // Датчик наличия кегли перед роботом Obstacle. const int Line_left = 2, Obstacle = 12, Line_right = 13; // Порт аналогового датчика цвета. const int black_white_keg = 17; //==================================================== int dist_cmX, dist_cmX_IR; // глобальная дистанция до фишки / /========================= void setup() { // Инициализируем сервомотор, управление 9 портом. neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // pinMode (Line_left, INPUT); pinMode(Obstacle, INPUT); pinMode(Line_right, INPUT); pinMode(black_white_keg, INPUT); // Двигатели запущены. setspeed(255, 255); // Смотрит вперед. neck.write(front_ang); Serial.begin(9600);
206 Глава 12 I I LLt\jLCiJ i\J / / / / void loop() { // Переменные - результаты опроса дотчиков. bool Obstacle_data, Line_left_data, Line_right_data; unsigned int black white keg_data; // Для таймеров, long Timerl, Timer2; // Угол поворота, int Ang; // Поиск кегли. Ang = center_celi(); // Если найдена кегля, if (Ang != 180) { _Povorot(Ang); Timerl = micros(); // Пока нет кегли перед роботом do { setspeed(255, 255) ; forward () ; //К сожалению, датчиком препятствия пользоваться не получилось, // т.к. он по-разному реагировал на кегли различного цвета. //Obstacle_data = digitalRead(Obstacle); Line_left_data = digitalRead(Line_left); Line_right_data = digitalRead(Line_right); //} while (!Obstacle_data && !Line_left_data && !Line_right_data); // Используем сонар, если кегля не перед роботом и он не на линии. } while ((sonar_3() > 410) && (!Line_left_data) && ( !Line_right_data)); _stop(); Timerl = micros() - Timerl;
Робот, играющий в кегельринг 207 delay(50); // Если есть кегля перед роботом. if (sonar_3() < 410) // Данные о цвете кегли, black_white_keg_data = analogRead(black_white_keg) , // Если кегля белая. if (black_white_keg_data < 600) { Timerl = micros() - Timerl; do { forward(); Line_left_data = digitalRead(Line_left); Line right_data = digitalRead(Line_right); } while (!Line_left_data && !Line_right_data); _stop() ; Timerl = micros() - Timerl; // Возврат на центр. Timerl = micros() + Timerl; // Теперь в Timerl время движения вперед. do { backward() ; // Движемся такое же время назад. Timer2 = micros(); } while (Timerl > Timer2); _stop(); setspeed(255, 255); } Povorot (30);
208 Глава 12 //_stop(); // Serial.print("left="); Serial.println(digitalRead(Line_left)); // Serial.print("right="); Serial.println(digitalRead(Line_right)); // Serial.print("keglya_color="); Serial.println(analogRead(black_white_ keg)); //delay(500) ; // Serial.print("dist_cmX="); Serial.println( dist_cmX); } / / //-180/+180 void _Povorot(int ugol) { // Врямя толчка для начала движения, // всегда есть и одинаковое. int tolchok = 9; // настраиваемый коэффициент - время поворота на угол. int k = 4; if (ugol < 0) { right() ; } if (ugol > 0) { left О; } // Время, требуемое на поворот, настраивается экспериментально. delay(abs(ugol)*k + 9) ; // Остановка после достижения требуемого угла. _stop(); //=
Робот, играющий в кегельринг 209 mt center_celi() // точно определяется угол поворота до цели { const int del = 100, del_2 = 50, max_angl = 40, popravka = -9; int dist_botl; int s; int dist_cm = 100, max_i_left, max_i_right, mertvaya_zona; int i = 0; int i_left, i_right; // Максимальная дистанция в единицах измерения, // которые можно перевести в сантиметры, поделив их на 58. dist_botl = 45 * 58;// Дистанция до кегли 45 см. neck.write(front_ang); delay(del); // пока угол меньше max_angl. while (i <= 40) { neck.write(front_ang + i); delay(del); //neck.detach(); delay(5); // Текущая дистанция до препятствия. dist_cm = sonar_3(); dist_cmX = dist_cm; //neck.attach(9); // Serial.print("dist_cm="); // Serial.println(dist_cm)/ i_left = 0, i_right = 0; // если нашли кеглю - ищем ее середину. if (dist cm < dist botl) do
210 Глава П { i_right—; neck.write(front_ang + i + i_right); delay(del_2); //neck.detach(); delay(5); s = sonar_3(); //neck.attach(9); // Пока видна кегля. } while ((dist_botl > s) && (i_right > -40)); neck.write(front_ang + i); delay(del); do neck.write(front_ang + i + i_left); delay(del_2); //neck.detach(); delay(5); // Пока видна кегля. s = sonar 3(); //neck.attach(9); } while ((dist_botl > s) && (i_left < 40)); //Serial.print("i"); //Serial.println(i) ; // Возврат угла поворота (ноль от фронта робота). i = i + popravka + (i_right + i_left) / 2; neck.write(front_ang); // Устанавливаем глобальную переменную расстояния до кегли. dist_cmX = dist_cmX / 58; //sonar.Ranging(CM); neck.write(front_ang) ; //Serial.print("i_left=");
Робот, играющий в кегельринг 211 //Serial.println(i_left); //Serial.print(Mi_right=") ; //Serial.println(i_right); return i; } l += 5; } neck.write(front_ang); // Нет решений - кегля не найдена. Рекомендуемый поворот 45 градусов. dist_cmX = 150; return 180; } / / // Уточненные данные от сонара, // требуется удалить шум, // снять показания 3 раза и рассчитать среднее. int sonar_3() { int si, sO; sO = 0; for (int j = 0; j < 3; j++) { sO = sO + sonar.Timing(); // if (si > sO) sO = si; } return (sO / 3); } / / //Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2. / /=======:===:== ========:============== = ===== = === ========== ====== = = = = = = ===
212 Глава 12 Выводы Здесь мы определили порядок обхода при поиске кеглей. Подобрали датчики для обнаружения черной ограничительной линии, поиска кегли и определения цвета кегли. Разработали порядок наведения робота на кеглю. Описали порядок установки датчиков на роботе и привели схему соединений. Создали алгоритмы и разработали программу, которая позволяет выборочно по цвету выбивать кегли из круга. Цель главы достигнута. Примечание Если после сборки и программирования робот не поехал или делает все шиворот-навыворот, стоит поиграть с временными константами. Если и это не помогло, следует искать ошибки пошагово: 1. Подключите робота к компьютеру и снимите колеса. 2. Закомментируйте весь код в основной программе. 3. Подключая блоки кода по одному, выводите служебную информацию через порт на КОМПЬЮТер, ИСПОЛЬЗуЯ Команды Serial, print () И Senal.prmtlnO. 4. Сверяйте полученную информацию с ожидаемой. В следующем проекте (см. главу 13) мы оснастим робота электронным компасом и научим ориентироваться по нему в пространстве.
ГЛАВА 13 РОБОТ, ДЕРЖАЩИЙ НАПРАВЛЕНИЕ ПО ЭЛЕКТРОННОМУ КОМПАСУ Цель, которую мы ставим себе в этой главе, — научиться применять электронный компас в собственных проектах. Для достижения поставленной цели нам потребуется решить следующие задачи: 1. Понять, как работает электронный компас. 2. Определиться с выбором электронного компаса. 3. Практически применить электронный компас для нахождения северного маг- нитного полюса. 4. Реализовать робота, который способен держать направление движения, исполь- зуя данные электронного компаса. О компасе подробнее Компас — это магнитный прибор. Традиционный компас представляет собой на- магниченную стрелку, посаженную на ось вращения с малым трением. Магнитная стрелка, свободно вращаясь, одним концом поворачивается к северному магнитному полюсу. При этом сам компас нужно держать в руке так, чтобы магнитной стрелке ничего не мешало вращаться. Перестав колебаться, стрелка укажет направление на северный магнитный полюс. Замечание Магнитный и географический северные полюса не совпадают. В настоящее время северный магнитный полюс находится в районе канадской Арктики и ежегодно смещается примерно на 10 километров.
214 Глава13 Электронный компас Подобным образом работает и электронный компас, почти так, но не совсем. Электронный компас состоит из магниторезисторов, изменяющих свое сопротивле- ние под воздействием магнитной силы, или элементов Холла, построенных на осно- ве кремниевых пластин, чувствительных к изменению положения объекта относи- тельно магнитного поля Земли. Для использования в самодельных роботах лучше всего подойдет компас, микро- схема которого уже распаяна на плате. Подобных решений много, самые распро- страненные строятся на основе микросхемы HMC5883L. Эти решения недорогие, но, как правило, не совсем точные. Более дорогие решения на основе микросхем НМС5983, Ак8975 имеют автоматическую калибровку и температурную компенса- цию. Впрочем, для непромышленного, в том числе и нашего, применения вполне до- статочно HMC5883L. Примечание Полное описание микросхемы HMC5883L от производителя можно найти по адресу: http:// www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/ Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf. Подключение Плата HMC5883L (рис. 13.1) содержит стабилизатор питания на 3,3 В и подтяги- вающие резисторы, что позволяет подключать ее напрямую к плате Arduino и к пи- танию 5 или 3,3 В. Обмен данными между HMC5883L и Arduino осуществляется по шине I2C, которая представляет собой последовательный интерфейс. К I2C могут vcc Напряжение питания 3,3-5 В GND Отрицательный контакт питания v ("земля") \^ SCL Контакт шины I2C N. SDA > Контакт >. шины I2C ^\ DRDY Сигнал о готовности компаса после самокалибровки (можно не подключать) Рис. 13.1. Электронный компас HMC5883L на плате
Робот, держащий направление по электронному компасу 215 быть подключены одновременно несколько устройств, одно из которых должно яв- ляться ведущим, а остальные — ведомыми. В нашем случае ведущим будет контрол- лер Arduino, а модуль HMC5883L — ведомым. Каждое устройство на шине I2C име- ет уникальный адрес. Когда ведущий начинает передачу, он передает по шине адрес устройства, к которому выполняется обращение. Устройства, подключенные к шине, проверяют этот адрес, и в случае совпадения начинают обмен информацией. Шина I2C имеет 2 контакта: SCL — вывод тактового сигнала, его задает ведущий, и SDA — передача/прием данных в обоих направлениях. Для работы по шине I2C потребуется соединить контакт SCL компаса с контактом SCL Arduino (порт А5) и контакт SDA компаса с контактом SDA Arduino (порт А4), как показано на рис. 13.2. Кроме обязательных контактов, плата HMC5883L снабжена пятым, необязатель- ным, контактом DRDY, на котором формируется положительный сигнал, когда ком- пас прошел самокалибровку и готов к работе. В нашем роботе мы его использовать не будем, и чтобы уменьшить риск перепутать контакты, впаивать в него разъем не следует. Примечание Как правило, подобные платы поставляются в комплекте с разъемами, к которым следует припаять провода, если вы собираетесь пользоваться разъемными соединениями. Если же вам по душе неразъемное соединение пайкой, то провода припаивать надо непосредственно к контактам платы. Рис. 13.2. Порядок подключения платы HMC5883L к Arduino UNO
216 Глава 13 Организация обмена данными Физического подключения платы HMC5883L к Arduino UNO недостаточно, следует активировать библиотеку wire, отвечающую за обмен данными между устройствами по протоколу I2C. Библиотека wire входит в стандартный пакет библиотек Arduino IDE и может быть подключена непосредственно после установки среды программи- рования (рис. 12.3). Далее можно обратиться к описанию модуля HMC5883L от производителя, ссылка на которое приведена в примечании ранее, но проще воспользоваться готовой би- блиотекой HMC5883L. put yrur Kali*! ссЗе nere, to run repeatedly: Рис. 13.3. Подключение библиотеки Wire
Робот, держащий направление по электронному компасу 217 Примечание Библиотека находится по ссылке http://code.bildr.org/project/HMC5883L/Arduino, а также в соответствующей папке сопровождающего книгу электронного архива. Она пред- ставляет собой удобную оболочку для работы с компасом. Скопируйте файлы HMC5883Lcpp и HMC5883Lh в текущий каталог с вашей программой И Добавьте В Нее Строку #include "HMC5883L . h". Модернизация робота Схема подключения модуля магнитометра (компаса) HMC5883L к роботу приве- дена на рис. 13.4. Согласно этой схеме, питание HMC5883L берет от контакта 3,3 В Arduino, но это не обязательно — можно запитать модуль и от 5 В. Рис. 13.4. Принципиальная схема подключения электронного компаса
218 Глава 13 В схеме подключения мо- торов обязательны кера- мические конденсаторы емкостью 100 нФ — они должны быть установле- ны на клеммах всех четы- рех моторов. Желательно установить подобный конденсатор и в цепь питания сервомото- ра (если это модели sg90 или mg90s), как можно ближе к самому мотору, а лучше всего разобрать сервомотор поворота го- ловы робота и припаять подобный конденсатор прямо на двигатель по- стоянного тока, который расположен внутри серво- мотора (рис. 13.5), — электронный компас будет избавлен от большей части электро- магнитных помех, которые будут «сводить его с ума» в противном случае. Если же проведенные мероприятия не помогли (что редко, но бывает), и при рабо- те двигателей робота (колеса сняты, робот неподвижен) показания прибора силь- но колеблются (более 3 градусов), то с целью дальнейшей защиты от помех плату HMC5883L следует поместить на мачту или полочку высотой 5-10 см. Сделать ее можно из любых подручных материалов — например, из пластиковой или деревян- ной линейки. Важно, чтобы при этом прибор был закреплен в горизонтальном по- ложении. Рис. 13.5. Место установки керамического конденсатора в сервомоторе Примечание И даже после этого HMC5883L может «врать» за счет наводок от различных бытовых и про- мышленных приборов, в которых работают мощные электрические двигатели и генериру- ется электромагнитное поле. Впрочем, и классический магнитный компас в этих ситуациях будет ошибаться. Получение данных от HMC5883L Программа приема данных от HMC5883L (листинг 13.1) основана на стандарт- ном примере, который входит в библиотеку HMC5883L. Программа выводит зна- чение угла отклонения от северного магнитного полюса в градусах. К программе
Робот, держащий направление по электронному компасу 219 подключаются две внешние библиотеки: wire и hmc5883l, создается объект compass, этот объект прикрепляется к физическому адресу датчика HMC5883L (это скрыто в библиотеке нмс588зь.п). В функции setupHMC5883L() задается точность прибора и проверяется правильность его подключения. Функция getcompassango возвра- щает угол отклонения от северного магнитного полюса — эта функция вызывается в программе, и результат ее работы передается по последовательному интерфейсу на компьютер. Каждые полсекунды новые значения угла будут выводиться в порт. Листинг 13.1. Прием данных от HMC5883L и передача их на ПК // Подключаем библиотеку I2C. #include <Wire.h> // Подключаем библиотеку компаса. #include <HMC5883L.h> // Создаем компас. HMC5883L compass; //======================================= void setup(){ // Серийный порт для связи с ПК. Serial.begin(9600); // Запускаем связь по шине I2C. Wire.begin(); // Создаем экземпляр HMC5883L библиотеки. compass = HMC5883L(); // инициализация HMC5883L. setupHMC5883L(); } / /======================================= void loop () { float heading = get_Compass_ang() ; Serial.println(heading); delay(500); } / /======================================= void setupHMC5883L(){
220 Глава 13 I/ инициализация HMC5883L, и проверка наличия ошибок, int error; // чувствительность датчика из диапазона: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1. error = compass.SetScale(0.88); // если ошибка, то выводим ее. if(error != 0) Serial.println(compass.GetErrorText(error)); // установка режима измерений как Continuous (продолжительный). error = compass.SetMeasurementMode(Measurement_Continuous); // если ошибка, то выводим ее. if(error != 0) Serial.println(compass.GetErrorText(error)); } float get_Compass_ang () { // считываем данные с HMC5883L и рассчитываем направление. // получаем масштабированные элементы с датчика. MagnetometerScaled scaled = compass.ReadScaledAxis(); // высчитываем направление. float heading = atan2 (scaled. YAxis, scaled.XAxis) ; // корректируем значения с учетом знаков, //if(heading < 0) heading += 2*PI; //if(heading > 2*PI) heading -= 2*PI; // переводим радианы в градусы, return heading * RAD_TO_DEG; Рисунок 13.6 демонстрирует работу программы для измерения угла от 0 до 360°, а рис. 13.7 - при изменении угла от -180 до +180°, когда строки: if(heading < 0) heading += 2*PI; И if(heading > 2*PI) heading -= 2*PI; закомментированы. Если пускать робота в направление на север, то отслеживать от- клонения от 0 в «+» и «-» удобнее.
Робот, держащий направление по электронному компасу 221 181.96 184.72 184.S4 136.34 1S4.36 183,75 no.cd 235.96 243.73 228.18 346.66 314.48 2S9.5S 29€.5Ч 237.58 285.5Q Рис. 13.6. Работа программы при настройке углов от 0 до 360° -ii. . CjL -5.75 -зле -6.29 -6.10 -4.27 -3.37 -3.4S -6.06 -4.36 -1.68 -0.56 ■3.00 2.14 -3.96 2.63 Рис. 13.7. Работа программы при настройке углов от -180 до 180°
222 Глава 13 Правильная установка магнитометра При установке на робота компас (магнитометр) должен быть точно ориентирован. Для правильной его ориентации нужно знать точное направление на северный маг- нитный полюс. Получить его можно с помощью обычного компаса, или электронно- го компаса в смартфоне, или от самого HMC5883L. Установка модуля компаса на робота осуществляется в несколько этапов: 1. Запустить на выполнение программу (листинг 13.1) и открыть порт для просмо- тра результатов работы магнитометра. 2. Поместить магнитометр на место предполагаемой установки на роботе. 3. Сориентировать робота по направлению на магнитный север. 4. Вращением магнитометра добиться положения, близкого к нулю. 5. Закрепить магнитометр на роботе так, чтобы исключить возможность его сме- щения (рис. 13.8). Теперь робот будет четко ориентироваться по сторонам света. Примечание Несмотря на наличие в плате компаса технологических отверстий для винтового крепления, пользоваться винтами не следует, так как металлические винты внесут дополнительные по- мехи в работу прибора. Закреплять HMC5883L следует при помощи клея или двустороннего скотча. Рис. 13.8. Вариант установки на робота платы магнитометра HMC5883L
Робот, держащий направление по электронному компасу 223 Программа Теперь можно приступить к разработке программы движения робота. На рис. 13.9 приведен алгоритм, отвечающий за движение робота в направлении на север, — ро- бот ищет северный магнитный полюс и разворачивается к нему. Нет" i г Да Ждать 50 м.сек. Остановиться Ждать 10 м. сш, {стабилизируем т Получить угол отклонения от заданного ComDass эгщ "Да 1 Нет Рис. 13.9. Алгоритм поворота робота на северный магнитный полюс
224 Глава 13 В листинге 13.2 приведена программа, реализующая этот алгоритм. В ней дополни- тельно предусмотрено, что робот должен объезжать препятствия: робот движется на север, пока нет препятствий, а при появлении препятствия, пытается его объехать и вернуться к намеченному маршруту. Листинг 13.2. Программа движения робота в северном направлении #include <Wire.h> #include <HMC5883L.h> // Подключаем библиотеку для создания дополнительных // последовательных (Serial) портов. #include <SoftwareSerial.h> // Подключаем библиотеку управления сервомоторами. #include <Servo.h> // Подключаем библиотеку, управляющую дальномером. #include <Ultrasonic.h> // Инициализируем дальномер // Контакт Trig соединен с 5 портом, Echo с 6 портом. Ultrasonic sonar(5, 6); // Создаем сервомотор поворота головы. Servo neck; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor_Rl, motor_R2, input_R; // Константы - постоянные значения для уточнения углов. const int left_ang = 168; const int front_ang = 98; const int right_ang = 28; // Временные константы служат для точного задания времени //на поворот, разворот, движение вперед //в миллисекундах. const int time_90 = 390; const int time_180 = 750; const int time_10cm = 220; // Номера портов, к которым подключены датчики препятствия.
Робот, держащий направление по электронному компасу 225 const int Frontl = 2, Front2 = 12, Right = 13; // Создан объект compass для обращения к устройству HMC5883L. HMC5883L compass; void setup () { // Инициализируем сервомотор, управление 9 портом. //neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 11, 7, 8, 10); // Инициализируем порты датчиков препятствия. pinMode(Frontl, INPUT); pinMode(Front2, INPUT); pinMode(Right, INPUT); // Двигатели запущены. setspeed(255, 255); compass = HMC5883L (); // создаем экземпляр HMC5883L библиотеки setupHMC5883L(); // инициализация HMC5883L // Устанавливаем скорость передачи данных по кабелю. // Порт компьютера Serial.begin(9600); } // Основная программа, void loop () // Создаем переменные для хранения трех дистанций - слева, впереди, справа, int Dist_left, Dist_front, Dist_right; float Compass_ang; setspeed(255, 255); _stop() ;
226 Глава 13 Compass_ang = get_Compass_ang() ; while ((Compass_ang > 5) && (Compass_ang < 355)) { if (Compass_ang <= 180) { left(); // Влево. } else { right();// Вправо. } delay(50); _stop() ; delay(10); Compass_ang = get_Compass_ang(); } // Анализ обстановки на наличие препятствий. // Поворот головы налево, neck.write(left_ang); // Ждет, так как поворот занимает небольшое время, delay(150); // Записывает расстояние до препятствия слева. Dist_left = sonar.Ranging(CM); // Поворачивает голову прямо вперед, neck.write(front_ang); // Ждет, так как поворот занимает небольшое время, delay(150); // Записывает расстояние до препятствия впереди. Dist_front = sonar.Ranging(CM); // Поворачивает голову направо, neck.write(right_ang); // Ждет, так как поворот занимает небольшое время, delay(150); // Записывает расстояние до препятствия справа.
Робот, держащий направление по электронному компасу 227 Dist_right = sonar.Ranging(CM); neck.write(left_ang); if (Dist_front > 20) { forward(); // едем вперед. } else if ((Dist_left > 20) || (Dist_right > 20)) { (Dist_left > Dist_right) { left(); // поворачиваем налево 0,5 секунд. delay(time_90); } else { right(); // поворачиваем направо 0,5 секунд. delay(time_90); forward(); // едем вперед 0.5 секунды. delay(time_10cm * 2); } else // Заехал в тупик. { backward(); delay(time_10cm); _stop(); neck.write(left_ang); // Ждет, так как поворот занимает небольшое время. delay(150); // Записывает расстояние до препятствия слева. Dist_left = sonar.Ranging(CM); // Поворачивает голову направо. neck.write(right_ang); // Ждет, так как поворот занимает небольшое время. delay(200) ; // Записывает расстояние до препятствия справа.
228 Глава 13 Dist_right = sonar.Ranging(CM); // Настройка компаса HMC5883L. void setupHMC5883L(){ // инициализация HMC5883L, и проверка наличия ошибок. int error; // чувствительность датчика из диапазона: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1. error = compass.SetScale(0.88); // если ошибка, то выводим ее. if(error != 0) Serial.println(compass.GetErrorText(error)); // установка режима измерений как Continuous (продолжительный). error = compass.SetMeasurementMode(Measurement_Continuous); // если ошибка, то выводим ее. if(error != 0) Serial.println(compass.GetErrorText(error)); } //====== Получение данных от компаса. float get_Compass_ang() { // считываем данные с HMC5883L и рассчитываем направление. // получаем масштабированные элементы с датчика. MagnetometerScaled scaled = compass.ReadScaledAxis(); // высчитываем направление. float heading = atan2 (scaled. YAxis, scaled.XAxis); // корректируем значения с учетом знаков. if(heading < 0) heading += 2*PI; if(heading > 2*PI) heading -= 2*PI; // переводим радианы в градусы. return heading * RAD_TO_DEG; } / / //Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2.
Робот, держащий направление по электронному компасу 229 Калибровка Хотя магнитометр HMC5883L не является высокоточным прибором, его, тем не ме- нее, устанавливают в большинство современных смартфонов. Увеличить точность показаний магнитометра можно, проведя его калибровку (корректировку). Примечание По адресу http://www.vectornav.com/support/library/magnetometer находится инте- ресная статья на этот счет — она на английском языке, но довольно легко читается. Показания магнитометра нужно корректировать с учетом, к примеру, температуры. В то же время подобными корректировками можно не только исправить ошибки определения, но и внести новые. Например, вами внесены корректировки, исходя из магнитной обстановки дома, а запускать робота планируется в другом месте, с другой магнитной обстановкой (другими магнитными помехами), — в этом случае сделанные корректировки еще больше запутают электронный компас робота. В главе 14 мы рассмотрим гироскоп-акселерометр MPU-6050, имеющий температур- ный датчик, который подходит для температурной корректировки магнитометра. Однако такие процедуры уже выходят за пределы понятия «простые роботы» и рам- ки нашей книги. Выводы В этой главе нами изучена работа электронного компаса. Для его реализации выбран магнитометр HMC5883L, создано его подключение к Arduino и организован обмен данными между ними. Модернизированный таким образом робот способен держать направление движения на север, используя показания электронного компаса. Следующий проект (см. главу 14) предоставляет нам еще большую свободу для твор- чества. Он посвящен интересной теме ориентации робота в пространстве с исполь- зованием гироскопа и акселерометра, и в нем мы отойдем от концепции четырехко- лесной платформы.
ГЛАВА 14 БАЛАНСИРУЮЩИЙ РОБОТ Балансирующий робот должен уметь ездить всего на двух колесах и держать при этом равновесие. Сконструировать его можно разными способами. Например, ис- пользовать большие колеса и сместить центр тяжести ниже их осей — при этом ро- бот будет держать равновесие, практически как игрушка-неваляшка. Можно сделать робота с датчиками препятствия спереди и сзади и заставить его балансировать в зависимости от наклона и соответствующей реакции одного из датчиков. Можно еще что-нибудь придумать. Мы же оснастим балансирующего робота электронными гироскопом и акселероме- тром, а попутно раскроем принцип действия этих приборов. Для достижения поставленной цели нам потребуется решить следующие задачи: 1. Понять принцип работы гироскопа. 2. Понять принцип работы акселерометра. 3. Разобраться в различиях электронного и классического гироскопов. 4. Подключить электронный гироскоп-акселерометр MPU-6050 к Arduino. 5. Научиться получать данные с гироскопа-акселерометра MPU-6050. 6. Сконструировать балансирующего робота, в основу балансировки которого по- ложена информация от гироскопа-акселерометра MPU-6050. 7. Написать для робота программу, которая, используя данные, полученные с MPU-6050, заставляет двухколесного робота сохранять равновесие.
232 Глава 14 Гироскоп Гироскоп — это прибор, способный реагировать на изменение ориентации объекта. Простейшим примером гироскопа является волчок. Если волчок раскрутить на пере- мещаемой поверхности — например, на доске (рис. 14.1, а), а затем наклонять эту доску (рис. 14.1, б и в), то волчок будет пытаться сохранить свою ориентацию. а 6 в Рис. 14.1. Эффект гироскопа на примере волчка Гироскоп был изобретен в начале XIX века, и в конце того же века его впервые при- менили на практике для стабилизации курса торпед. Более подробно о гироскопах можно узнать из специализированной литературы. Нам же пока необходимо знать о нем лишь то, что гироскоп позволяет отследить углы отклонения устройства, на ко- тором он установлен, от первоначального положения. Гироскопы бывают как одно- осевыми, так и трехосевыми — позволяющими получать данные сразу по трем осям. Различаются они по типам на роторные (классические гироскопы), вибрационные (сохраняющие направления своих колебаний) и оптические. На рис. 14.2 показано, как можно измерить отклонение машинки от первоначального направления с помощью гироскопа. Черная стрелка — вектор движения, штрихован- ная — показания гироскопа. В позиции б машинка повернула, но стрелка гироскопа осталась на месте и указывает на заданное при включении гироскопа направление. Зная ее отклонение, без труда можно скорректировать направление, но только на- правление, — гироскоп ничего не знает о пройденном расстоянии и о том, по какому маршруту это расстояние было пройдено. Акселерометр Акселерометр служит для измерения ускорения. С его помощью можно измерять ускорение движущегося тела и, используя простые формулы, определять положение тела в пространстве. Например, если знать начальную скорость и считывать ускоре- ние в равные малые промежутки времени, несложно вычислить пройденное расстоя- ние (рис. 14.3). Рассмотрим это на примере прямолинейного движения:
Балансирующий робот 233 Рис. 14.2. Применение гироскопа для измерения угла поворота L1 L2 Рис. 14.3. Применение акселерометра при измерении пройденного расстояния 2ll, (14.1) где I, — расстояние, пройденное ранее, L2 — итоговое расстояние, А/ — прира- щение времени (время движения машинки от А до Б), F, — начальная скорость (в точке А), а2 — полученное от акселерометра ускорение (полагаем на отрезке А-Б ускорение постоянным). Точность измерения расстояния зависит от частоты сбора данных и от вычислительных способностей процессора. Второе предназначение акселерометра — это нахождение углов отклонения объекта от вертикали. Для точного измерения объект должен быть неподвижен или двигать- ся прямолинейно без ускорения. В этом случае на него действует только сила при- тяжения, направленная к центру Земли.
234 Глава 14 Проекция g на ось Y Ускорение свободного падения 9 Рис. 14.4. Нахождение угла отклонения от вертикали (робот неподвижен) На рис. 14.4 изображен неподвижный объект (робот) на наклонной плоскости. Координатная ось У акселерометра робота направлена вперед, ось Z — вниз под пря- мым углом к наклонной плоскости, ось X — к наблюдателю. Искомый угол отклоне- ния объекта от вертикали Ang^ находится по формуле: = arctg рЧ, (14.2) где aY — проекция ускорения свободного падения на ось У акселерометра, az — про- екция на ось Z. Можно также использовать формулы: = arcsin — или ^[«gyz=arccos -2- L U ) где g - ускорение свободного падения, но для электронного прибора, который бу- дет рассмотрен далее, рекомендуется использовать формулу (14.2), оперирующую только относительными величинами.
Балансирующий робот 235 Электронный гироскоп Электронный гироскоп серьезно отличается от классического - он вообще не по- казывает угол отклонения от заданного направления. Электронный гироскоп — это прибор, регистрирующий и возвращающий текущую угловую скорость (скорость вращения). Зная мгновенную угловую скорость, можно вычислить угол, на который повернется объект за некоторый промежуток времени: Ang^Ang^+AtxV^ (14.3) где Angx — начальный угол, рассчитанный ранее, At — малый промежуток времени, на котором можно считать, что угловая скорость не менялась, Vang — полученное от электронного гироскопа в течение At значение угловой скорости, Ang2 — рассчи- танный угол, на который повернулся объект вокруг исследуемой оси с начала пово- рота. На рис. 14.5 вращение происходит вокруг оси Z. Показания гироскопа именно по этой оси следует использовать в расчетах. Рис. 14.5. Расчет угла поворота по показаниям электронного гироскопа Подключение гироскопа-акселерометра MPU-6050 На рис. 14.6 изображена микросхема гироскопа-акселерометра MPU-6050, уста- новленная на печатную плату, что позволяет удобно его подключать. На плате име- ется 8 контактов, но для работы достаточно подключить 4 из них: VCC — питание 3,3 В (возьмем от платы Arduino), GND — «земля» (подключим к любому нулевому
236 Глава М VCC Напряжение питания 3,3-5 В GND Отрицательный ____ контакт питания ("земля") SCL Контакт ^ шины I2C SDA Контакт шины I2C XDA и XCL - служат для подключения к шине !2С дополнительных устройств (не используются) ADO - изменяет адресацию (не используется) INT - настраиваемый сигнал о событии, например, о переполнении буфера (использовать не обязательно) Индикатор наличия электропитания Рис. 14.6. Микросхема гироскопа-акселерометра MPU-6050, смонтированная на плате Рис 14.7. Схема подключения MPU-6050 к Arduino UNO
Балансирующий робот 237 проводу), SDA и SCL — контакты шины I2C, знакомой нам по главе 12 (подключаем их к соответствующим портам Arduino: А4 — SDA и А5 —SCL). Имеется на плате так- же информационный красный светодиод, сигнализирующий о наличии питающего напряжения. Схема подключения MPU-6050 к Arduino приведена на рис. 14.7. Она схожа со схе- мой подключения цифрового магнитометра-компаса HMC5883L. Оба эти устройства можно использовать одновременно и даже подключить их параллельно на одни и те же порты Arduino. В таком случае контроллер Arduino должен выступать в качестве ведущего шины и разрешать устройствам передачу информации поочередно. Получение данных с MPU-6050 Листинг 14.1 реализует функцию получения и вывода данных от гироскопа-аксе- лерометра MPU-6050. Его показания считываются с устройства и выводятся через порт на компьютер: • на рис. 14.8 представлены показания устройства, когда его ось У приблизительно совпадает с вертикалью и направлена вниз, при этом показания по этой оси наибольшие по модулю: -16340...-16220; • на рис. 14.9 представлены показания устройства, когда его ось Z вертикальна и направлена вверх, — в этом случае наибольшие показания акселерометра снимаются по оси Z: 14804... 15148. При вращении устройства изменяются проекции ускорения свободного падения на его оси. В первом случае максимальна проекция на ось 7, во втором — на ось Z. Показания устройства выводятся в относительных единицах, и их можно использо- вать для нахождения угла отклонения от вертикали по формуле (14.2). Листинг 14.1. Получение данных от MPU-6050 // Библиотека для работы с протоколом I2C (порты A5/SCL и A4/SDA) #include <Wire.h> const int MPU_addr = 0x68; // упрощенный // 12С-адрес нашего гироскопа/акселерометра MPU-6050. // переменные для хранения данных, возвращаемых прибором. intl6_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; void setup() { Wire.begin();
238 Глава 14 Wire.beginTransmission(MPU_addr); // Производим запись в регистр энергосбережения MPU-6050 Wire.write(ОхбВ); Wire.write(0); // устанавливаем его в ноль. Wire.endTransmission(true); Serial.begin(9600) ; // ндидттп void loop() { Wire.beginTransmission(MPU_addr); // Готовим для чтения регистры с адреса ОхЗВ. Wire.write(ОхЗВ); Wire.endTransmission(false); // Запрос состояния 14 регистров. GyX«-260 GyY=lQ3 GyZ=*-3S AcX«4 AcY-16312 AcZ«~12$2 GyX»-235 GyY»101 Gy2=-9€ AcX»92 AcY-l€3€0 Ac2»-1312 GyX=~218 GyY=96 Gy2=-55 AcX-€4 AcY-16316 Ac2«-1368 GyX*=-243 GyY=8? GyZ=-98 AcX«4 Ac GyX*~23S GyY=95 GyZ«-70 AcX*-28 AcY*16220 AcZ«-13?2 GyX— 236 GyY»93 Gy2*-96 AcX=4£ AcY«16272 Ac2*-1364 GyX*-225 GyY»93 Gy2«-75 AcX-20 AcY=l€340 Ac2=-12S0 GyX«-256 GyY*100 Gy2=-S7 AcX=-32 AcY*1630S Ac2=-12€0 GyX=-240 GyY«8€ GyZ—104 AcX«-24 AcY»i€21€ Ac2«-1472 GyX«-239 GyY=87 GyZ—101 Рис. 14.8. Ось /акселерометра перпендикулярна горизонту
Ьолансирующий робот 239 Wire.requestFrom(MPU_addr, 14, true); // ОхЗВ (ACCEL_XOUT_H) & ОхЗС (ACCEL_XOUT_L) AcX = Wire.read() « 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & ОхЗЕ (ACCEL_YOUT_L) AcY = Wire.read() « 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) AcZ - Wire.read() « 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) Tmp = Wire.read() « 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyX = Wire.read() « 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyY = Wire.read() « 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) GyZ = Wire.read() « 8 | Wire.read(); GyX*-2S2 GyY=S9 GyZ»-113 GyX—283 GyY=S5 GyZ—109 AcX»1320 AcY=-320 Ac2=150€8 GyX«-lfi7 GyY*85 GyZ*-80 GyX«-2Sl GyY*13€ Gy2=-30 AcX*1320 AcY«-292 Ac GyX=-429 GyY»106 GyZ*-108 AcX-1280 AcY«-?^€ AcZ~!5Q56 GyX*-289 GyY*114 Gy2»-S€ AcX=i34S AcY*-604 Ac2=14992 GyX»-349 GyY=S3 GyZ*-lQl AcX-1372 AcY^-584 AcZ«15I4S GyX—205 GyY=104 GyZ=-8G AcX=140S AcY=«84O AcZ«150€0 GyX*-234 GyY=r£? GyZ=-9S AcX-1360 AcY=-824 AcZ=14804 GyY*107 Рис. 14.9. Ось Z акселерометра перпендикулярна горизонту
240 Глава Ц Вывод в порт данных, полученных от прибора. Serial.print(" АсХ=") Serial.print(" AcY=") Serial.print(" AcZ=") Serial.print(" GyX=") Serial.print(" GyY=") Serial.print(" GyZ=") delay(lOOO); Serial.print(AcX); Serial.print(AcY) ; Serial.println(AcZ) , Serial.print(GyX); Serial.print(GyY); Serial.println(GyZ) , Следует заметить, что даже при полной неподвижности робота показания гироскопа- акселерометра не постоянные, а колеблются вокруг некоторых средних значений. Для повышения точности показаний рекомендуется эти средние значения опреде- лить экспериментально, а затем ввести в расчеты. Для этого следует до начала ра- боты с прибором некоторое время держать его в неподвижном состоянии, собирая показания его угловой скорости, рассчитать среднее значение, а затем эту величину постоянно вычитать из полученных от прибора данных. Возможен также темпера- турный дрейф данных — тогда погрешность будет зависеть и от температуры, что учесть можно, но сложнее. Шкала значений MPU-6050 Как показания прибора из относительных единиц перевести в привычные величи- ны? Для ответа на этот вопрос следует обратиться к документации. На сайте произ- водителя InvenSense (www.invensense.com) представлена таблица основных харак- теристик MPU-6050 (рис. 14.10). В частности, чтобы перевести показания гироскопа в градус/сек, их требуется поделить на 131. Для перевода ускорения в привычную для нас систему мер требуется поделить показания прибора на 16384, а затем умно- жить на 9,8 м/с2. Рис. 14.10. Основные характеристики MPU-6050
Балансирующий робот 241 Сборка балансирующего робота Схема подключения Ознакомившись с работой MPU-6050, можно приступать к сборке робота. Полная его схема приведена на рис. 14.11. Берем два мотора с редукторами и плату Arduino из предыдущих проектов, а в качестве драйвера двигателей вместо модуля L298 можно использовать микросхему L293D (см. рис. 6.1) с радиатором. Выводы EN1 и EN2 этой микросхемы можно посадить на питание 5 вольт, подав на них тем самым постоянную единицу, или подключить их к портам D10 и D11 платы Arduino. Саму микросхему Рис. 14.11. Полная схема балансирующего робота
242 ' Глава 14 L293D желательно припаять на жестяную подложку, используя для этого контакты GND, которые одновременно выполняют функцию теплоотвода. Логическое пита- ние 5 В для L293D рекомендуется подавать от отдельного стабилизатора питания, собранного, например, на микросхеме стабилизатора L7805CV (см. рис. 3.4) — это позволит избежать нагрузки на стабилизатор питания Arduino, особенно если ис- пользовать Arduino Nano со слабым стабилизатором. Оснастим робота информаци- онным красным светодиодом LED1, информирующем о его готовности. На клеммы моторов припаяем керамические конденсаторы — без них электромагнитные поме- хи от работающих двигателей будут мешать работе электроники робота. Конструкция На рис. 14.12 показан сам робот, участвующий в испытаниях. Следует заметить, что чем выше центр тяжести такого робота, тем он устойчивее, что на первый Рис. 14.12. Балансирующий робот с низким центром тяжести
Балансирующий робот 243 взгляд парадоксально, в сравнении со всем известной игрушкой ванька-встанька. Устойчивость робота растет за счет увеличения момента инерции — он падает мед- леннее, а значит, момент начала падения легче отследить и компенсировать. Поэтому тяжелые аккумуляторы можно перенести в его верхнюю часть (рис. 14.13). Рис. 14.13. Балансирующий робот со смещенным вверх центром тяжести
244 Глава И Рис. 14.14. Сборка нижней части корпуса робота Рис. 14.15. Сборка верхней части корпуса робота
Балансирующий робот 245 Корпус робота смоделирован в инженерном пакете, а ^атем вырезан из 3-мм фане- ры. Его конструкция настолько проста, что он и без моделирования легко собирается из подручных материалов. Процесс сборки робота представлен на рис. 14.14-14.16. Рис. 14.16. Завершение сборки робота: установка двигателей и колес
246 Глава 14 Программирование Рассмотрим несколько возможных программ для балансирующего робота. Программа на показаниях гироскопа Первая программа (листинг 14.2) анализирует угловую скорость вращения во- круг оси X и стремится снизить ее до нуля. Когда робот начинает падать, ему дается команда двигаться в направлении падения, компенсируя наклон. Когда робот встает прямо, его моторы выключаются (рис. 14.17). На практике робот не может стоять неподвижно и вынужден непрерывно балансировать, как клоун в цирке на одноко- лесном велосипеде. тшш шштт Рис. 14.17. Демонстрация поведения робота
Балансирующий робот 247 Листинг 14.2. Программа балансировки на основе анализа показаний гироскопа // Библиотека для работы с протоколом I2C (порты A5/SCL и A4/SDA) #include <Wire.h> // Упрощенный 12С-адрес нашего гироскопа/акселерометра MPU-6050. const int MPU_addr = 0x68; // Переменные для хранения данных, возвращаемых прибором. intl6_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; long GyXsum; // Переменные для хранения состояния двух моторов. int motor_Ll, motor_L2; int motor_Rl, motor_R2; //========================================================== void setup() { // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 7, 8); // Двигатели остановлены. // Инициализация MPU-6050. Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); Wire.write(0) ; Wire.endTransmission(true) ; Serial.begin(9600) ; _stop() ; GyXsum =0; / / // Основная программа, void loop()
248 Глава 14 const long compensatorX = -257; Wire.beginTransmission(MPU_addr); Wire.write(ОхЗВ); // Готовим для чтения регистры с адреса ОхЗВ. Wire.endTransmission(false); Wire.requestFrom(MPU_addr, 14, true); AcX = Wire, read () « 8 | Wire.readO; AcY = Wire.readO « 8 | Wire.readO; AcZ - Wire.readO « 8 | Wire.readO; Tmp = Wire.readO « 8 | Wire.readO; GyX = Wire.readO « 8 | Wire.readO; GyY = Wire.readO « 8 | Wire.readO; GyZ = Wire.readO « 8 | Wire.readO; GyXsum = GyXsum + (long)GyX - compensatorX; if (GyXsum > 10) { forward(); else if (GyXsum < -10) backward(); else stop(); // Функция инициализации управления моторами. void setup_motor system(int LI, int L2, int Rl, int R2) { // Заносим в переменные номера контактов (пинов) Arduino. motor_Ll = LI; motor L2 = L2; // Для левых и правых моторов машинки. motor_Rl = Rl; motor_R2 = R2; // Переводим указанные порты в состояние вывода данных. pinMode(motor_Ll, OUTPUT); pinMode(motor_L2, OUTPUT);
Балансирующий робот 249 pinMode(motor_Rl, OUTPUT); pinMode(motor_R2, OUTPUT); // движение вперед. void forward() { // Если двигатель будет работать не в ту сторону, // поменять на нем контакты местами. digitalWrite(motor_Ll, HIGH); digitalWrite(motor_L2, LOW); digitalWrite(motor_Rl, HIGH); digitalWrite(motor_R2, LOW); // Включаем движение назад. void backward () { // Меняем направление вращения двигателей. digitalWrite(motor_L2, HIGH); digitalWrite(motor_Ll, LOW); digitalWrite(motor_R2, HIGH); digitalWrite(motor_Rl, LOW); } void _stop() { // Блокируем все колеса. digitalWrite(motor_L2, LOW); digitalWrite(motor_Ll, LOW); digitalWrite(motor_R2, LOW); digitalWrite(motor_Rl, LOW);
250 Глава 14 Алгоритм работы программы из листинга 14.2 довольно прост (рис. 14.18). Считая, что временные интервалы между опросами гироскопа одинаковые, будем опериро- вать напрямую с данными, поступающими от MPU-6050. При неподвижном робо- те гироскоп показывает ненулевые значения угловой скорости. Чтобы учесть такое смещение нуля, введем специальный компенсатор (compensatorx). Следует подо- брать для него такое значение, чтобы вычисляемая угловая скорость неподвижного робота была равна нулю. Практически это реализовать довольно сложно, но реакция робота в целом верная - при падении он пытается вернуть себя в начальное положение. Начало compensatorX= - 257; GyXsum =0; 1 t Получить данные от гироскопа. Угловую скорость вокруг оси X: GyX GyXsum =GyXsum+GyX+compensatorX; Рис. 14.18. Алгоритм программы балансировки на основе анализа показаний гироскопа
Балансирующий робот 251 Программа с фильтром Калмана Для написания второй программы применим немного математики. Чаще всего для решения задач обеспечения устойчивости используют фильтр Калмана. Фильтр Калмана — это рекурсивный фильтр, который оценивает текущее состояние динамической системы, используя данные, содержащие помехи. Фильтр Калмана успешно сглаживает скачки, преобразуя показания о состоянии системы к предска- зуемым величинам. Он учитывает предыдущие показания и генерирует сглаженное текущее значение. Алгоритм разбит на два этапа. Первый этап — прогнозирование, фильтр экстрапо- лирует значения переменных состояния и их неопределенности. Во время второго этапа результат уточняется на основании полученных измерений. На сайте https://github.com/TKJElectronics/KalmanFilter разработчик Kristian Lauszus выложил свою реализацию библиотеки фильтра Калмана (рис. 14.19). Следует скачать файлы, обозначенные стрелками, и положить их в папку с програм- мой из листинга 14.3. Developed by Kristian Lauszus, TKJ Electronics 2012 Рис. 14.19. Библиотека фильтра Калмана на сайте
252 Глава 14 Примечание Папка Kalman, содержащая нужные файлы библиотеки фильтра Калмана, также находится в составе электронного архива, сопровождающего книгу, — при использовании входящего в нее файла kalman.h, файл kalman cpp вам не понадобится. Начало Установка коэффициентов фильтра Калмана kalmanX setQangle(O 001),kalmanX setQbias(O 003);kalmanX.setRmeasure(0 03), Установка начальных углов для фильтра kalmanX.setAngle(O), kalmanYsetAngle(O); Получить данные от гироскопа, угловую скорость вокруг оси X GyX Получить данные от акселерометра- ускорения по осям AcY, AcZ. Склонение по показаниям акселерометра accXangle = (atan2(AcY, AcZ)) * RAD_TO_DEG; Перевести угловую скорость в градусы/сек. gyroXrate= - ((double)GyX/131,0); Обработка данных фильтром Калмана kalAngleX = kalmanXgetAngle(accXangle, gyroXrate.dt); Ехать вперед Рис. 14.20. Алгоритм программы балансировки с использованием фильтра Калмана
Балансирующий робот 253 Пусть MPU-6050 расположен на роботе так, что его ось Y направлена вперед, а ось X — вправо по отношению к ходу робота (оси изображены на плате прибора). Тогда для балансировки робота с использованием фильтра Калмана потребуется снимать с MPU-6050 три значения: ускорения по осям Y и Z и угловую скорость по оси X. Пользуясь формулой (14.2), находим угол склонения по данным акселеро- метра (угол нужно будет перевести из радиан в градусы). Затем вызывается фильтр Калмана с входными параметрами: угол склонения по данным акселерометра, от- рицательная угловая скорость по оси X (приведенная к градусам в секунду) и при- ращение времени (рис. 14.20). Листинг 14.3. Программа балансировки с использованием фильтра Калмана #include <Kalman.h> // Библиотека для работы с протоколом I2C (порты A5/SCL и A4/SDA) #include <Wire.h> // упрощенный 12С-адрес нашего гироскопа/акселерометра MPU-6050. const int MPU_addr = 0x68; // Переменные для хранения данных, возвращаемых прибором. intl6_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; long AcYsum, GyXsum; // Переменные для хранения состояния двух моторов. int motor_Ll, motor L2; int motor_Rl, motor_R2; int s_diod = 5; // Переменные для хранения данных времени работы контроллера Arduino. unsigned long time_data_request, time_in_system; // Время, через которое производится опрос гироскопа/акселерометра. const unsigned long time step = 10; uint32_t timer; double accXangle; // Угол, посчитанный по акселерометру. double gyroXangle ; // Угол, посчитанный по гироскопу. double gyroXrate; // Приращение угла по показаниям гироскопа. // Результирующий угол после обработки фильтром Калмана. double kalAngleX ; Kalman kalmanX; Kalman kalmanY; //=======================================z== = z==z===============
254 Глава 14 void setup() { // Коэффициенты для фильтра Калмана. kalmanX.setQangle(0.001); kalmanX.setQbias(0.003); kalmanX.setRmeasure(0.03); // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 7, 8); // Двигатели остановлены. _stop() ; Wire.begin (); Wire.beginTransmission(MPU_addr); // Запись в регистр энергосбережения MPU-6050. Wire.write(ОхбВ); Wire.write(0); // установить его в ноль Wire.endTransmission(true); Serial.begin(9600); pinMode(s_diod, OUTPUT); digitalWrite(s_diod, LOW); delay(200); digitalWrite(s_diod, HIGH); _stop() ; kalmanX.setAngle(0); // Начальные углы. kalmanY.setAngle(0); timer = micros(); } / / // Основная программа, void loop() { while (true) { Wire.beginTransmission(MPU_addr); Wire.write(ОхЗВ); // Готовим для чтения регистры с адреса ОхЗВ. Wire.endTransmission(false);
Балансирующий робот 255 // Запрос 14 регистров. Wire.requestFrom(MPU_addr, 14, true); // ОхЗВ (ACCEL_XOUT_H) & ОхЗС (ACCEL_XOUT_L) AcX = Wire.read() « 8 | Wire.readO; // 0x3D (ACCEL_YOUT_H) & ОхЗЕ (ACCEL_YOUT_L) AcY = Wire.read() « 8 | Wire.readO; // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) AcZ = Wire.read() « 8 | Wire.readO; // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) Tmp = Wire.read() « 8 | Wire.readO; // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyX = Wire.readO « 8 | Wire.readO; // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyY - Wire.readO « 8 | Wire.readO; // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) GyZ = Wire.readO « 8 | Wire.readO; // Расчет угла по показаниям акселерометра. accXangle = (atan2(AcY, AcZ)) * RAD_TO_DEG; // Расчет приращения угла по гироскопу. gyroXrate = -((double)GyX / 131.0); // Обработка данных фильтром Калмана. kalAngleX = kalmanX.getAngle (accXangle, gyroXrate, (float) ( micros () - timer)/1000000.0); timer = micros(); // Компенсируем наклон if (kalAngleX > 2.0) { forward(); } else if (kalAngleX < -2.0) { backward(); } else { _stop() ;
256 Глава И // delay(500); // Serial.print("kalAngleX="); Serial.println(kalAngleX); // Функции setup_motor_system(), fоrward(),backward() и _stop() взять из листинга 14.2 ЕСЛИ раскомментировать СТрОКИ: delay (500) ;, Serial, print («kalAngleX=») ; И Serial, println (kalAngleX) ;, ВЫКЛЮЧИТЬ ОСНОВНОе ПИТаНИе (ИЛИ СНЯТЬ КОЛеса) и подключить робота к компьютеру, можно будет следить за изменением угла накло- на робота через окно порта (рис. 14.21). Угол, рассчитанный программой, визуально совпадает с заданным углом (углом наклона робота). В результате испытаний робота с фильтром Калмана было замечено, что фильтр ра- ботает, показания плавные, но они отстают от реальности, что приводит к тому, что реакция моторов становится неверной. Более детальное исследование работы фильтра подтвердило, что контроллеру Arduino при математических расчетах не хватает скорости... kalAngleX-~4.00 \ kaiAng 1 е\=-20 .00 kalAngleX»12.00 fcaiAngleX~€.0G kalAngleX=2.Co ikaIAngieX=5.QG jfcaiAngleX*3.S2 jkdlAncfleX=2. = * jkalAngleX«1.00 j |fcaIAngieX=15,00 |kalAngleX=24.00 ifcaiAngleX=31.I6 fcaiAngleX-39.00 =-22 ЛЭ kalAngleX=-l€.OO kaiAngleX=14.00 Рис. 14.21. Демонстрация работы программы 14.3 (данные выводятся в порт)
Балансирующий робот 257 Программа с комплементарным фильтром Комплементарный фильтр Существуют другие, менее инерционные и сравнительно быстрые фильтры, позво- ляющие, смешивая данные с различных приборов, получать эффективные выходные значения. К таким фильтрам относится комплементарный фильтр. При объединении показаний акселерометра и гироскопа на основе комплементарно- го фильтра значение угла наклона рассчитывается по формуле: GyXsumx = (1 - alfa) x (GyXsum0 + GyX x At) + alfa x AcYsum, (14.4) где GyXsumx — расчетное значение угла наклона, GyXsum0 — значение угла наклона из предыдущего расчета, alfa — коэффициент комплементарного фильтра (подби- рается экспериментально от 0,001 до 0,05), GyX — угловая скорость, А/ — время итерации, AcYsum — угол склонения, рассчитанный по текущим показаниям аксе- лерометра. Итоговая величина является долевой суммой интегрированного значения показа- ний гироскопа и мгновенного значения показаний акселерометра. Доля показаний акселерометра мала, поскольку они умножаются на малую величину alfa, равную 0,001-0,05, и основной вклад вносят показания гироскопа - они умножаются на величину (l-alfa\ равную 0,999-0,95. Однако благодаря акселерометру, компенси- руются ошибки измерений, которые обязательно возникают и накапливаются, если пользоваться только гироскопом. Коэффициент alfa в расчет был взят равным 0,001 — этого оказалось достаточно для компенсации дрейфа нуля гироскопа. Таким образом, благодаря использованию комплементарного фильтра, который ма- тематически намного проще, чем фильтр Калмана, удалось добиться стабилизации робота, и он стал успешно справляться с задачей балансировки. Точная настройка Если акселерометр немного наклонен относительно поверхности земли, робот мо- жет постоянно ехать в одну сторону. Точно закрепить прибор довольно сложно, но этот наклон можно компенсировать постоянной составляющей, прибавляемой к значению угла, получаемому от акселерометра. Для описываемого нами робота был введен эмпирический коэффициент balancing_zerro=2.4. После этого робот уве- ренно стоял на месте. Заметим, что изменяя значение baiancingzerro, можно так- же управлять движением робота для перемещения назад или вперед.
258 Глава U На рис. 14.22 приведен алгоритм работы комплементарного фильтра — он проще как для понимания, так и с точки зрения потребляемых вычислительных мощностей. Созданная по этому алгоритму программа (листинг 14.4) снабжена понятными ком- ментариями. Для достижения положительного эффекта следует скорректировать программу под своего робота, поэкспериментировав с коэффициентами. Начало Смещение нуля баланса. balancing_zerro=2.4; AcYsum = 0; GyXsum = 0; Да Нет Ехать вперед Остановка Ехать назад Получить данные от гироскопа, угловую скорость вокруг оси X:GyX. Получить данные от акселерометра: ускорения по осям AcY, AcZ Расчет угла по показаниям акселерометра с учетом корректировки точки равновесия balancing_zerro. AcYsum = (atan2(AcY, AcZ)) * RAD_TO_DEG+balancing_zerro; «Использование Комплементарного фильтра» alfa - коэффициент фильтра. alfa = 0,001; GyXsum = (1 -alfa) * (GyXsum + (GyX/131 * dt) + alfa * AcYsum; Рис. 14.22. Алгоритм программы балансировки с использованием комплементарного фильтра
Балансирующий робот 259 Листинг 14.4. Программа балансировки с использованием комплементарного фильтра // Библиотека для работы с протоколом I2C (порты A5/SCL и A4/SDA) #include <Wire.h> const int MPU_addr = 0x68; // переменные для хранения данных, возвращаемых прибором. intl6_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; double AcYsum, GyXsum; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2; int motor_Rl, motor_R2; // Пин информационного светодиода. int s_diod = 5; // смещение нуля баланса. double balancing_zerro=2.4; / / / / void setup() { // Заносим в переменные номера контактов (пинов) Arduino. // Для левых и правых моторов машинки. setup_motor_system(3, 4, 7, 8); // Двигатели остановлены. _stop() ; Wire.begin(); Wire.beginTransmission(MPU_addr); // Производим запись в регистр энергосбережения MPU-6050. Wire.write(ОхбВ); Wire.write(0); // устанавливаем его в ноль. Wire.endTransmission(true); Serial.begin(9600); pinMode(s_diod, OUTPUT); _stop() ; AcYsum = 0;
260 Глава Ы GyXsum = 0; for (int i = 0; i < 5; i++) { delay(100); digitalWrite(s_diod, HIGH); delay(lOO); digitalWrite(s_diod, LOW); } //Serial.println(compensatorX); digitalWrite(s_diod, HIGH); } 11 // Основная программа. void loop() { uint32_t timer = micros(); while (true) { // Компенсируем наклон. if (GyXsum > 1.0) { forward(); } else if (GyXsum < -1.0) { backward(); } else { _stop() ; } Wire.beginTransmission(MPU_addr); Wire.write(ОхЗВ); // Готовим для чтения регистры с адреса ОхЗВ. Wire.endTransmission(false); // Запрос 14 регистров.
Балансирующий робот 261 Wire.requestFrom(MPU_addr, 14, true); // ОхЗВ (ACCEL_XOUT_H) & ОхЗС (ACCEL_XOUT_L) AcX = Wire.read() « 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & ОхЗЕ (ACCEL_YOUT_L) AcY = Wire.read() « 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) AcZ = Wire.read() « 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) Tmp = Wire.read() « 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyX = Wire.read() « 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyY = Wire.read() « 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) $ 0x48 (GYRO_ZOUT__L) GyZ = Wire.read() « 8 | Wire.read(); // Расчет угла по показаниям акселерометра //с учетом корректировки точки равновесия balancing_zerro. AcYsum = (atan2(AcY, AcZ)) * RAD_TO_DEG+balancing_zerro; // Измерение наклона по X. // Использование Комплементарного фильтра, // alfa - коэффициент фильтра. double alfa = 0.001; GyXsum = (1 - alfa) * (GyXsum + ((double)GyX * (double)(micros() - timer)) / 131000000.0) + alfa * AcYsum; // Для перевода угловой скорости в угол нужно знать время! timer = micros(); //delay(500); //Serial.println(GyXsum); // Функции setup_motor_system(), forward(),backward() и _stop() взять из листинга 14.2
262 Глава 14 Выводы В этой главе мы изучили принципы работы гироскопа и акселерометра. Разобрались с различиями между электронным и классическим гироскопами. Подключили гироскоп-акселерометр MPU-6050 к Arduino, написали программу его опроса. Создали несложную схему и конструкцию балансирующего робота. Поэтапно рас- смотрели три версии программы, предназначенной для организации балансировки робота, и выбрали наиболее удачный алгоритм — с комплементарным фильтром. Таким образом, цель, поставленная нами перед собой в этой главе, достигнута. Рекомендуем вам и дальше развивать полученные знания и умения. Например, по- лезно вернуться к предыдущим главам и научить роботов поворачивать на точные углы и отслеживать пройденное расстояние, используя данные от гироскопа и аксе- лерометра. А мы этим займемся в следующей главе.
ГЛАВА 15 НЕКОТОРЫЕ УЛУЧШЕНИЯ И ПРОЧАЯ ПОЛЕЗНАЯ ИНФОРМАЦИЯ Модернизация детектора препятствий Инфракрасный детектор (датчик) препятствия, примененный нами при сборке ла- биринтового робота (см. главу И), очень чувствителен к солнечному свету. И попа- дая в зону даже непрямых солнечных лучей, перестает нормально работать. Чтобы избежать такого эффекта, следует поместить фототранзистор датчика в черную тру- бочку (рис. 15.1) — это позволит значительно улучшить его работу. Рис. 15.1. Усовершенствование детектора препятствия
264 Глава 15 Точные повороты В главе 14 мы познакомились с гироскопом. Его можно успешно использовать для решения задач, описанных в главах 10 и 11, а также в самостоятельных проектах. Ценность для нас гироскопа в том, что он дает возможность точно рассчитывать по- вороты робота. Для этого сам гироскоп рекомендуется установить на оси вращения робота и обязательно параллельно плоскости его движения. В листинге 15.1 приведен пример программы, реализующей повороты робота на основании данных гироскопа. Управление направлением движения робота при этом осуществляется с помощью IR-приемника, подсоединенного к 16-му порту Arduino (на его плате — это А2), и IR-пульта дистанционного управления. При подключении библиотеки iRremote .h частично теряется возможность управления скоростью ра- боты моторов с помощью ШИМ, поэтому функцию ШИМ здесь применять не следу- ет (в программе скорость постоянна и равна 255). Примечание Демонстрацию работы гироскопа и программы из листинга 15.1 можно посмотреть в учеб- ном ролике «Arduino робот/robot и MPU-6050 (гироскоп/gyroscope)» на канале автора в YouTube (https://www.youtube.com/watch?v=76cEsG23BY4). Подключение гироскопа-акселерометра MPU-6050 к роботу осуществляется как программно (см. листинг 15.1), так и физически — по схеме, аналогичной представ- ленной в главе 14 (см. рис. 14.7). Листинг 15.1. Программа демонстрации работы гироскопа на 4-колесном роботе // Библиотека для работы с протоколом I2C (порты A5/SCL и A4/SDA) #include <Wire.h> #include <IRremote.h> // Порт для IR-приемника. int RECV_PIN =16; // Создание IR-приемника. IRrecv irrecv(RECV_PIN); // Переменная для результатов IR-приемника. decode_results results; int PROG; const int MPU_addr = 0x68; // упрощенный 12С-адрес нашего // гироскопа/акселерометра MPU-6050.
Некоторые улучшения и прочая полезная информация 265 // переменные для хранения данных, возвращаемых прибором. intl6_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; double AcYsum, GyXsum; // Угол поворота вокруг оси Z. float Ang_; const int key_flash = 14; const int flash_data = 15; // Объявляем переменные для хранения состояния двух моторов. int motor_Ll, motor_L2, input_L; int motor_Rl, motor_R2, input_R; // Пин информационного светодиода. int Line_L =14; float CompensatorZ, CompensatorAcX; // смещение нуля баланса. double balancing_zerro = 2.4; // Время на разгон/торможение в микросекундах. const long time_razgon = 100000; const int max_speed = 255; const int min_speed = 255; / / . void setup() { // Заносим в переменные номера контактов (пинов) Arduino // для левых и правых моторов машинки. // Двигатели остановлены. Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(ОхбВ); // Производим запись в регистр энергосбережения MPU-6050. Wire.write(0); // Устанавливем его в ноль. Wire.endTransmission(true); //Serial.begin(9600); // pinMode(s_diod, OUTPUT); AcYsum = 0; GyXsum = 0; //delay(lOOO);
266 Глава 15 CompensatorZ = 0; CompensatorAcX =0; for (int i = 0; i < 500; i++) { delay(10); Data_mpu6050(); CompensatorZ += GyZ; CompensatorAcX += AcX; } CompensatorZ = CompensatorZ / 500.0; CompensatorAcX = CompensatorAcX / 500.0; // Serial.print(«compensatorZ=»); // Serial.println(CompensatorZ); // digitalWrite(s_diod, HIGH); // Инициализируем сервомотор, управление 9 портом. // neck.attach(9); // Заносим в переменные номера контактов (пинов) Arduino // для левых и правых моторов машинки. pinMode(key_flash, OUTPUT); setup_motor_system(3, 4, 11, 7, 8, 10); // Двигатели остановлены. setspeed(255, 255); irrecv.enableIRIn(); // Основная программа. void loop () { int high_, low_; float ang; long micro, hod = 700000; if (irrecv.decode(^results)) { switch (results.value) { // 1 case 0xFF6897: Angle(10); break;
Некоторые улучшения и прочая полезная информация 267 // 2 case 0xFF9867: Angle(20); break; // 3 case 0xFFB04F: Angle(30); break; // 4 case 0xFF30CF: Angle(40); break; // 5 case 0xFF18E7: Angle(50); break; // 6 case 0xFF7A85: Angle(60); break; // Вперед 10 сек. case 0xFF629D: forward_t(10000000) ; break; // Назад 10 сек. case 0xFFA857: backward_t(10000000); break; case 0xFF02FD: Angle_t(100000000) ; break; } irrecv.resume(); } delay(10);
268 Глава 15 // Ехать вперед заданное время. //////// / / void forward_t( long microsec) { int _speed = min_speed; bool flag = false; microsec = microsec + micros(); long microsec_begin__tormog = microsec - time_razgon; float Ang_2 = Ang_; long timer; do { timer = micros(); if (Ang_ < (-1.0 + Ang_2)) { forward_left(); time_gyro(0.5); } else if (Ang_ > (1.0 + Ang_2)) { forward_right(); time_gyro(0.5); } else { forward(); time_gyro(0.5); _stop(); time_gyro(0.8); } if ((timer > microsec_begin_tormog)) { _stop(); time_gyro(0.5); } } while (microsec > timer); _stop() ; } / / // Ехать назад заданное время. //////// / / void backward_t( long microsec) { int _speed = min_speed; bool flag = false; microsec = microsec + micros(); long microsec_begin_tormog = microsec - time_razgon;
Некоторые улучшения и прочая полезная информация 269 float Ang_2 = Ang_; long timer; do { timer = micros(); if (Ang_ < (-1.0 + Ang_2)) { backward_right(); time_gyro(0.5); } else if (Ang_ > (1.0 + Ang_2)) { backward_left(); time_gyro(0.5); } else { backward(); time_gyro(0.5); } if ((timer > microsec_begin_tormog)) { _stop(); time_gyro(0.5); } } while (microsec > timer); _stop() ; } / / // Поворот на заданный угол. //////// / / void Angle (float ang) { int speed = max_speed; bool flag = false; float Ang_2 = Ang_; long timer; setspeed(_speed, _speed); // возможно стоит уменьшить скорость, если угол маленький. //if (abs(ang) < 8) setspeed(230, 230); if (ang == 0) return; if (ang < 0) { do { right(); time_gyro(1); _stop(); time_gyro(1); } while (Ang_ > (ang + Ang_2));
270 Глава 15 else { do { left(); time_gyro(1); _stop(); time_gyro(1); } while (Ang_ < (ang + Ang_2)); } _stop() ; Ang_2 = Ang_ - (ang + Ang_2) ; if (abs(Ang_2) > 1.0) Angle(-Ang_2); setspeed (max_speed, max_speed); // Держать угол определенное время void Angle_t( long microsec) { //time_razgon int _speed = min_speed; bool flag = false; microsec = microsec + micros(); long microsec_begin_tormog = microsec - time_razgon; float Ang_t = Ang_; long timer; setspeed(_speed, _speed); _stop() ; do { timer = micros(); if (Ang_ < (Ang_t - 1.0)) { left(); time_gyro(1); _stop(); } else if (Ang_ > (Ang_t +1.0)) { right(); time_gyro(1); _stop(); } else _stop(); time_gyro(1); } while (microsec > timer); _stop(); time_gyro(10); / /
Некоторые улучшения и прочая полезная информация 271 void Data_mpu6050() { Wire.beginTransmission(MPU_addr); Wire.write(ОхЗВ); // Готовим для чтения регистры с адреса ОхЗВ. Wire.endTransmission(false); // Запрос 14 регистров. Wire.requestFrom(MPU_addr, 14, true); // ОхЗВ (ACCEL_XOUT_H) & ОхЗС (ACCEL_XOUT_L) АсХ = Wire.read() « 8 | Wire.readO; // 0x3D (ACCEL_YOUT_H) & ОхЗЕ (ACCEL_YOUT_L) AcY = Wire.read() « 8 | Wire.readO; // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) AcZ = Wire.read() « 8 | Wire.readO; // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) Tmp = Wire.read() « 8 | Wire.readO; // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyX = Wire.read() « 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) .GyY = Wire.readO « 8 | Wire.readO; // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) GyZ = Wire.readO « 8 | Wire.readO; } // Задержка, но с расчетом изменения Z угла, void time_gyro (float mill_sec) { long ms = mill_sec; unsigned long timer = micros О; unsigned long endtime = micros() + long(ms * 1000.0); while (endtime > timer) { timer = micros(); Data_mpu6050() ; Ang_ = Ang_ + (( (float) (GyZ) - CompensatorZ) * (float) (micros () - timer)) / 131000000.0; delayMicroseconds(1) ; } // Функции инициализации и управления моторами не включены в листинг, //их следует взять из листинга 8.2.
272 Глава 15 Самостоятельная сборка корпуса робота В папке Korpus сопровождающего книгу электронного архива (см. приложение 3) имеется файл Корпус робота для резки.сс1г, содержащий векторный рисунок, выполнен- ный в программе CorelDRAW (рис. 15.2). Используя данные этого файла, можно заказать резку лазером деталей корпуса робота из акрилового стекла (оргстекла) или фанеры. В наше время найти лазерный резак не сложно — как правило, они есть в багетных мастерских. Альтернативой резке лазером может стать фрезерование на фрезерном станке, но найти его, возможно, будет труднее. Корпус робота для главы 14 (рис. 15.3) также представлен в папке Korpus отдельным файлом Балансирующий po6oT.cdr с векторным рисунком CorelDRAW. Колеса, вырезанные из тонкого материала, должны быть склеены по три штуки для получения полноценного колеса. Колеса нуждаются в шинах, например, из пористой резины, которые можно приклеить к ним клеем. В файле Колесо.БИ папки Korpus содержится заготовка колеса для печати на 3D- принтере (рис. 15.4). Рис. 15.2. Детали корпуса четырехколесного робота
Некоторые улучшения и прочая полезная информация 273 D О О D О О D D О D D О D D О D D D ODD □ a о а из О а о г 2? or оц . С? Рис. 15.3. Детали корпуса балансирующего робота Рис. 15.4. Колеса робота для ЗЭ-печати
274 Глава 15 В качестве крепежа можно использовать 3-мм винты с гайками. Приобрести их мож- но в любом магазине строительных товаров. Моторы с редукторами можно заказать через Интернет или приобрести в магазине электроники. Платы Arduino и ее клоны также не являются редкостью. Листинги Все приведенные в книге листинги в полном объеме включены в электронный ар- хив (см. приложение 3), их можно скачать и использовать. Кроме них, в архив так- же включены листинги некоторых альтернативных вариантов программ, которые в книге не приводились. Интересные каналы YouTube Много интересного о работе с Arduino, сборке роботов, пайке и т. п. можно узнать, если смотреть тематические каналы на YouTube. • Канал «Паяльник TV» — это видеоканал сайта http://cxem.net/. Здесь содер- жится огромное количество интересных проектов и учебных курсов по электронике. • Канал «Dmitry OSIPOV» содержит большое количество интересных обзоров Arduino-проектов. Объясняется все просто и доступно. • Канал «kid robot maker» посвящен колесным и гусеничным роботам на платформе Arduino. • Канал «arduinoLab» посвящен различным проектам на Arduino. • Канал «МгПоделкинЦ» — интересный канал по электронике. • Канал «Роботы наступают» просто демонстрирует красивых роботов. • Канал автора называется «Mikhail Momot», там также много интересного мате- риала по сборке роботов.
ПРИЛОЖЕНИЕ 1 КОММУТАЦИОННАЯ ПЛАТА ARDUINO UNO SENSOR SHIELD V5.0 Коммутационная плата (плата расширения) Arduino Sensor Shield V5.0 предостав- ляет удобный вариант подключения сервоприводов, датчиков и прочих устройств. Плата не несет на себе каких-либо стабилизаторов, преобразователей уровней или других активных элементов, а содержит лишь набор обычных переходников с одних разъемов на другие (рис. П1.1). Р^ЩтЩЩм ж Рис. П1.1. Установка платы расширения Arduino Sensor Shield V5.0 на плату Arduino UNO
276 Приложение 1 На плате расширения Arduino Sensor Shield V5.0 расположено множество интерфей- сов для подключения внешних устройств, таких как: • серводвигатели; • регуляторы скорости двигателей; • модуль SD-карты; • модуль Bluetooth; • дисплей 128x64 с параллельным портом или последовательным (SPI); • аналоговые датчики; • устройства с 12С-интерфейсом; • устройства с UART-интерфейсом; • модуль беспроводной связи АРС220. Питание на плату подается или с Arduino, или от внешних источников (блоков пита- ния, батарей). Переключение питания с Arduino на внешний источник осуществля- ется с помощью перемычки SEL. Для платы расширения необходимо напряжение 5 В. Когда на плату подается напряжение, должен загореться светодиод PWR. Внимание! Для всех описанных в книге экспериментов мы рекомендуем подавать напряжение с выхода +5 В платы драйвера двигателей L298N (см. главу 5). Также раздельное питание рекоменду- ется применять при подключении более одного сервопривода. На плате расширения находится кнопка сброса параметров или перезагрузки RESET, а также демонстрационный светодиод, подключенный к 13-му порту. Назначение разъемов Arduino UNO Sensor Shield V5.0 приведено на рис. Ш.2. Схема подключения компонентов при использовании коммутационной платы Arduino UNO Sensor Shield V5.0 приведена на рис. П1.3.
Коммутационная плата Arduino UNO Sensor Shield 1/5.0 277 параллельный и последовательный порт для подключения жидкокристаллического дисплея СО СМ т- О т— ч— т— т— О) 00 I4- QQQQQQQ светодиод, подключенный к 13 контакту 13 Pin LED цифровые входы/выходы G[1P|_ GND V *f- VCC S [•J— Signal Digital 10 Ports D0-D13 G[#}_ GND V %\- VCC S Щ- Signal Analog 10 Ports A0-A5 аналоговые входы/выходы Reset кнопка сброса Power питание APC220 Wireless Module Interface gnd интерфейс для подключения внешнего Wi-Fi модуля АСР220 vcc интерфейс gnd для подключения D1 внешнего gnd устройства Bluetooth последовательная шина COM последовательная о шина данных для связи интегральных схем интерфейс для подключения карт памяти SD интерфейс для подключения ультразвуковых датчиков Рис. П1.2. Назначение разъемов платы расширения Arduino UNO Sensor Shield V5.0
278 Приложение 1 Внешнее питание Ультразвуковой датчик Vcc Gnd Серводвигатель ИК приемник пульта управления или Bluetooch Рис. П1.3. Схема подключения компонентов при использовании коммутационной платы Ardulno UNO Sensor Shield V5.0
ПРИЛОЖЕНИЕ 2 КРЕПЛЕНИЕ СЕРВОДВИГАТЕЛЯ И УЛЬТРАЗВУКОВОГО ДАЛЬНОМЕРА HC-SR04 НА ШАССИ РОБОТА Для крепления на шасси робота серводвигателя и ультразвукового датчика на практи- ке применяются различные приспособления. Одним из таких приспособлений явля- ется Mini Pan-Tilt Kit. На рис. П2.1 показана последовательность установки серводви- гателя и ультразвукового дальномера на шасси робота. Подробная инструкция при- ведена на сайте: https://learn.adafruit.com/mini-pan-tilt-kit-assembly?view=all. Примечание Mini Pan-Tilt Kit позволяет закрепить на шасси робота также видеокамеру и вращать ее не только в горизонтальной, но и в вертикальной плоскостях (с помощью второго серво- двигателя). 1. Детали для крепления УЗ дальномера HC-SR04 2. Крестовина для крепления оси двигателя SG90
280 Приложение 2 3. Обрезать крестовину... 5. Вставить сервомотор между двумя боковыми деталями 7. Вставить ось сервомотора в крестовину и закрепить саморезом 4. Вставить крестовину в верхнюю часть основания и закрепить саморезами 6. Скрепить всю конструкцию двумя саморезами 8. Продеть в боковые детали эластичное кольцо и закрепить им плату дальномера HC-SR04. Уста- новить всю конструкцию на верхней палубе робота на стойках Рис. П2.1. Последовательность установки серводвигателя и ультразвукового дальномера на шасси робота
ПРИЛОЖЕНИЕ 3 ОПИСАНИЕ ЭЛЕКТРОННОГО АРХИВА Электронный архив к книге опубликован на FTP-сервере издательства «БХВ- Петербург» по адресу: ftp://ftp.bhv.ru/978S977537414.zip. Ссылка на архив до- ступна и со страницы книги на сайте http://www.bhv.ru. Описание электронного архива приведено в табл. П3.1. Таблица П3.1. Описание электронного архива Папки Listing_4_1 Listing_4_2 Listing_4_3 Listing_4_5 Listing_4_6 Listing_4_7 Listing_4_8 Listing_4_10 Listing_7_1 Listing_7_2 Listing_8_1 Listing_8_2 Listing_8_3 Описание Листинг 4.1. Программа мигания светодиодом Листинг 4.2. Объявление переменных. Зоны видимости. Сообщение об ошибке Листинг 4.3. Получение данных от компьютера через порт ввода/вывода Листинг 4.5. Программа управления миганием светодиодом с ПК Листинг 4.6. Программа управления миганием светодиодом с ПК с использованием оператора switch... case Листинг 4.7. Программа управления миганием светодиодом с ПК с использованием оператора цикла while Листинг 4.8. Пример использования оператора цикла for (на 300 повторений) Листинг 4.10. Пример управления сервомотором Листинг 7.1. Тестовая программа Листинг 7.2. Программа движения вперед Листинг 8.1. Проверка кодов кнопок пульта Листинг 8.2. Программа управления роботом IR-пультом Листинг 8.3. Переименование робота и проверка работы Bluetooth Главы 4 4 4 4 4 4 4 4 7 7 8 8 8
282 Приложение 3 Таблица П3.1 (окончание) Папки Listing_8_4 Listing_9_1 Listing_9_2 Listing_9_3 ultrasonic-HC- SR04 Listing_10_1 Listing_10_1m Listing_10_2 Listing_11_1 Listing_11_3 Listing_11_4 Listing_12_1 HMC5883L Listing_13_1 Listing_13_2 Listing_14_1 Listing_14_2 Listing_14_3 Kalman Listing_14_4 Listing_15_1 Korpus Описание Листинг 8.4. Управление роботом по Bluetooth-каналу Листинг 9.1. Измерение расстояния до препятствия Листинг 9.2. Управление сервомотором Листинг 9.3. Точная установка головы Библиотека для ультразвукового сонара ultrasonic-HC-SR04 Листинг 10.1. Программа обхода препятствий роботом Листинг 10.1т. Программа обхода препятствий роботом (модифицированная, в книге не приведена) Листинг 10.2. Отладочная (неполная) программа обхода препятствий с выводом в порт Листинг 11.1. Программа движения вдоль правой стенки. Ультразвуковой датчик Листинг 11.3. Программа движения робота с тремя детекторами препятствия Листинг 11.4. Модернизированная программа прохода лабиринта с использованием датчиков препятствия Листинг 12.1. Программа выбивания кеглей по цвету (белые кегли) Библиотека для магнитометра HMC5883L Листинг 13.1. Прием данных от HMC5883L и передача их на ПК Листинг 13.2. Программа движения робота в северном направлении Листинг 14.1. Получение данных от MPU-6050 Листинг 14.2. Программа балансировки на основе анализа показаний гироскопа Листинг 14.3. Программа балансировки с использованием фильтра Калмана Библиотека фильтра Калмана Листинг 14.4. Программа балансировки с использованием комплементарного фильтра Листинг 15.1. Программа демонстрации работы гироскопа на 4-колесном роботе Файлы с векторными рисунками для самостоятельного изготовления корпусов роботов. Файл с ЗЭ-моделью колеса для робота Главы 8 9 9 9 9 и после- дующие 10 10 10 11 11 11 12 13 13 13 14 14 14 14 14 15 15
ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ Акселерометр 16,231-240,247,253,255, 257, 261, 262 Активные флюсы 40 Алгоритм 50 движения робота в направлении на север 223 движения робота с тремя детекторами препятствия 178 движения робота с ультразвуковым датчиком 178 обхода лабиринта 166 объезда препятствий 149 поиска кегли с использованием ультразвукового датчика 201 тестовых движений робота 106 Алкалиновые батареи 43 Аналого-цифровые преобразователи 23 Андроиды 71 Аудиоканалы 25 IRremoteh 264 для работы с Ш-приемником 115 Библиотеки 68 Блок-схема алгоритма 50, 62 Бокорезы 34-36 Бокс для элементов питания 99 в Видеокамера 22 Визуальные каналы 25 Встроенные функции 68 Выбор паяльника 38 припоя 39 ходовой части 71 Выключатель 31 электропитания 99 Базовые функции движения 105 Батареи/аккумуляторы формата АА 86 Беспроводные компьютерные сети 26 Библиотека HMC5883L 216 Гирокомпас 16 Гироскоп 232,250 Гироскоп-акселерометр MPU-6050 229, 231, 262, 264 Гусеничная ходовая часть 73
284 Предметный указатель Дальномер 16,137 HC-SR04 138 Датчик 16 влажности 21 газа 21 движения 20 касания 16 наличия освещенности 189 определения цвета TCS230 188 препятствия 17,18,231 расстояния 16,136 температуры 17 угла поворота 20 шума 16 Двигатели постоянного тока с редуктором 76 Двоичное представление чисел 49 Двуногие роботы 71 Десятичная система счисления 49 Детектор шума 19 Дисплей 27 Драйвер двигателей 35,83,86,90-96, 100,101 Емкость аккумуляторной батареи 42 ж Желеобразные флюсы 40 Заготовка программы 52 Задание номера порта 54 Закон Ома 41 Защита роботов от электромагнитных помех 131 и Измеритель освещенности 16 ИК детектор препятствия 196,198 Импульсные стабилизаторы 46 Информационно-измерительная система роботов 15, 22 Инфракрасные каналы 25 Инфракрасный датчик отражения TCRT 5000 192,194,196,198 препятствия 18 расстояния 18 датчик расстояния Sharp GP2Y0A21YK 173 Инфракрасный детектор препятствия 172,174,175,263 канал 111 светодиод 17 Исполнительная система 27 К Канал Bluetooth 26,136 Кегельринг 185 Клеммные соединения 35,196 Клеммы Dupont 35 с болтовым зажимом 35 Коды кнопок IR-пульта 116,118 Колесная ходовая часть с дифференциалом 74 Колесные ходовые части с мотором 74 Комплементарный фильтр 257 Компьютерная программа 49
Предметный указатель 285 Конденсаторный микрофон 19 Контроллер Arduino 23 Bluetooth HC-05 126 Л Летающие роботы 75 Линейный алгоритм 50 Линза Френеля 20 Литиевые аккумуляторы 86 Литий-ионные аккумуляторы 44 Лужение провода 37 м Магазин приложений Google Play Маркет 125 Магнитный датчик 16 Магнитометр HMC5883L 214-220, 222, 229 Магнитометр-компас НМС5883 237 Манипуляторы 27 Микроконтроллер 23 Микросхема Ак8975 214 HMC5883L 214 НМС5983 214 L293B 77 L293D 77, 241, 242 L298N 77 L7805CV 45 LM317T 47 LM2596 46 MPU-6050 231, 235-238, 240, 241, 247, 250, 253, 254, 259, 262 КР142ЕН5А 45 Многожильные провода 34 Модули Wi-Fi 26 Модуль НС-05 125,127 н Недостатки клеммных соединений 35 Никель-металлогидридные аккумуляторы 43 Номинальное напряжение 42 Номинальный ток 42 Обмен информацией с ПК 57 Объектно-ориентированное программирование 69 Объявление переменных 59 Одножильные провода 33 Оперативная память 23 Операторы организации циклов 66 Операционная система Android 26 Оптический рефлекторный датчик расстояния 18 Отладка программ 156 п Пайка 36, 37 Паяльная кислота 40 Паяльник 36, 38 Перезаряжаемые элементы питания 43 Переменные 58 с плавающей точкой 60 управления моторами 105 Переменный резистор 20
286 Предметный указатель Плата Ш-приемника 113 драйвера двигателей 86, 93, 95,100,101, 138 Повышающие импульсные стабилизаторы 46 Подключение контроллера Arduino к компьютеру 54 электропитания 101 Пожарная сигнализация 21 Поиск выхода из лабиринта 163 Получение данных от MPU-6050 237 Пороговый датчик освещенности 17 уровень срабатывания датчика 17 Порядок обхода кегельринга 188 Постоянная память 23 Правила поведения робота 22 Припой 36 Проводники электрического тока 33 Проводные каналы 25 Программа Fritzing 16 балансировки на основе анализа показаний гироскопа 247 балансировки с использованием комплементарного фильтра 259 балансировки с использованием фильтра Калмана 253 выбивания кеглей по цвету 203 движения робота в северном направлении 224 движения робота с тремя детекторами препятствия 180 измерения расстояний 140 инсталляции Arduino IDE 52 переименования робота 128 Программатор 54 Процессор 23 Радиоканал Bluetooth 111 Wi-Fi 111 Радиоканалы 25 связи 26 Радиоуправляемые квадрокоптеры 75 Разветвляющийся алгоритм 50 Расстояние срабатывания 17 Редукторные передачи 28 Резистор 30, 31 Робот исполнительная система 15 механика 15 система принятия решений 15 система связи 15 система энергоснабжения 15 Сборка робота 83 Светодиод 17, 31, 56,190,192,196 Связка светодиод-фоторезистор 199 Сенсор 16 Сервомотор 29, 76,141 SG90 142 Сервомоторы постоянного вращения 76 Сервопривод 71,72,137 Система машинного зрения 16 полива растений 21 принятия решений 22 связи 25 энергоснабжения 30 Соединение клеммами 35 скруткой 35
Предметный указатель 287 Солевые батареи 43 Специализированная библиотека Ultrasonic.h 140 Специализированные микросхемы драйверов двигателей 77 Способы дистанционного управления роботом 111 Среда Arduino IDE 51 Стабилизатор тока 47 Стабилизаторы питания 45 Стандарт АА 42 Стандарт ААА 42 Стандартные комплектующие 83 Стопоходящая машина 72 Счетчик команд 49 Текстовая форма алгоритма 51 Температурный датчик 16 Тестовая программа движений робота 108 Типоразмер 18650 42 Типоразмеры элементов питания 42 Типы данных переменных 59 Тонкая настройка программ 154 Традиционный компас 213 Триангуляционный принцип измерений 18 Тумблер 31 Управление роботом по каналу Bluetooth 112,125 роботом по IR-каналу 112 Управляющие команды 25 Условные операторы 61 Установка нестандартного драйвера 54 Устранение неполадок сборки 147 Ф Фильтр Калмана 251, 256 Флюс 39 Фотодиод 189,190 Фоторезистор 17,190,191 Фототранзистор 17,191,192,196, 263 Функции 68 движений 106 Ходовая часть 27 робота 71 Целочисленные переменные 60 Циклический алгоритм 50 Цифровые порты 24, 57 Укладка проводов 103 Ультразвуковой дальномер HC-SR04 137,148 датчик расстояния 18,110,193 датчик расстояния HC-SR04 171 Человекоподобные роботы 71 Четырехколесный робот 74 Четырехногий робот 72
288 Предметный указатель ш Шагающий робот 71 Шаговый двигатель 30,76 Широтно-импульсная модуляция (ШИМ) 79, 80,141, 264 Широтно-импульсные генераторы 23 э Энкодер 20 Этапы пайки я Язык C++ 51 А Arduino UNO 37 24 Электрическая мощность 41 Электрические двигатели 27 Электрический двигатель постоянного тока 28 Электромагнитные наводки 87 Электронный акселерометр 231 архив 57, 252, 274 гироскоп 231,235 гироскоп-акселерометр 231 компас 213, 214, 218, 229 Элементы питания робота 86 в Bluetooth-контроллер 125,127 i IR-канал 136 IR-компоненты 113 IR-приемник 25,113,114,264 IR-пульт 113,136,264