Что значит робота разработать

Вы читаете о роботах и программировании и думаете: «Было бы здорово сделать что-то подобное самому!» Теми, кем эта идея овладевает чуть больше просто мыслей смотрят кто и как делал своего робота. Читают статьи, смотрят видео. На картинках все понятно. В видеороликах тоже обычно показываются уже готовые продукты, а также сжато показываются технологии их изготовления. И вроде бы то же всё понятно: отпилил, прикрутил, припаял, соединил, запрограммировал вон на той программе вот этим кодом. Еще более увлечённые, выбрав интересный и, с первого взгляда, простой вариант, переходят к действию и, зачастую копируя, делают своего первого робота. Это волевое и очень значимое решение — главное начать хоть что-то сделать самому! В процессе изготовления оказывается куча технологических заковырок вплоть до того, что оказыается для заказа/покупки какуй-то штукенции, надо узнать как она точно называется. А еще — разъёмы не паяются нормально — и как на видео в одно касание всё получается? Процесс создания нередко затягивается, но настойчивый начинающий робототехник так или иначе добивает результат до какого-то осмысленного первого запуска хотя бы «по прямой».fc4b0373af834c11a42adef8d76e1e70.JPGПотом, когда робот закончен, приходит понимание, почему все делается именно так и именно в такой последовательности. Процесс создания уже можно как-то осознать, формализовать, расписать. Вот с этого момента-то и начинается разработка модели следующего, второго поколения.

Да, я тоже раньше с интересом читал статьи. И сейчас читаю! Особенно мне нравятся статьи про коптеры: с земли, да в небо! Однако, если быть честным, они во мне вызывали только мысли. Тем более, надо было разбираться в программировании, а последний раз я работал с Си в институте, всё уже начисто забылось. Я знаю, что такое Arduino, но я никогда не видел её «живьём». И так далее. У меня техническое образование, я занимаюсь вопросами ЦОС на FPGA. Технически для меня нет препятствий взять и разобраться, но… по сути я занимаюсь всем этим на работе и мне там всего этого дела, как говорится, «выше крыши» :) В результате нужен был какой-то хороший стимул, чтобы этим как-то начать заниматься. Стимул появился, когда это стало нужно кому-то ещё: правду говорят, что настоящее созидание — когда отдаешь другим.

Мой хороший знакомый, который является одним из учредителей молодой (можно сказать свежеиспечённой) компании Endurance, зная характер моей работы, обратился ко мне по ряду технических вопросов. Оказалось, что ребята имеют разработчиков в США и уже представили свой прототип супердешевого (телефон + пластиковая платформа с колесами на ардуине — вроде бы уже дешевле и некуда) робота телеприсутствия. Но они захотели не просто заниматься одним маркетингом и бизнесом в стиле «купил там — продал тут», а захотели более подробно погрузиться в техническую тему и даже планируют разработать свою модель (пусть даже эквивалентную по принципу и функционалу), но уже тут, у нас в России, с целью получения не только готового результата, но и понятной самим технологии его изготовления. Такова предпосылка участия в этом деле вашего покорного слуги (это я на себя намекаю).

Поначалу я тоже почитал статьи, посмотрел где и что покупают и как делают. Но не было единой картины. Вроде бы, в целом-то, всё понятно, но одновременно и не всё. Непонятно как управлять с компьютера, как видео на компьютер доставить. Тем более, я же не софтовик и не хотелось бы «раскапывать» эту, софтовую, тему с нуля, хотя это было бы интересно конечно; так-то я все свои потребности как-то успешно удовлетворял скриптовым языком AutoIt. В результате поисков я нашел два ключевых ресурса, которые стали для меня ключевыми: интернет-магазин carduino и форум cyber-place. В магазине можно было купить все необходимые комплектующие — всё в одном месте. Цены, по сравнению с ebay или ali, конечно, дикие, но главное было не в этом — можно было купить платформу и необходимый обвес к ней, также как и всю мелочевку. И это было удобно забирать/заказывать. На форуме в разделе «Сделай сам»\«Робототехника» и «Сделай сам»\«CyberWrt» можно почерпнуть информацию общего характера, а также как детально организовать связь компьютера с роботом через Wi-Fi. Десятилетний опыт работы по специальности дал о себе знать, и я вместо того, чтобы немедленно начать копировать, что-нибудь скручивая или программируя, взял в руки карандаш и бумагу…

Что значит «разработать»? Вот понятно, что такое «сделать робота» — берёшь и… делаешь! А «разработать» это как? Ниже я попытался описать процесс, именно, разработки, а не создания робота. Создание робота, как конструирование, изначально интуитивно понятно и представляемо. По мере создания прикручивается то — то, то — это. Понакрутил так — и вдруг оказалось, что ту, вторую деталь, надо иначе прикрутить, тогда восьмая деталь встанет как влитая, надо только проводки от батареек передвинуть влево поближе к пятой детали, а, чтобы не болтались, лучше прикрепить к четвёртой, немного их подогнув, так как там рядом будет десятая деталь. Сплошное творчество. А давайте попробуем по взрослому: сначала продумаем, что будем делать, а потом сделаем это :)

Итак, о чем пойдёт речь в данной статье. Я решил не писать про то, как я делал робота, таких статей немало и смысла в появлении ещё одной, всего скорее, нет. Я уж точно не первый и даже не десятый, кто на покупной платформе, понавесив датчиков сделал игрушку на радость себе и окружающим. Я решил попытаться, так скажем, изложить свою технологию мышления. Я постарался донести до читателей не просто тот факт, что сделать робота не так и сложно, а изложить методику, по которой можно взять и попробовать сделать своего робота с нуля, причем начинающему робототехнику будут ясны и понятны этапы создания изначально, а не открываться по мере продвижения в неизведанное.

Представим себе человека, который никогда не занимался робототехникой. У него есть друг-паяльник, мультиметр и всякий ручной инструмент типа кусачек, отверток и прочего. Представили себя? Отлично! Поехали…

Первый этап — осмысление

Что мы хотим сделать? И зачем это нужно?

Для меня этот вопрос был изначально решён за меня — мне нужно сделать машинку с видеокамерой, которая бы могла подключаться через Wi-Fi или интернет к компьютеру, на компьютере я бы видел картинку с машинки и управлял бы ей, заставляя её двигаться. Вроде бы понятно, но как-то скучно и чего-то не хватает. Удалённое управление — робот что ли какой-то? Робот? Что такое робот? Робот — это какая-то автономная штука, которая выполняет работу самостоятельно. Как это применить для данной задачи? А пусть машинка будет ездить сама! Как таковой постановки задачи нет — ну пусть ездит как захочет. Однако, если она будет ездить как вздумается, то будет сталкиваться с предметами. Это как-то нехорошо, неправильно. Значит, машинка должна уметь видеть впереди себя и объезжать препятствия, предотвращая столкновение. Как это можно сделать? Можно обрабатывать данные с видеокамеры. Э-эээ… как-то непонятно как вообще к этому подступаться. Наверное это непросто. Что у нас ещё есть? Продаются всякие инфракрасные и лазерные измерители расстояния! Можно купить такой и как-то получать расстояние с него. Бред вроде, но что-то в этом есть…

Исходя из размышлений, рождается замысел, концепция устройства. Результат размышлений должен быть изложен в общем виде тезисно и кратко, концентрируя суть. Необходимо получить устройство, которое: — умеет перемещаться по поверхности по командам оператора транслируя ему видео впереди себя; — имеет автономный режим «существования»: умеет самостоятельно двигаться в произвольном направлении; — контролирует обстановку впереди себя; — в случае обнаружения впереди какого-то объекта не даёт себе с ним столкнуться, игнорируя команды опреатора, или меняет направление движения в автономном режиме.

Кажется определились с целью. Берём паяльник и устраиваем его на столе. Можно в тряпочку укутать — ему помягче будет, поуютнее. Пускай прывыкает пока к обстановке.

Второй этап — изучение реальности

После того, как определились с базовым функционалом и стало понятно, что нужно сделать, встаёт вопрос: как это сделать, как это будет выглядеть?

Можно взять молоток в руки и, обведя суровым взглядом свое жилище, безапеляционным тоном заявить окружающим: крышка от стола, колесики от кресел, резинка из трусов, пара китайских палочек, 20 сантиметров ткани от шторы, защёлки из босоножек, ноутбук разбираем на запчасти — всё сдать мне во имя прогресса! Дабы не было ненужных вопросов голосу можно придать оттенки угрозы и одухотворения одновременно. Однако, предлагаю более эффективный метод: для этой цели идеально подходит созданный людьми инструмент под названием «Интернет». Набираем слово «Робот своими руками» в той поисковой системе, которую позволяет использовать ваша религия, и начинаем читать, смотреть, слушать и вникать. Этот этап может длиться гораздо дольше предыдущего, так как придумать что-то сделать гораздо проще, чем придумать, как сделать это что-то. Тем более, мимоходом можно ещё столько интересного узнать!

Итак, результатом этого этапа должнен являться более детальный тезисный список, который будет определять вид того, что мы придумали на прошлом этапе. Наше устройство будет иметь следующий вид: — трёхколёсная платформа с двумя двигателями: два ведущих колеса, третье — как подпорка; — питание от аккумуляторов АА (1,2–1,3В х 4 = примерно 5 вольт — как раз для двигателей подходит); — устройством будет управлять микроконтроллер Arduino Nano (управление двигателями — через драйвер двигателей, запитать микроконтроллер можно от 5В); — дальность определять будем используя ультразвуковой датчик (питание 5В); — перепрошитый маршрутизатор (питание 5В) будет работать как точка доступа, подсоединяясь к которой можно подключиться к вебсерверу и выдавать команды на микроконтроллер, при этом нам будет доступна картинка с вебкамеры, подключенной к маршрутизатору; — на устройстве установлены два переключателя: ВКЛ/ОТКЛ питание и ВКЛ/ОТКЛ автономный режим — с этого момента никаких устройств, раз автономно умеет работать — значит робот; — робот снабжён светодиодом, который будет загораться при обнаружении препятствия; — на роботе будут присутствовать спереди два ярких белых светодиода — фары — почему бы и нет: когда темно, роботу не должно быть страшно, а с ярким светом всегда как-то пободрее, тут главное — назад не оглядываться лишний раз — значит видеокамера будет направлена только вперёд; — на роботе будет установлена веб-камера, которая будет подключена к маршрутизатору.

Этот, представляемый нами внешний вид базируется на тех представлениях, которые мы получили изучая рынок комплектующих для роботов. Здесь нет детального представления робота до винтика — только общие черты, однако, они позволяют представить себе, что получится в результате. В целом, приходим к выводу, что можно всё купить в магазине carduino, а также организовать связь с роботом, используя маршрутизатор и настроив его примерно так, как указано на форуме cyber-place. Пока не разбирались в тонкостях подключения отдельных комплектующих и не разбирались как программировать маршрутизатор. Но поняли, что отдельные комплектующие можно друг к другу подключить (электрически и информационно), а также определились, как минимум, со структурой и внешним видом.

Компоненты робота

Паяльник лежит на столе и заинтересованно смотрит на картинки выше. Интерес понятен — паять-то это всё ему!

Третий этап — творчество: общая разработка

Столько времени портрачено, а результата еще не видно! Результат только у нас в голове в виде образов и мыслей. Может быть стоит как-то материализовать эти мысли? Как будет выглядеть внешний вид робота уже, примерно, понятно. Также определён набор комплектующих. Как это будет соединяться? Как это всё будет общаться между собой? Робот — это же не лампочка — щелкнул выключателем и она загорелась. Тут щелкнул тумблером, питание подалось —, а дальше что? И вот тут, уважаемые читатели, разработка начинает ветвиться на три составляющие: конструкторская, электротехническая и программная.

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

Посидев и порисовав можно прийти к следующему функциональному виду робота:

5da2028161664536a26d1ae45f74f03b.jpg Заранее извиняюсь за качество картинок. Картинок у меня получилось много, а раздувать траффик под катом не хотелось, поэтому я пришел к некоторому компромиссу между качеством и объёмом, который выражается в том, чтобы весило мало, но было читаемо и понимаемо.

Что мы видим на картинке? Наш робот будет состоять из двух независимых частей: блок связи и блок управления. Блок связи связывается с внешним оператором, принимает от него команды и выдаёт их на блок управления. Блок управления, принимая команды, выполняет их. То есть, мы поделили управление на два уровня — низкоуровневое (управление платформой, взаимодействие с датчиками) и высокоуровневое (взаимодейтвие с оператором и командное управление низкоуровневой частью). Задача по управлению разбилась на две части, которые можно решать раздельно: сначала разобраться с движущейся платформой в виде микроконтроллера Arduino, затем — со связью в виде перенастроенного маршрутизатора.

Блок связи.1) Элеткротехника.Тут, вроде как, в целом всё ясно: камера даёт видео и звук и подключается через хаб к маршрутизатору. К нему же через хаб подключается и Arduino. Невелика премудрость воткнуть кабель в USB разъем, вероятность сделать это не так, или наоброт, достаточно мала Правда, некоторым и такой вероятности хватает, но это ж не про нас!!! Мы же смотрим, куда вставляем, если не лезет просто посильнее дожмем — должно влезать, это ж USB!2) Программирование. Тут никакой разработки нет, так как используется уже готовая прошивка под маршрутизатор и готовые модули для робота. Интерфейсный протокол с блоком управления уже определили за нас — надо тоже только разобраться. Как именно прошивать и что именно там настраивать — разберёмся потом.

Блок управления.1) Электротехника. Вроде бы, тоже, всё понятно. У нас имеется материнская плата, на которой всё распаивается. Надо будет только разобраться, куда подсоединяются датчики к Arduino и при этом нигде не натворить лишней работы, перепутав землю с питанием. С точки зрения подключения, вроде бы, нет особых проблем. Правда, сразу и не сообразишь куда на плате что подключается, но посмотрев работы масетров, а также, найдя нижеприведённую картинку, всё становится на свои места. Как там и что разведено — потом разберёмся, тем более правило напильника никто не отменял: если чего — доработаем!

dd9cc3627d9b458e99e88eb1707ef8ff.png 2) Программирование. А вот тут проблема. Как и чего там должно делаться. Вот пришла команда. Чего делать? Берём опять карандашик с бумажкой и рисуем. В результате можно получить следующую функциональную программную схему (только платформы):

1bfdf05944dc47b396041a1f74f5be3d.jpg Получились очередные квадратики. Но теперь это уже чисто программные модули. Некая материализация того, что нельзя пощупать и потрогать, но оно есть, так как робот двигается исходя из логики этого уровня абстракции.Команда должна приниматься интерфейсным модулем. Именно он должен распознать, что приходящие данные имеют смысл, что это не помехи или неверная команда. При идентификации команды модуль должен сообщить модулю управления, что за команда к нам пришла. Модуль управления по команде должен будет выполнить какие-то действия — начать движение, остановиться, «посмотреть» нет ли впереди преграды, включить фары или выключить их и прочее. Если нажата кнопка автономного режима, то модуль управления должен будет определять нет ли впереди препятствия и двигаться вперёд выдавая соответствующую команду на модуль моторов, а также принимать какие-то действия, если препятствие имеется. Функции непосредственно управления конечными устройствами частично делегированы другим модулям исходя из уровня сложности. Модулю управления, чтобы приказать модулю двигателям двигаться вперед, нужно знать можно ли двигаться вперёд. Всего скорее, просто так, с ультразвукового датчика данные не получишь — да и зачем нам этим заниматься? Мы только командовать умеем — для работы с датчиком имеется модуль сонара! Вот у него и запрашиваем доклад об оперативной обстановке спереди робота — ехать-то вперед можно?

Паяльник радостно и незаметно выбрался из-под тряпочки, заинтересованно уставившись на розетку: интересно, сколько там вольт — 110 или 220?

Четвёртый этап — творчество: детальная разработка

Что и как делать понятно. Понятно из чего. Понятно, как именно, это должно и будет выглядеть функционально. Пора! Пора уже начать что-то делать! Столько всего прочитали, просмотрели, оценили, обдумали, придумали, забраковали, разрисовали. Эх… вон, паяльник невдалеке лежит. На нас смотрит. Недоумевает — казалось бы бери да паяй, чего всякой фигнёй заниматься? Вздыхаем и накрываем паяльник листком бумаги: поспи родной пока, ещё не все готово. Мало понять как будет выглядеть всё функционально, нужно понять как будет выглядеть всё структурно. Нужно максимально детализировать своё понимание.

Блок связи.Практически всё выяснили на прошлом этапе. Всё понятно. На форуме cyber-place ознакомимся с этой темой и понимаем как перепрошить маршрутизатор TP-Link MR3020 и настроить его. Скачиваем прошивку для маршрутизатора. Создаём файлики с описанием куда какой IP вводить, что и где нажимать. Единственная проблема — непонятно какие именно команды будут высылаться на микроконтроллер. Посидев на форуме, почитав и пообщавшись становится всё понятным (больше спасибо всем, кто мне отвечал и пытался помочь). Записываем все команды так же в текстовой файл и помечаем, какая команда за что отвечает. Оказалось всё просто — при нажатии на кнопку, например «вперёд», высылается определенная строка ASCII кода, а при отпускании кнопки выдаётся другая команда — «стоп» (какие именно байты передаются приведено ниже).

Блок управления.На прошлых этапах определили что именно будет подключено к блоку управления. Сердце блока управления — Arduino nano. Что это такое? За что отвечают вон те лампочки и вот эти разъёмы? К каким выводам подключены ножки от сонара? Да и вообще:, а с сонаром-то как общаться?

Начинаем упорно изучать информацию по комплектующим. Благо, в библиотеку ходить не нужно при наличии интернета. Составляем для себя технические описания используемых компонентов. Можно вычитывать на русскоязычных ресурсах какая плата как работает и конспектировать. Для того, чтобы понять, как подключать и как работать с конечными устройствами, создаются свои «даташиты», в которых всё предельно кратко, ясно и понятно. Возможно, достаточно будет просто изучения англоязычных datasheet от производителя, но порой бывает, что язык китайский или сам по себе datasheet довольно объёмный (страниц этак на 200), поэтому делать свои краткие записи разумно.

Создаём для себя «хелп» по микроконтроллеру:

Carduino Nano v. 7 a0233ac8474d490eaf55ecc4f2ddcd1c.jpg Затем разбираемся как подключаются и управляются периферийные устройства. Драйвер двигателей: Драйвер двигателей на базе микросхемы L9110S 527e19ec666740f487b0e762bca3544b.jpg daaaaa5feff74c33b804d9924c9d6877.jpg И ультразвуковой датчик: Сонар HC-SR04 153643c726ee42188700730c83d79296.jpg a8c6ffeab1af4fd8aeb64b0059e9d96e.jpg После всего этого осмысления рисуется структурная схема соединения программных модулей, которая отражает взаимодействие с ними и содержит информацию что и куда подключено (к каким ножкам микроконтроллера):

a6d545bf6b234a30a0566fcfa003e3dc.jpg Рисование этой схемы требует хороших мыслительных усилий — ведь задаётся по сути каркас, на который потом будет ложится код. Тут необходимо сделать ремарку. Дело в том, что я занимаюсь разработкой на ПЛИС, поэтому, изначально я и разрисовал структуру так, как делал бы для ПЛИС. Надо понимать, что для СИ-подобного программирования количество сигналов на схеме вообще-то избыточно. Но зато мы получаем некую платформонезависимость — можно всё реализовать на ПЛИС попробовать, тем более есть доступные варианты.

Давайте прочитаем эту схему слева направо. Интерфейсный модуль по UART получит данные. Если данные являются командой, то он выдаёт управляющий байт CTRL под импульсным стробом SCTRL на модуль управления. Модуль управления, получив строб, понимает, что пришла какая-то команда, читает вход CTRL и выполняет команду. Допустим, пришла команда «вперёд». На выход выдаётся импульсный сигнал Get_Dist и ожидаются данные дальности по входу Dist. В принципе, нам не запрещено постоянно выдавать импульсы Get_Dist, в этом случае значение дальности мы можем просто снимать с входного порта Dist в нужное нам время. Допустим с дальностью всё в порядке — до препятствия еще далеко, можно и прокатиться с ветерком. На модуль управления моторами по шине Mode выдаётся сигнал, говорящий о том, что нужно двигаться вперёд с заданной скорость Speed. При измерении дальности и при движении на соответствующие светодиоды так же выдаётся высокий уровень (логическая единица) для индикации работы и понимания что происходит с системой (полезно будет при отладке).

Модульная схема есть! В голове порядок! Понятно как и что. Теперь надо только это описать — что каждый модуль должен делать и при каких условиях.

Интерфейсный модуль:

Модуль управления:

Модуль измерения дальности:

Модуль управления двигателями: aef33b1ff6294f229d885468800f71ea.jpg 4fbe88a71b3245b485126e0a5727ed4c.jpg Из-под края листа за угол стола вывалился хвостик с вилкой от паяльника. Лист немного сполз и открылась его мордочка. Паяльник смотрит с выражением даже не требующим жеста «покрутить палец у виска»: «сам себе ТЗ пишет — чё за ересь… вот «повезло» мне с владельцем, однако» — грустно подумал он, незаметно покачивая вилкой питания за столом.

Пятый этап — сотворение

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

Хватаем грустный паяльник и включаем в розетку. Он начинает греться и шипеть от удовольствия в те моменты, когда мы очищаем жало о губку. Флюс с припоем водят дружный хоровод на столе. Солнце заглядывает в окно, подсвечивая место точечной пайки SMD резистора на плате. Жизнь хороша, когда паяешь не спеша!

e1e1fb83ba094c66aa581307784ad78d.JPG 50567c4866b94929a595e6ef4dca99dd.JPG Самый веселый и зрелищный этап разработки, который никого не оставит равнодушным. Тут уже на глазах получается что-то интересное, всем очевидное. Этот этап контрастирует со всеми предыдущими, так как рисование каких-то картинок с табличками, мало того, что неинтересно наблюдателю так еще и искренне непонятно, как из этого может что-то получиться. А тут… это же так здорово, когда твой первый робот проедет свой первый сантиметр на столе и почтительно остановится от края ровно за 20 сантиметров только потому, что ты ладонью загородил край стола. Умная тварюшка получилась — понимает что дальше ему нельзя!

3401ae4f874a4e56a4367046fada4e31.JPG 3e50b20577f44312b3411d153a3e544c.JPG На этом этапе собираем всю механическую конструкцию, паяем провода, программируем микроконтроллер. Тестируем, что получилось. Не понимаем. Думаем. Правим ТЗ, так как в реальности оказывается, может быть, совсем иначе, чем написано и напридумано! Возвращаемся снова к сборке. Тестируем. Не понимаем. Не унываем. Тыкаем мультиметром и заменяем разрядившиеся батарейки. Радуемся…

09ba71d3b2894819912d832310922e84.JPG 5e250485914643cea700579ac66e7a84.JPG 33c5df7c2aca4356a7fb8f34a677bef6.JPG Строго говоря, по завершении этого этапа должен быть сформирован список, который в совокупе с вышеприведенной документацией обеспечивал бы повторяемость результата. Крупные комплектующие я приводил выше, однако, при формировании заказа я попросил положить также необходимую «рассыпуху»: переключатель питания, разъем для подключения батарейного отсека, колодки разъёмов 2,54 мм…

347b244dd59b4960be664715ad13c08d.JPG 6949c0c4d3f04863bcc66425d0d23225.JPG Помимо этого в работе использовались расходные материалы — провода, припой, флюс, а также инструменты. Если есть какие-то технологические нюансы, на них тоже должно быть акцентировано внимание.

d6caf974315f4a798616ec0dea2a8c45.JPG Программу я писал два раза.Первый раз написалось так, как написалось. Активно читал сайт arduino.ru Я и не программу больше писал, а разбирался с синтаксисом, вспоминал Си и постоянно матерился на последовательность выполнения программного кода (я-то привык к параллельности исполнения кода, когда по тактам/циклам работают все вычислительные блоки, а не отрабатывается только одна строка).Второй раз я подошел к орагнизации программы жестко структурно. Не всегда это оказалось оправдано, но если задали изначальный стиль, то его нужно придерживаться. Смысл заключается в… повторении в коде структуры программных моделй нарисованных выше. В коде сначала у нас объявляются все переменные и прописываются настроечные константы. Затем следует блок инициализации «void setup». А затем следует основной цикл «void loop», задачей которого является непрерывный опрос модулей. Каждый модуль имеет свои входные и выходные переменные, которые влияют на его работу. В основном цикле происходит управление этими переменными. Опрашиваемая кнопка задаёт режимы работы всех модулей. Если по интерфейсу пришла команда, то она транслируется на другие модули управления, если не активирован автономный режим. Сначала у меня было только два модуля — управления мотором и светом. Затем появился модуль формирования звука, который я сделать не успел. Тут как раз и сказалась заложенная структура — просто и понятно добавлять/исключать модули: блок в объявления переменных, строчку в инициализацию, строчку в основной цикл и код самого модуля. Модуль определения дальности и модуль реализующий алгоритм поворотов вызываются из других модулей по необходимости.

Текст программы ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Robot Platform RASH 1 © AlSHex // 1.0 // // Create: 23/03/2015 // Modification: 11/04/2015 // // Description: Программа управления платформой RASH 1 // //////////////////////////////////////////////////////////////////////////////////////////////////////////

//припиновка const int LEDtech = 13; //вывод технологического сигнала на светодиод const int LEDdist = 3; //вывод сигнала от сонара на светодиод const int Sonar_t = 14; //данные на сонар const int Sonar_r = 15; //данные от сонара const int Mode = 16; //подключение кнопки установки режима — автономный или ручной: =0 — ручной; 1= автономный режим const int MB1 = 4; //левый мотор — digital const int MB2 = 5; //левый мотор — pwm const int MA1 = 6; //правый мотор — pwm const int MA2 = 7; //правый мотор — digital const int HDL = 17; //вывод сигнала на фары const int SPK = 11; //вывод сигнала на динамик //const int LGHT = ; //данные от датчика освещенности

//настройка модуля интерфейса const long UART_Speed = 9600; //Скорость UART

//настройка модуля сонара const int D1 = 20; //коэффициенты функции ШИМ для вывода данных сонара на светодиод const int D2 = 110; const float A = 2.5; const float B = 305;

//настройка модуля управления const byte Byte_forward = byte ('W'); //команда: вперед const byte Byte_back = byte ('S'); //команда: назад const byte Byte_left = byte ('A'); //команда: влево const byte Byte_right = byte ('D'); //команда: вправо const byte Byte_stop = byte ('x'); //команда: стоп const byte Byte_sound = byte ('C'); //команда: звуковой сигнал/мелодия const byte Byte_light = byte ('V'); //команда: фары const int Dist_min = 40; //минимальная дистанция, при которой робот запустит алгоритм объезда препятствий [см] const int Cycle_lightoff = 1000; //кол-во циклов повтора программы после которого отключаются включенные фары в автономном режиме const int Speed_default = 255; //значение по умолчанию, которое будет использоваться после включения пока не придёт команда, скорость сбрасывается в значение по умолчанию при переходе на автономный режим

//общие настройки const int Delay_prog = 10; //задержка выполнения повтора программы, [мс] const int M_stop = 0; //константы для модуля мотора (для удобства ипользования) const int M_forward = 1; const int M_back = 2; const int M_left = 3; const int M_right = 4;

//объявление и описание модулей — функций

//========== Interface ========== void _UART_Interf (unsigned int RST, unsigned int *Data); //данные от интерфейса: Data[0]=1 — наличие команды; Data[1] — данные команды //RST — сброс: 0= нормальная работа; 1= сброс //Data — массив данных от интерфейса: Data[0]=1 — наличие команды; Data[1] — данные команды // //Подсоединенеи к UART происходит с помощью библиотеки Serial

//========== Motor ========== void _Motor (unsigned int RST, unsigned int Mode, unsigned int Speed); //RST — сброс: 0= нормальная работа; 1= сброс //Mode — режим работы: 0= стоп; 1= движение вперед; 2= движение назад; 3= поворот налево; 4= поворот направо //Speed: скорость вращения двигателей — уровень, фомируемый ШИМ: 0= нулевой уровень; 255= максимальный уровень // //MA1, MA2, MB1, MB2 — сигналы припиновки двигателей, MB1 и MA2 — цифровые, MB2 и MA1 — аналоговые (0/255) //LEDtech — цифровой сигнал припиновки для технологического светодиода, загорается при выполнении команды и гаснет при получении команды «стоп»

//========== Sonar ========== unsigned int _Sonar (unsigned int RST); //RST — сброс: 0= нормальная работа; 1= сброс // //Sonar_t — цифровой сигнал припиновки для сонара Trig //Sonar_r — цифровой сигнал припиновки для сонара Echo //LEDdist — аналоговый (0/255) сигнал припиновки для светодиода, на который будет выводиться ШИМ-сигнал для визуализации дальности — чем ближе объект, тем светодиод будет гореть ярче

//========== Control Motor ========== void _ControlM (unsigned int RST, unsigned int SCTRL, unsigned int DCTRL, unsigned int Mode); //RST — сброс: 0= нормальная работа; 1= сброс //SCTRL — сигнал актуальности данных DCTRL: 0= неактулальны; 1= актуальны //DCTRL — данные (команда) от модуля интерфейса //Mode — режим управления: 0= управления по командам; 1= автономный режим // //Модуль обращается к модулям Sonar, Motor и Rotate //LEDtech — цифровой сигнал припиновки для технологического светодиода, загорается на 1 секунду при получении команды установки скорости

//========== Control Light ========== void _ControlL (unsigned int RST, unsigned int SCTRL, unsigned int DCTRL, unsigned int Mode); //RST — сброс: 0= нормальная работа; 1= сброс //SCTRL — сигнал актуальности данных DCTRL: 0= неактулальны; 1= актуальны //DCTRL — данные (команда) от модуля интерфейса //Mode — режим управления: 0= управления по командам; 1= автономный режим // //HDL — цифровой сигнал припиновки для управления фарами: 0= фары выключены; 1= фары включены

//========== Control Sound ========== void _ControlS (unsigned int RST, unsigned int SCTRL, unsigned int DCTRL, unsigned int Mode); //RST — сброс: 0= нормальная работа; 1= сброс //SCTRL — сигнал актуальности данных DCTRL: 0= неактулальны; 1= актуальны //DCTRL — данные (команда) от модуля интерфейса //Mode — режим управления: 0= управления по командам; 1= автономный режим // //SPK — аналоговый (0/255) сигнал припиновки для вывода ШИМ сигнала

//========== Rotate ========== — алгоритм вращения, модуль выделенный из состава модуля ControlM в самостоятельный void _Rotate (unsigned int RST, unsigned int Speed); //RST — сброс: 0= нормальная работа; 1= сброс //Speed: скорость вращения двигателей — уровень, фомируемый ШИМ: 0= нулевой уровень; 255= максимальный уровень

//объявление переменных unsigned int CMD[2] = {0,0}; //данные от интерфейса: CMD[0]=1 — наличие команды; CMD[1] — данные команды unsigned int CTRL[8] = {0,0,0,0,0,0,0,0}; //массив сигналов управления //CTRL[0]: 0= нормальная работа; 1= сброс модулей //CTRL[1]: 0= ручной режим; 1= автономный режим

void setup () { //припиновка pinMode (MB1, OUTPUT); digitalWrite (MB1, LOW); pinMode (MB2, OUTPUT); analogWrite (MB2, 0); pinMode (MA1, OUTPUT); analogWrite (MA1, 0); pinMode (MA2, OUTPUT); digitalWrite (MA2, LOW); pinMode (Sonar_t, OUTPUT); digitalWrite (Sonar_t, LOW); pinMode (Sonar_r, INPUT); digitalWrite (Sonar_r, LOW); pinMode (LEDdist, OUTPUT); analogWrite (LEDdist, 0); pinMode (Mode, INPUT); digitalWrite (Mode, LOW); pinMode (LEDtech, OUTPUT); digitalWrite (LEDtech, LOW); pinMode (HDL, OUTPUT); digitalWrite (HDL, LOW); pinMode (SPK, OUTPUT); analogWrite (SPK, 0); //начальная инициализация модулей Serial.begin (UART_Speed); _UART_Interf (1, CMD); _UART_Interf (0, CMD); _Sonar (1); _Sonar (0); _Motor (1, 0, 0); _Motor (0, 0, 0); _Rotate (1, 0); _Rotate (0, 0); _ControlM (1, 0, 0, 0); _ControlM (0, 0, 0, 0); _ControlL (1, 0, 0, 0); _ControlL (0, 0, 0, 0); _ControlS (1, 0, 0, 0); _ControlS (0, 0, 0, 0); }

void loop () { //опрос кнопки режима и установка режима работы if (digitalRead (Mode) == LOW) { if (CTRL[1] == 1) { CTRL[0] = 1; } else { CTRL[0] = 0; } //если было переключении из другого режима, то будет выдан reset на все схемы при проходе программы, на след. проходе reset снимется CTRL[1] = 0; } else { if (CTRL[1] == 0) { CTRL[0] = 1; } else { CTRL[0] = 0; } CTRL[1] = 1; }© Habrahabr.ru