Компьютерная грамотность
  • Главная
  • Windows
  • Электроника и котики: собираем робота-игрушку для кота на STM32. Создаем робота в домашних условиях Какие компоненты доступны для конкретного микроконтроллера

Электроника и котики: собираем робота-игрушку для кота на STM32. Создаем робота в домашних условиях Какие компоненты доступны для конкретного микроконтроллера

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

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

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

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

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

Питание

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

Адаптация и поведение

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

Концепция BEAM-роботов, предложенная Марком Тилденом, состояла в том, что реакция на внешние факторы должна обеспечиваться на первом этапе самой машиной, без участия какого-либо "мозга", как это происходило и в живой природе, на пути от простейших к человеку. По этому же пути должно идти совершенствование и создание более сложных робосистем.

Виды

Существуют разные виды роботов BEAM, которые созданы для выполнения разных задач.
Аудиотропы - реагируют на звуки.
Фототропы - реагируют на свет.
Радиотропы - реагируют на радиочастоты.
Термотропы - реагируют на тепловое излучение.

Наиболее часто встречаются фототропы, поскольку поиск света является наиболее очевидной задачей для использующего солнечную энергию робота.

Модульная структура

Лично мне нравится идея создания BEAM робота из отдельных функциональных модулей, и руководствуясь принципом "от простого к сложному" можно будет развивать робота, добавляя все новые и новые модули. Каждый модуль сам по себе может работать отдельно, т.е. не будет использоваться централизованный мозг для обработки информации.

Шасси

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

1. Гусеничное.

На рисунке представлено готовое шасси, которое не трудно найти в продаже. В большинстве случаев приходит в движение от пары мотор-редукторов.
Плюсы: хорошо поворачивает, не используя при этом рулевые механизмы; имеет повышенную проходимость; на него удобно монтировать электрические платы и отдельные компоненты.
Минусы: такое шасси трудно собрать дома самому, а стоимость составляет в среднем 90 долларов.

2. Шасси на колесах.


Плюсы: самый простой тип в отношении того, что его можно собрать дома самому (например из детского конструктора и пр.) или использовать игрушечную машинку.
Минусы: для осуществления поворота требуется рулевой поворотный механизм, а значит придется использовать дополнительный электродвигатель, что влечет за собой увеличение массы конструкции и повышение потребления электроэнергии.

3. Робот на ногах.


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

ДЕЛАЕМ САМИ!

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

За основу можно взять коробочку. Лучше из пластмассы, потому что это легкий материал. В этой же коробке удобно разместить элемент питания: аккумулятор, батарейки и т.п.
Учитывайте, что чем больше колеса, тем медленнее будет ехать робот (а может и не сдвинуться с места).

Второй вариант. Здесь использованы пластиковые хомутики для закрепления моторчиков.

Электромоторы можно взять со старой техники: магнитофоны, игрушки, дисководы и пр.

У меня дома имелись моторчики трех типов:

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

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

Ниже представлена простая схема робота, который едет на свет фонарика.

Схема 1. "Идущий на свет".

В этой схеме использованы фотодиоды. Их выбираем по диапазону чувствительности, т.е. учитывая на какой свет робот будет идти. К примеру на свет от фонарика (видимый диапазон) или на лучик пульта от телевизора (инфракрасный диапазон). Если осветить фотоэлемент VD1, то будет вращаться Мотор 1, а если осветить фотоэлемент VD2, то будет вращаться Мотор 2. Учитывая это, моторы расположим так, чтобы когда VD1 освещен Мотор 1 поворачивал робота к свету.

А если моторы поменять местами, то робот наоборот будет отворачиваться от света.

Теперь рассмотрим фотоэлементы.
В качестве элементов, чувствительных к свету используются фотодиоды, фототранзисторы, фоторезисторы и т.п. В интернете присутствует много информации по этим элементам, поэтому я опишу их вкратце.

1. Фоторезистор: в темноте он представляет собой высокоомный резистор, а при освещении светом его сопротивление падает пропорционально интенсивности света, проявляя линейную зависимость. Как правило воспринимают только видимый свет.

2. Фотодиод: полупроводниковый прибор, так же как и обычный диод имеет анод и катод.
Если применить прямое включение, то освещенный фотодиод будет вырабатывать напряжение на выводах.
При обратном включении сопротивление облученного фотодиода падает так же как у фоторезистора.
По диапазону света фотодиоды делятся на ИК-диоды и для видимого света. ИК-диоды воспринимают только инфракрасное излучение, но также хорошо реагируют на лампы накаливания и на Солнце.

3. Фототранзистор: отличается от обычного транзистора тем, что на область базы подается свет, который управляет усилением тока эмиттер-коллектор.

Без особого успеха в качестве светочувствительного элемента можно использовать светодиод. Он обладает слишком малой чувствительностью и усилить ее можно лишь с помощью дополнительной схемы.

BEAM-робот, который получился у меня

В своем роботе я использовал разные фотодиоды неизвестного происхождения. На видео видно, что чувствительность одного из них больше.
Один из фотодиодов реагирует на лучик пульта от телевизора.
Также вся "начинка" залита термоклеем.
Надеюсь у вас получится лучше и красивее!

Список радиоэлементов

Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
VT1, VT3 Биполярный транзистор

КТ3102

2 КТ315 В блокнот
VT2, VT4 Биполярный транзистор

КТ361Б

2 КТ816

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

10 ресурсов для начинающего робототехника

Информация на сайте позволяет самостоятельно создать робота со сложным поведением. Здесь можно найти примеры программ, схемы, справочные материалы, готовые примеры, статьи и фотографии.

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

На сайте есть специальный курс «Шаг за шагом», в котором детально описан процесс создания простейших BEAM-роботов, а также автоматизированных систем на основе микроконтроллеров AVR.

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

Данный ресурс посвящён постепенному погружению в мир сотворения роботов. Начинается всё с познания Arduino, после чего начинающему разработчику рассказывают о микроконтроллерах AVR и более современных аналогах ARM. Подробные описания и схемы очень доступно объясняют, как и что делать.

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

На этом ресурсе очень доходчиво расписано, как самостоятельно создать робота, с чего начать, что нужно знать, где искать информацию и необходимые детали. Сервис также содержит раздел с блогом, форумом и новостями.

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

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

Аппаратная платформа Arduino является наиболее удобной для разработки роботизированных систем. Информация сайта позволяет быстро разобраться в этой среде, освоить язык программирования и создать несколько несложных проектов.

Наверняка, насмотревшись фильмов про роботов, тебе не раз хотелось построить своего боевого товарища, но ты не знал с чего начать. Конечно, у тебя не получится построить двуногого терминатора, но мы и не стремимся к этому. Собрать простого робота может любой, кто умеет правильно держать паяльник в руках и для этого не нужно глубоких знаний, хотя они и не помешают. Любительское роботостроение мало чем отличается от схемотехники, только гораздо интереснее, потому что тут так же затронуты такие области, как механика и программирование. Все компоненты легкодоступны и стоят не так уж и дорого. Так что прогресс не стоит на месте, и мы будем его использовать в свою пользу.

Введение

Итак. Что же такое робот? В большинстве случаев это автоматическое устройство, которое реагирует на какие-либо действия окружающей среды. Роботы могут управляться человеком или выполнять заранее запрограммированные действия. Обычно на роботе располагают разнообразные датчики (расстояния, угла поворота, ускорения), видеокамеры, манипуляторы. Электронная часть робота состоит из микроконтроллера (МК) – микросхема, в которую заключён процессор, тактовый генератор, различная периферия, оперативная и постоянная память. В мире существует огромное количество разнообразных микроконтроллеров для разных областей применения и на их основе можно собирать мощных роботов. Для любительских построек широкое применение нашли микроконтроллеры AVR. Они, на сегодняшний день, самые доступные и в интернете можно найти много примеров на основе этих МК. Чтобы работать с микроконтроллерами тебе нужно уметь программировать на ассемблере или на Cи и иметь начальные знания в цифровой и аналоговой электронике. В нашем проекте мы будем использовать Cи. Программирование для МК мало чем отличается от программирования на компьютере, синтаксис языка такой же, большинство функций практически ничем не отличаются, а новые довольно легко освоить и ими удобно пользоваться.

Что нам нужно

Для начала наш робот будет уметь просто объезжать препятствия, то есть повторять нормальное поведение большинства животных в природе. Всё что нам потребуется для постройки такого робота можно будет найти в радиотехнических магазинах. Решим, как наш робот будет передвигаться. Самым удачным я считаю гусеницы, которые применяются в танках, это наиболее удобное решение, потому что гусеницы имеют большую проходимость, чем колёса машины и ими удобнее управлять (для поворота достаточно вращать гусеницы в разные стороны). Поэтому тебе понадобится любой игрушечный танк, у которого гусеницы вращаются независимо друг от друга, такой можно купить в любом магазине игрушек по разумной цене. От этого танка тебе понадобится только платформа с гусеницами и моторы с редукторами, остальное ты можешь смело открутить и выкинуть. Так же нам потребуется микроконтроллер, мой выбор пал на ATmega16 – у него достаточно портов для подключения датчиков и периферии и вообще он довольно удобный. Ещё тебе потребуется закупить немного радиодеталей, паяльник, мультиметр.

Делаем плату с МК



Схема робота

В нашем случае микроконтроллер будет выполнять функции мозга, но начнём мы не с него, а с питания мозга робота. Правильное питание – залог здоровья, поэтому мы начнём с того, как правильно кормить нашего робота, потому что на этом обычно ошибаются начинающие роботостроители. А для того, чтобы наш робот работал нормально нужно использовать стабилизатор напряжения. Я предпочитаю микросхему L7805 – она предназначена, чтобы на выходе выдавать стабильное напряжение 5В, которое и нужно нашему микроконтроллеру. Но из-за того, что падение напряжения на этой микросхеме составляет порядка 2,5В к нему нужно подавать минимум 7,5В. Вместе с этим стабилизатором используются электролитические конденсаторы, чтобы сгладить пульсации напряжения и в цепь обязательно включают диод, для защиты от переполюсовки.
Теперь мы можем заняться нашим микроконтроллером. Корпус у МК - DIP (так удобнее паять) и имеет сорок выводов. На борту имеется АЦП, ШИМ, USART и много другого, что мы пока использовать не будем. Рассмотрим несколько важных узлов. Вывод RESET (9-ая нога МК) подтянут резистором R1 к «плюсу» источника питания – это нужно делать обязательно! Иначе твой МК может непреднамеренно сбрасываться или, проще говоря – глючить. Так же желательной мерой, но не обязательной является подключение RESET’а через керамический конденсатор C1 к «земле». На схеме ты так же можешь увидеть электролит на 1000 мкФ, он спасает от провалов напряжения при работе двигателей, что тоже благоприятно скажется на работе микроконтроллера. Кварцевый резонатор X1 и конденсаторы C2, C3 нужно располагать как можно ближе к выводам XTAL1 и XTAL2.
О том, как прошивать МК, я рассказывать не буду, так как об этом можно прочитать в интернете. Писать программу мы будем на Cи, в качестве среды программирования я выбрал CodeVisionAVR. Это довольно удобная среда и полезна новичкам, потому что имеет встроенный мастер создания кода.


Плата моего робота

Управление двигателями

Не менее важным компонентом в нашем роботе является драйвер двигателей, который облегчает нам задачу в управлении им. Никогда и ни в коем случае нельзя подключать двигатели напрямую к МК! Вообще мощными нагрузками нельзя управлять с микроконтроллера напрямую, иначе он сгорит. Пользуйтесь ключевыми транзисторами. Для нашего случая есть специальная микросхема – L293D. В подобных несложных проектах всегда старайтесь использовать именно эту микросхему с индексом «D», так как она имеет встроенные диоды для защиты от перегрузок. Этой микросхемой очень легко управлять и её просто достать в радиотехнических магазинах. Она выпускается в двух корпусах DIP и SOIC. Мы будем использовать в корпусе DIP из-за удобства монтажа на плате. L293D имеет раздельное питание двигателей и логики. Поэтому саму микросхему мы будем питать от стабилизатора (вход VSS), а двигатели напрямую от аккумуляторов (вход VS). L293D выдерживает нагрузку 600 мА на каждый канал, а этих каналов у неё два, то есть к одной микросхеме можно подключить два двигателя. Но, чтобы перестраховаться, мы объединим каналы, и тогда потребуется по одной микре на каждый двигатель. Отсюда следует, что L293D сможет выдержать 1.2 А. Чтобы этого добиться нужно объединить ноги микры, как показано на схеме. Микросхема работает следующим образом: когда на IN1 и IN2 подаётся логический «0», а на IN3 и IN4 логическая единица, то двигатель вращается в одну сторону, а если инвертировать сигналы – подать логический ноль, тогда двигатель начнёт вращаться в другую сторону. Выводы EN1 и EN2 отвечают за включение каждого канала. Их мы соединяем и подключаем к «плюсу» питания от стабилизатора. Так как микросхема греется во время работы, а установка радиаторов проблематична на этот тип корпуса, то отвод тепла обеспечивается ногами GND - их лучше распаивать на широкой контактной площадке. Вот и всё, что на первое время тебе нужно знать о драйверах двигателей.

Датчики препятствий

Чтобы наш робот мог ориентироваться и не врезался во всё, мы установим на него два инфракрасных датчика. Самый простейший датчик состоит из ик-диода, который излучает в инфракрасном спектре и фототранзистор, который будет принимать сигнал с ик-диода. Принцип такой: когда перед датчиком нет преграды, то ик-лучи не попадают на фототранзистор и он не открывается. Если перед датчиком препятствие, тогда лучи от него отражаются и попадают на транзистор – он открывается и начинает течь ток. Недостаток таких датчиков в том, что они могут по-разному реагировать на различные поверхности и не защищены от помех - от посторонних сигналов других устройств датчик, случайно, может сработать. От помех может защитить модулирование сигнала, но пока мы этим заморачиватся не будем. Для начала, и этого хватит.


Первый вариант датчиков моего робота

Прошивка робота

Чтобы оживить робота, для него нужно написать прошивку, то есть программу, которая бы снимала показания с датчиков и управляла двигателями. Моя программа наиболее проста, она не содержит сложных конструкций и всем будет понятна. Следующие две строки подключают заголовочные файлы для нашего микроконтроллера и команды для формирования задержек:

#include
#include

Следующие строки условные, потому что значения PORTC зависят от того, как ты подключил драйвер двигателей к своему микроконтроллеру:

PORTC.0 = 1;
PORTC.1 = 0;
PORTC.2 = 1;
PORTC.3 = 0;

Значение 0xFF означает, что на выходе будет лог. «1», а 0x00 – лог. «0».

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

If (!(PINB & (1< {
...
}

Если на фототранзистор попадает свет от ик-диода, то на ноге микроконтроллера устанавливается лог. «0» и робот начинает движение назад, чтобы отъехать от препятствия, потом разворачивается, чтобы снова не столкнуться с преградой и затем опять едет вперёд. Так как у нас два датчика, то мы проверяем наличие преграды два раза – справа и слева и потому можем узнать с какой стороны препятствие. Команда «delay_ms(1000)» указывает на то, что пройдёт одна секунда, прежде чем начнёт выполняться следующая команда.

Заключение

Я рассмотрел большинство аспектов, которые помогут тебе собрать твоего первого робота. Но на этом робототехника не заканчивается. Если ты соберёшь этого робота, то у тебя появится куча возможностей для его расширения. Можно усовершенствовать алгоритм робота, как например, что делать, если препятствие не с какой-то стороны, а прямо перед роботом. Так же не помешает установить энкодер – простое устройство, которое поможет точно располагать и знать расположение твоего робота в пространстве. Для наглядности возможна установка цветного или монохромного дисплея, который может показывать полезную информацию – уровень заряда аккумулятора, расстояние до препятствия, различную отладочную информацию. Не помешает и усовершенствование датчиков – установка TSOP (это ик-приёмники, которые воспринимают сигнал только определённой частоты) вместо обычных фототранзисторов. Помимо инфракрасных датчиков существуют ультразвуковые, стоят подороже, и тоже не лишены недостатков, но в последнее время набирают популярность у роботостроителей. Для того, чтобы робот мог реагировать на звук, было бы неплохо установить микрофоны с усилителем. Но по-настоящему интересным, я считаю, установка камеры и программирование на её основе машинного зрения. Есть набор специальных библиотек OpenCV, с помощью которых можно запрограммировать распознавание лиц, движения по цветным маякам и много всего интересного. Всё зависит только от твоей фантазии и умений.
Список компонентов:
  • ATmega16 в корпусе DIP-40>
  • L7805 в корпусе TO-220
  • L293D в корпусе DIP-16 х2 шт.
  • резисторы мощностью 0,25 Вт номиналами: 10 кОм х1 шт., 220 Ом х4 шт.
  • конденсаторы керамические: 0.1 мкФ, 1 мкФ, 22 пФ
  • конденсаторы электролитические: 1000 мкФ х 16 В, 220 мкФ х 16В х2 шт.
  • диод 1N4001 или 1N4004
  • кварцевый резонатор на 16 МГц
  • ИК-диоды: подойдут любые в количестве двух штук.
  • фототранзисторы, тоже любые, но реагирующие только на длину волны ик-лучей
Код прошивки:
/*****************************************************
Прошивка для робота

Тип МК: ATmega16
Тактовая частота: 16,000000 MHz
Если у тебя частота кварца другая, то это нужно указать в настройках среды:
Project -> Configure -> Закладка "C Compiler"
*****************************************************/

#include
#include

Void main(void)
{
//Настраиваем порты на вход
//Через эти порты мы получаем сигналы от датчиков
DDRB=0x00;
//Включаем подтягивающие резисторы
PORTB=0xFF;

//Настраиваем порты на выход
//Через эти порты мы управляем двигателями
DDRC=0xFF;

//Главный цикл программы. Здесь мы считываем значения с датчиков
//и управляем двигателями
while (1)
{
//Едем вперёд
PORTC.0 = 1;
PORTC.1 = 0;
PORTC.2 = 1;
PORTC.3 = 0;
if (!(PINB & (1< {
//Едем назад 1 секунду
PORTC.0 = 0;
PORTC.1 = 1;
PORTC.2 = 0;
PORTC.3 = 1;
delay_ms(1000);
//Заворачиваем
PORTC.0 = 1;
PORTC.1 = 0;
PORTC.2 = 0;
PORTC.3 = 1;
delay_ms(1000);
}
if (!(PINB & (1< {
//Едем назад 1 секунду
PORTC.0 = 0;
PORTC.1 = 1;
PORTC.2 = 0;
PORTC.3 = 1;
delay_ms(1000);
//Заворачиваем
PORTC.0 = 0;
PORTC.1 = 1;
PORTC.2 = 1;
PORTC.3 = 0;
delay_ms(1000);
}
};
}

О моём роботе

В данный момент мой робот практически завершён.


На нём установлена беспроводная камера, датчик расстояния (и камера и этот датчик установлены на поворотной башне), датчик препятствия, энкодер, приёмник сигналов с пульта и интерфейс RS-232 для соединения с компьютером. Работает в двух режимах: автономном и ручном (принимает сигналы управления с пульта ДУ), камера также может включаться/выключаться дистанционно или самим роботом для экономии заряда батарей. Пишу прошивку для охраны квартиры (передача изображения на компьютер, обнаружение движений, объезд помещения).

По пожеланиям выкладываю видео:

UPD. Перезалил фотографии и сделал небольшие поправки в тексте.

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

Предыстория и постановка задачи

Пол года назад у меня появился вот этот черный красавец мейн-кун, которого я назвал Артасом в честь известного героя компьютерной игры.

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

  1. Защищенность критичных частей конструкции от котовых зубов и когтей, в идеале - полностью закрытый корпус (шарик)
  2. Из предыдущего пункта следует требование к малым габаритам устройства, т.к. желательно, чтобы это все-таки был небольшой шарик, а не футбольный мяч.
  3. Возможность управления с мобильного телефона/планшета и стационарного компьютера - чтобы не изобретать велосипед и обеспечить совместимость с мобильными устройствами идеально подойдет связь по Bluetooth.
  4. Чтобы было поинтереснее желательно наличие хоть какого-нибудь датчика, который бы позволил в перспективе сделать робота более-менее автономным, а не просто радиоуправляемой машинкой.
  5. Наличие какого-нибудь способа вывести звук, чтобы привлекать внимание котэ.

Сразу же продемонстрирую короткое видео того, что получилось, кошкобот запущен в тестовом режиме (управляется мною, с компьютера):

Кошкобот тестируется без внешней оболочки, издает привлекающие кота звуки и не может убежать т.к. выходит из строя один из приводов.
(Об этом подробнее в конце статьи)


Кошкобот в сборе

Некоторым может показаться, что кот не очень активно реагирует на робота, но на самом деле причина в том, что за время тестирования он уже сотню раз выхватывал его у меня, уносил и грыз. Разумеется, робота я отбирал (пока он не закончен), поэтому кот, видя робота на полу, решил выжидать некоторое время, чтобы удостовериться, что у него его не отберут сразу же, как только он нападет)

Разработка: выбор элементной базы и подготовка
Корпус
Определившись с предполагаемой конструкцией я приобрел пару пластиковых шариков, состоящих из двух половинок - один диаметром 60 мм, другой - 80 мм, на случай если в первый не удастся вместиться. Такие габариты сильно ограничили выбор двигателей и датчиков (в том смысле, что, например, об УЗ-датчике можно было забыть, он не вместился бы в шар и, более того, не стал бы работать в закрытом пространстве.

Микроконтроллер
После отпиливания «ушка», шары стали идеальными кандидатами на роль корпуса. В силу ограниченности габаритов, было решено проектировать всю схематику с использованием самых малогабаритных корпусов, то есть, большей частью, QFN.
В качестве центрального процессора был выбран STM32F101 , так как это микроконтроллер на ядре Кортекс М3, а не урезанном М0, при этом он может работать на 36 МГц, обладает 64 КБ флеша и 16 КБ ОЗУ, и, самое главное, выпускается в 6х6 мм QFN-корпусе.
Датчик
В качестве датчика был выбран трехосный акселерометр от тех же ST, на который как раз была скидка в Терраэлектронике, так что он достался мне по цене около 30 рублей за штуку.

Акселерометр выпускается в корпусе QFN, 3х3 мм и может общаться по шине I2C, что весьма кстати в условиях ограниченных габаритов. При помощи акселерометра возможно вычилить наклон робота по трем осям, а также, возможно попробовать получить от него информацию о том, движется ли робот, или налетел на препятствие (по изменению ускорения). Ну и, конечно, определить момент, в которые его пинает кот, чтобы издать писк - таким образом кот будет считать, что это что-то живое)

Связь
В качестве средства связи, конечно, берем зарекомендовавшие себя, дешевые и малогабаритные китайские модули HC-05

Это единственный готовый модуль в составе робота.
Источник звука
Изначально я хотел использовать малогабаритные динамики, но, к сожалению, даже самые малогабаритные все равно были весьма большими. К тому же они немало потребляли и требовали как минимум транзистора и фильтра, для того, чтобы раскачать их ШИМом. После некоторого количества гугления я нашел вот такую вот занятную пьезо-пищалку:

PKLCS1212E4001 фирмы Murata стоит 48 рублей, имеет габариты 11х11 мм (самый большой элемент на плате!) и является стандартным Piezo Sounder"ом - устройством, которое издает звук за счет изгиба мембраны пьезоэлектрическим эффектом. А это значит, что она потребляет на порядки меньше тока, чем динамик, пищащий на той же громкости.
Но, в отличие от динамика у нее весьма хитрая и неровная АЧХ, так что лучше всего она умеет именно пищать. И громче всего у нее получается это делать на частоте 4КГц (но это не значит, что нельзя пищать на других!)
Приводы
Важнейший элемент - приводы, которые будут двигать робота. К сожалению, с ними было не все так гладко, как хотелось бы, об этом подробнее в конце статьи. В качестве приводов я решил взять самые малогабаритные сервы, которые только смог найти и переделать их под постоянное вращение.
Мой выбор объясняется тем, что взяв сервы я получаю мотор+редуктор+плату управления в корпусе порядка 15х20х8 мм. При всем желании я не смог найти мотор-редукторов таких габаритов.
В итоге выбор пал на суб-микро сервы , ценой 187 рублей за штуку:

Питание
Все элементы выбраны, осталось определиться как и чем питать систему. Очевидно, самым малогабаритным и подходящим источником является небольшой литий-полимерный аккумулятор. Так как приводы требуют 4.8В, повысим напряжение до 5В малогабаритным DC-DC конвертером от MAXIM Semiconductors. MAX8815 - великолепная микросхема в корпусе 3х3 мм, позволяющая отдать в нагрузку до 1А с 97% эффективностью (которая, разумеется, зависит от правильности разводки печатной платы, режима работы и выбора обвязки, как всегда).
Так как приводы даже в моменты пиковой нагрузки потребляют не более 600 мА вдвоем, этого более чем достаточно.

Чтобы запитать остальную электронику и уберечь ее от помех, вносимых двигателями, после DC-DC буст-конвертера поставим малогабаритный линейный регулятор от TI, LP2985 , c фиксированным 3.3В выходом.

Схемотехника и немного конструкции

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

Чтобы приводы не съезжали, между платой и их поверхностью я положил замечательный материал - латекс от эспандера Torres

Дело в том, что когда-то я купил в Китае рогатку. Сама рогатина была очень удобная, из титанового сплава, но вот резина там была ни к черту. В интернете специалисты по рогаткам советовали сразу ее выкинуть, купить себе этот самый эспандер, и вырезать из него жгуты на замену. Результат превзошел все мои ожидания и рогатка стала невероятно мощной. А т.к. эспандер - штука большая, то бо льшая часть материала осталась нетронута и лежала в ящике, дожидаясь своего часа.
После использования этого латекса в качестве прокладки между приводами и платой, приводы встали как влитые, не сдвигаясь ни на миллиметр.

Соответственно, для реализации такой конструкции необходимо две платы, у которых все компоненты сосредоточены на внешних сторонах.
Раз у нас такое внезапное увеличение полезной площади, на нижней плате можно разместить зарядное устройство для аккумулятора, разъем мини-USB, светодиоды индицирующие зарядку, а, заодно, вынести туда BT-модуль, чтобы его не накрывал аккум и не мешал связи.
Таким образом, были разработаны две печатные платы, TOP и BOTTOM. На нижней расположено то, о чем я уже сказал, а на верхней располагается весь «мозг» и, так сказать, пищеварительная система робота - микроконтроллер, акселерометр, конвертер и регулятор питания обвязкой и, конечно - пьезо-пищалка.

Схема верхней платы выглядит так:


Схема питания


Мозг

Чтобы USB не гнал свои пять вольт куда не надо, входы ON конвертера U1 и регулятора U2 соединены, подтянуты к питанию и выведены на контакт J1 на краю платы - подача туда уровня GND переведет входы и выходы конвертера в состояние высокого импеданса, по сути разорвав схему и позволив току USB течь туда, куда ему и положено - в схему зарядки аккумулятора. В остальном схема подключения конвертера типовая, из даташита.

Акселерометр U4 подключен к шине I2C контроллера без подтягивающих резисторов - да, они необходимы для работы шины, но в даташите уверяют, что both the lines are connected to Vdd_IO through a pull-up resistor embedded inside the LIS331DL . Как ни странно, больше никакой информации о них нет, номинала я так и не узнал (а в выключенном состоянии он не замеряется, видимо, они отключены от шины транзисторами). Так что пришлось слепо положиться на даташит. Надо сказать, в этом я не прогадал - акселерометр в самом деле отлично работает без дополнительных резисторов.
Однако, с ним был связан другой крупный фак-ап, о котором читайте в разделе «Тестирование и фак-апы».

Помимо акселерометра к контроллеру подключен светодиод D1, призванный визуально привлекать внимание кота и служить средством индикации а также делитель напряжения на резисторах R4 и R5, который подключен ко входу АЦП контроллера через сглаживающий конденсатор C5. Этот делитель приводит напряжение аккумулятора к диапазону, который способен измерить АЦП, давая возможность судить об уровне заряда батареи.
С этими резисторами, кстати, был связан мини-фак-ап. Дело в том, что я предполагал наличие в моем контроллере встроенного опорного напряжения (порядка 1.2 вольта), как в старших моделях. Но, как оказалось, в моделях в корпусе QFN36, встроенный источник отсутствует, а вход REF внутри корпуса замкнут на напряжение питания (3.3В), так что резисторы, которые при 4.2В аккуму давали 1В на выходе пришлось менять на те, что дают 3В.

Пищалка LS1, благодаря свое пьезо сущности может быть подключена напрямую к пину контроллера - ее потребление очень мало, на резонансной частоте ее импеданс составляет несколько сотен ом. Единственная потенциальная проблема состоит в том, что она может работать и в обратном направлении, то есть генерировать напряжение при деформации (ударах), для чего обычно ставят защитные диоды или резисторы. Однако, по результатам эксперимента, напряжение при ударе средней силы не превышало 1.5В, с чем вполне могут справиться и защитные диоды выхода контроллера, так что я рискнул не поставить дополнительной защиты.

Выходы со встроенного ШИМ-генератора контроллера выведены на контакты J8 и J9 для управления приводами. В качестве дополнительной (и, как выяснилось, не лишней) меры по снижению потребления в неактивном режиме, контакты J11 и J12, к которым подключается GND приводов, отрезаны от земли схемы силовым транзистором Q1 - подача высокого уровня на затвор дарует приводам силу земли и позволяет току течь через их внутренности. Как выяснилось, даже при нулевом ШИМ-сигнале, управляющая схема приводов все равно подает на них какое-то напряжение и потребление возрастает на 10 мА по сравнению с полностью отключенными.

Важным моментом оказался выбор отладочного интерфейса. В условиях сильно ограниченных габаритов, разумеется, хотелось обойтись минимальным количеством проводов. Но информация о том, какое же количество минимально оказалась весьма противоречива. После вдумчивого гугления и экспериментов я остановился на интерфейсе SWD, выведя только пины SWDIO и SWCLK. С этим связан еще один фак-ап, описанный в разделе «тестирование и фак-апы». Но если коротко - да, этих двух пинов в самом деле хватает для отладки в большинстве случаев .

Нижняя плата устроена совсем элементарно:


Нижняя плата

На ней размещены две включенные в параллель линейные микросхемы зарядки Li-Pol(Li-Ion) аккумуляторов, LTC4054 от Linear Technology. Это самый простой способ зарядить одноячейные литий-полимеры и литий-ионы, известный мне, если не страшен довольно низкий КПД (который обусловлен тем, что микросхемы линейные).
Они превосходно встают в параллель, в некоторых китайских схемах видел аж четыре аналогичные микрухи параллельно, обеспечивающие большой ток заряда. В отдельности каждая может дать до 800 мА, но это только в том случае, если вы хотите пожарить на них яичницу. При нагрузке выше 500 мА и полностью разряженном аккуме, микросхема начинает греться так, что невозможно держать палец. Т.к. в нее встроена схема защиты по температуре, это, в принципе, не страшно - она автоматом сбросит ток нагрузки, когда разогреется до 120 градусов. Но все же это не очень приятно, поэтому я предпочел поставить две штуки, благо место позволяло. Ток заряда задается резисторами R4 и R5, подобранными мной так, чтобы он составлял порядка 500 мА на двоих (то есть по 250 мА на каждую), при котором они не так греются.

Кроме этого на плате расположен разъем мини-USB (J2), транзистор Q1, подтягивающий вход ON схемы питания на верхней плате к земле, при подключении USB и модуль связи Bluetooth.

Платы я заказывал в «Резоните», вышло вполне бюджетно - я заплатил меньше 2000р за панель из шести различных плат, на которой были и две платы от кошкобота.
Верхняя и нижняя платы имеют размеры 32х26 мм. После сборки (и до фикса фак-апов) верхняя плата выглядит так:

А нижняя вот так:

Пришло время написать тестовую прошивку!

Тестовая прошивка

Итоговую прошивку я планирую сделать на базе FreeRTOS (чтобы не тратить время на реализацию нормальной многозадачности, блокирующих очередей и прочего), но для теста я набросал небольшую прошивку, инициализирующую всю периферию и позволяющую управлять ею простыми командами с компьютера. Пройдемся по инициализациям:

Тактирование и GPIO

Код

void InitRCC() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); } void InitGPIO() { GPIO_InitTypeDef GPIO_InitStructure; //LED GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOB, &GPIO_InitStructure); //ADC GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOA, &GPIO_InitStructure); //Buzzer GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET); //Servo GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure); //Servo On/Off GPIO_WriteBit(GPIOA, GPIO_Pin_5, Bit_RESET); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_Init(GPIOA, &GPIO_InitStructure); //Accel GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(GPIOB, &GPIO_InitStructure); //UART & BT Control GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure); }


Здесь все просто - подаем такт на всю нужную нам периферию, то есть на порты ввода-вывода, АЦП, UART, пару таймеров (один для пищалки, второй для ШИМа приводов) и на I2C. Потом - настраиваем все GPIO.
Пищалка

Код

void InitBuzzer() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseStructure.TIM_Period = 4; TIM_TimeBaseStructure.TIM_Prescaler = 1800; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM_Cmd(TIM2, ENABLE); }


Настройка сводится к инициализации таймера, выход которого подключен к пищалке. Настраиваем ШИМ, но, по сути, именно ширину импульса менять не будем, выставив ее всегда на 50%. Вместо этого будем менять делитель, заставляя таймер поменять частоту импульсов, чтобы пищать другим тоном.
Так как системная частота составляет 36 МГц, выставим период 4 (все равно нам не нужно много разрядом ШИМа), а предделитель 1800, получив частоту 4КГц.
Приводы

Код

void InitServo() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseStructure.TIM_Period = 0xFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0xB0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM3, ENABLE); TIM_Cmd(TIM3, ENABLE); }


Делаем то же, что и с пищалкой, но уже затачиваем на вывод ШИМа с нужными приводам параметрами, а именно - частота около 50 Гц, и достаточно большое число разрядов, чтобы управлять скоростью с большой точностью. Таким образом, предделитель задаем равным 176, а период - 4096, что дает нам примерно 50 Гц и 12 разрядов ШИМа.
Акселерометр и Bluetooth

Код

void InitAccel() { I2C_InitTypeDef I2C_InitStructure; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 200000; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); } void InitBT() { USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }


Тут все просто - для акселерометра просто включаем I2C на скорость 200КГц (хотя можно и больше и меньше, аксель позволяет), а Bluetooth для нас обычный UART, который мы включаем на стандартные 9600 и заодно настраиваем интеррапт приема, в котором будем обрабатывать команды.

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

Код получения команд

Код

#define OPCODE 0 #define LENGTH 1 #define PAYLOAD 2 enum CommandStates {CS_DONE, CS_RECEIVING, CS_EXECUTING}; enum CommandCodes {CC_TEST=0x01, CC_SERVO_STATE, CC_SET_SERVO1_DS, CC_SET_SERVO2_DS, CC_GET_ACCEL_REG, CC_SET_ACCEL_REG, CC_GET_BATTERY, CC_LED_STATE, CC_BUZZER, CC_INVALID}; enum ErrorCodes {EC_NONE, EC_INVALID_CMD, EC_MAX_LEN_EXCEEDED}; enum ReplyCodes {RC_NONE, RC_EXECUTED, RC_TEST, RC_ACCELREG, RC_ERROR}; typedef struct { unsigned char Command; unsigned char State; unsigned char Length; unsigned char Payload; }CommandDescriptor; CommandDescriptor Cmd; void InitCmd(CommandDescriptor *Comm) { Comm->Command=0; Comm->Length=0; unsigned char i; for(i=0;iPayload[i]=0; Comm->State=CS_DONE; //Init state at the end, to prevent interrupt from interfering } void SetInvalidCmd(CommandDescriptor *Comm, unsigned char ErrorCode) { Comm->Command=CC_INVALID; Comm->Length=3; Comm->State=CS_EXECUTING; //Just send back error Comm->Payload=ErrorCode; } void USART1_IRQHandler(void) { char data; if ((USART1->SR & USART_FLAG_RXNE) != (u16)RESET) { data = USART_ReceiveData(USART1); switch(Cmd.State) { case CS_DONE: if(data>=CC_INVALID) { SetInvalidCmd(&Cmd, EC_INVALID_CMD); return; } Cmd.Command=data; Cmd.Length=0; Cmd.State=CS_RECEIVING; return; case CS_RECEIVING: if(Cmd.Length==0) { if(data>CMD_BUFFER_LEN) { SetInvalidCmd(&Cmd, EC_MAX_LEN_EXCEEDED); return; } Cmd.Length=data; BufPtr=0; return; } if(BufPtr=Cmd.Length-2) { Cmd.State=CS_EXECUTING; return; } case CS_EXECUTING: return; } } }


Для начала объявим структуру команды, которая будет состоять из, собственно, самой команды, состояния (выполнена, в процессе получения, в процессе обработки), длины пакета (включая уже перечисленные два поля) и полезной нагрузки, которая может составлять от 0 до 8 байт.
Опишем вспомогательную функцию для инициализации этой структуры и еще одну - для заполнения ее значениями Invalid Command.
Теперь опишем прерывание. Получив один байт по UART, посмотрим, что там происходит с текущей командой (той самой, единственной в «очереди») -
если ее статус говорит нам, что исполнение было завершено, то проверим, правильный ли мы получили опкод, если нет - сообщим об ошибке, если да - начнем получать новую команду, поставив ей состояние CS_RECEIVING .
Если же мы в процессе получения, контролируем длину того, что получаем - чтобы не превысила 10 байт (2 байта заголовка и пейлоад) и заявленную во втором байте заголовка длину. Если что-то не так - сообщаем об ошибке, иначе - говорим, что команда получена и перешла в состояние CS_EXECUTING . С этого момента мы игнорируем все, что нам придет, пока кто-нибудь не выставит этой команде состояние CS_DONE .
Если бы у нас была настоящая очередь, можно было бы кинуть полученную команду в нее и пока принимать следующие.

Вот, собственно, и все - основная функция прошивки просто инициализирует периферию, включает Bluetooth и ждет, пока у команды появится состояние CS_EXECUTING . После этого она обрабатывает команду (этот код приводить не буду, там просто большой switch по опкодам с занесением байт из пейлоада в регистры) и выставляет ей статус CS_DONE .

void main()

Код

int main(void) { InitCmd(&Cmd); InitHardware(); DisableServos(); EnableBT(); EnableLED(); while(1) { if(Cmd.State==CS_EXECUTING) { ProcessCmd(&Cmd); InitCmd(&Cmd); } } }

Модификация приводов под постоянное вращение и вопросы конструкции
Так как приводы изначально рассчитаны на поворот в пределах градусов 170, их нужно немножко проапгрейдить, чтобы использовать их как двигатели робота. Из-за их маленького размера это по началу может оказаться не очень просто.
В целом, все приводы построены одинаково, независимо от размера - у них есть мотор, у них есть редуктор, выходной вал которого сидит на одной оси с переменным резистором, с которого схема управления снимает информацию о текущем положении вала.


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

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


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


Безжалостно отрезаем провода от потенциометра, убираем их из сервы, чтобы не мешались. К тем контактным площадкам, к которым они шли, паяем два одинаковых маленьких СМД-резистора, суммарным сопротивлением порядка 5 КОм (если чуть больше или чуть меньше - не страшно), формируя постоянный делитель. Я припаял два по 2.4КОма.
Так как моторы будут лежать зеркально относительно друг-друга, у одного из них еще и меняем местами провода, идущие к мотору. Можно, конечно, это софтварно делать, но железно оно приятнее.

Все, теперь серва всегда будет считать, что его вал находится ровно посередине. И подав ШИМ-сигнал со значением скважности больше среднего, выходной вал начнет вращаться в одну сторону, а при меньшем - в другую. И чем сильнее отстоит поданное значение от среднего, тем быстрее вращается вал.

Тестирование и фак-апы


Заказчик тестирует прототип устройства

Так как видео и фото устройства я уже демонстрировал выше, данный раздел будет в основном содержать текстовое описание граблей, на которые я наступил. Некоторые из них произошли по моей вине, некоторые от меня не зависели.

Фак-ап с питанием
Самый первый фак-ап, повлекший за собой больше всего доработок в схеме. Связан с буст-конвертером. При первом запуске устройства (пока без приводов), я ничего не заметил, контроллер завелся и прошился. 5В присутствовали на выходе конвертера. Пришло время проверить приводы, вот тут-то и вылезли грабли. При подключении приводов конвертер моментально отрубался - срабатывала его встроенная защита, отключающая микросхему, в случае, если выходное напряжение упадет более чем на 10 процентов ниже заданного (5В). Отладка заняла у меня весьма продолжительное время, включая сидение за осциллографом, замену самой микросхемы конвертера на аналогичную, тестирование разных дросселей и т.п.
Что интересно, не помогали даже емкости, навешенные около приводов, поэтому я решил, что проблема в разводке платы либо в дросселе. Замеры показали, что конвертер перестает работать при нагрузке больше 90 мА, причем даже в случае чисто-резистивной нагрузки! При этом КПД был порядка 40 процентов, понятное дело, для импульсного конвертера это неприемлемо.

Причина оказалось невероятно банальной - похоже, что вместо выходного керамического конденсатора в 10 мкФ я по ошибке впаял такой же на 1 мкФ. При такой выходной емкости микросхема никак не могла выйти на режим, и навешенные на соплях большие конденсаторы ей в этом совсем не помогали.
Слегка зачистив плату от маски, я впаял по два 22 мкФ керамических конденсатора на выход конвертера, на его вход и прямо перед сервами.
Заодно поставил между выходом конвертера и сервами сглаживающий дроссель (точнее, ferrite bead), BLM41PG471SN1 , рассчитанный на 2А.
К тому же, как оказалось, место на плате позволяет впихнуть туда один танталовый конденсатор в корпусе «А», на 150 мкФ, прямо рядом с выходом конвертера.
На самом деле, для корректной работы хватило бы одного 22 мкФ конденсатора на выходе и одного на входе, но раз уж место позволяло, я решил перестраховаться.
Результат был просто великолепен, выходные 5В даже под нагрузкой были почти не зашумлены, а КПД конвертера, по моим замерам (я включил амперметры во входную и выходную цепь), достиг 93 процентов, что само по себе весьма хороший показатель.

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

Фак-ап с акселерометром
Геморройный фак-ап, опять из-за невнимательности. При тестировании периферии выяснилось, что акселерометр не отвечает. Т.к. он сидит на шине I2C, общение начинается (не считая стартового импульса) с передачи адреса устройства. После чего оно должно ответить импульсом подтверждения, если адрес совпал. Импульса не было.
Так как корпус акселерометра был самым мерзким для пайки (3х3 мм и на пузе микросхемы отсутствовала «земляная» площадка, из-за чего она отвратительно центрировалась), я решил, что проблема в пайке и очень много времени провел перепаивая его по несколько раз. Не помогло.
Потом я решил, что обещанные встроенные резисторы оказались-таки недостаточными, зачищал плату и впаивал свои. Не помогло.
Много раз проверял код и сверял адрес с даташитом. Не помогло.
В итоге каким то чудом подал адрес, отличающийся от заданного на единичку (в одном из разрядов бинарного представления адреса). Помогло.
Начал копать даташиты, потому что такого просто не могло быть - чтобы устройство отвечало на другой адрес. И выяснил великолепную вещь.
Оказывается, есть две модификации акселерометра: и .
Одинаковый корпус. Одинаковые даташиты. Одинаковая карта регистров. Прост второй может мерить не 2g/4g/8g, а первый - только 2g/4g.
И их адреса отличаются на единичку. Добрый гугл, когда я начинал вводить LIS133 автоматом подсказывал мне «LIS133DLH», разницы в даташитах я сходу не увидел, вот и долбил аксель чужим адресом.

Вывод из фак-апа: Проверять название элемента в даташите. Если оно отличается от ожидаемого хотя бы на одну букву - обязательно узнать, за что эта буква отвечает. Чаще всего буквы в конце не важны для разработки и относятся к типу поставки компонента, но бывает и как с этим акселерометром.

Фак-ап с Bluetooth-модулем
Ну этот фак-ап больше на совести китайцев. Оказывается, они выпускают несколько модификаций этого модуля, HC-04, HC-05, HC-06 - железом они не отличаются, отличаются прошивкой. При желании можно перешить один на другой.
Мне пришел HC-04 вместо HC-05, они отличаются тем, что у 04 прошивка попроще, и, если 05 переводится в режим команд подачей сигнала на один из его GPIO, и 05 может работать как мастером, так и слейвом, то 04 всегда работает только слейвом (либо только мастером, но я не видел в продаже таких модулей), изначально находится в режиме приема команд и перестает на них реагировать после установки связи с мастером.
Плюс ни один из этих модулей не поддерживает энергосберегающего режима сна.
Поэтому оказалось, что выведенный мной сигнал перевода модуля в режим команд бесполезен, а также - что модуль постоянно жрет от 20 до 40 мА пока ищет мастера.
Решением стало перекидывание бесполезного в данной ситуации сигнала управления на пин RESET модуля. Теперь при подаче туда низкого уровня модуль уходит в состояние RESET и перестает потреблять.

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

Фак-ап с отладочным интерфейсом
Не то чтобы фак-ап, но информация к размышлению. Да, для прошивки и отладки в самом деле хватает двух сигнальных пинов SWD - тактового и данных. Однако, шиться не будет вообще никак (ST-LINKом во всяком случае), если пин программатора VAPP не подключен непосредственно к питанию контроллера. Программатор им тестирует напряжение и вообще довольно трепетно к нему относится, у меня почему-то не шилось даже когда я замыкал его на программаторский же источник 3.3В. Это, впрочем, не так страшно - ну подпаялся к одному из сглаживающих кондеров.
Куда страшнее другое. Есть пин NRST , отвечающий, понятное дело, за резет контроллера. И в самом деле SWD может сбросить контроллер софтварно, так что в принципе, его можно не подключать. Но.
Грабли подкрались когда я тестировал режим сна. К сожалению, я не прочитал вот этих важных срок из рефмана СТМ32, раздел Debug support for low-power modes : The core does not allow FCLK or HCLK to be turned off during a debug session. As these are required for the debugger connection, during a debug, they must remain active.
Во время самого глубокого сна, режима Stand-By, тактирование отключается вместе с дебагом. А т.к. я для теста потребления просто вписал в мэин вход в стенд-бай, то я получил в итоге не шьющийся контроллер.
Связь между резетом и вот этим фактом простая - программатор умеет шить из-под резета, когда стенд-бай еще не активировался (а активируется он сразу же при включении при моей прошивке), только для этого он должен суметь перезагрузить контроллер, чего без пина NRST он сделать не мог.
Спасла меня, как ни странно, стандартная утилита от СТ, в которой был великолепный авто-режим, в котором программатор постоянно пытается обнаружить программируемый контроллер. Включив этот режим я начал проводком с GND, подпаянным к иголке, пытаться тыкнуть в еле выступающую из-под контроллера площадку резета. Удалось, программатор успел подхватить контроллер, до того как он опять заснул вечным сном и стереть прошивку.

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

Фак-ап с приводами
Самый печальный фак-ап, и он не на моей совести. Приводы, простите, говно. Они рассчитаны исключительно на свой серво-режим, причем так, чтоб проводить бо льшую часть времени в статичном положении. При нагрузке греются нещадно. Более того, греются даже если к ним ничего не приделано, просто крутится вал. Поэтому в режиме постоянного вращения они работать не могут - после двух минут, даже при пониженных скоростях и отличной смазке внутри (ничего не заедает, ход плавный) они начинают натурально плавиться.

Плавится корпус, и, что хуже всего - шестерни, особенно выходная. После этого привод клинит и помогает только замена. Так что кошкобот в том виде, в котором он представлен на фото и видео может работать только 1-2 минуты с перерывами. Посему пришлось его разобрать и заменить приводы на более здоровые, более медленные и более жрущие MG90, с металлическими шестернями, которые способны неспешно крутиться бесконечно долго.
Так что теперь он не влезает в шарик (даже в большой, не говоря уж о малом) и весьма медленно ездит.
Коту, правда, по-прежнему интересен.

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

Общие выводы по работе: В целом - опыт полезный. И коту нравится даже несмотря на новые приводы, с которыми кошкобот стал больше и медленнее. Особенно, когда он пищит)
Собирающим подобную вещь могу сказать еще вот что - датчик поворота (аксель к нему не относится) - вещь обязательная, потому никакой калибровкой и постоянными значениями нельзя добиться одинаковой скорости двух разных приводов и колес на них. Поэтому робот будет ехать по окружности. При хорошей калибровке - по очень большой окружности, так что это будет заметно только при поездке от стены до стены. При плохой - будет заметно раньше. Так что в следующую версию я планирую поставить более хитрый датчик. Ну и более подходящие приводы, конечно.
Еще есть мысль попробовать организовать охлаждение моторчиков в мелких приводах, вместе с пониженными оборотами этого вполне может хватить для корректной работы (ведь сейчас теплоотвод от них отвратительный). Если получится - ждите следующей статье, о кошкоботе v1.5, с охлаждаемыми приводами и на FreeRTOS!

На этом у меня все, собирайте роботов и развлекайте своих котэ!

Решил плавно перейти к динамичным движущимся моделям. Это проект маленького самодельного робота на ИК-управлении, собранного из простых и доступных для приобретения деталей. В основе - два микроконтроллера. Передачу с пульта ДУ обеспечивает PIC12F675 , а приёмная часть к контроллером моторчиков реализована на PIC12F629 .

Схема робота на микроконтроллере

С цифровой частью всё вышло гладко, проблема была только в "двигательной установке" - маленьких редукторах, которые сделать в домашних условиях очень проблематично, поэтому пришлось развить идею "виброжуков ". Управление микромоторами осуществляется через усилительные транзисторные ключи на BC337. Они заменимы на любые другие небольшие транзисторы n-p-n с током коллектора от 0,5 А.

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

Обсудить статью МАЛЕНЬКИЙ САМОДЕЛЬНЫЙ РОБОТ

Лучшие статьи по теме