Этот микропроект начался с того, что я заказал в одном известном магазине гусеничное шасси. Мне давно хотелось примерять на своих роботов что-то подобное, ведь до этого я орудовал только колесными платформами. К тому же, хотелось продемонстрировать нашим ученикам еще один вид шасси, которое бы они могли использовать в своих проектах.
Нужно сказать, изначально я хотел купить другой набор — Tamiya 70100. Ведь у меня уже есть мотор-редукторы от Tamiya, которые мы используем для учебного робота МР1. Указанные двигатели отлично интегрируются с этим набором. на рисунке слева как изображена такая компоновка.
Но волею судеб, Tamiya 70100 не оказалось в наличии, а ждать посылок из далеких стран мне никак не хотелось. Именно поэтому я решил попробовать Pololu 30T. Внимательно на посмотрев на 30T, я понял что этот вариант в чем-то даже лучше первоначального — с виду гусеницы выглядят боле прочными, и имеют меньше элементов. Но у Tamiya есть и явный плюс — они имеют классическую конструкцию с опорными катками, что делает их более проходимыми.
Комплектация Pololu 30T включает
- две резиновые литые гусеницы;
- два ведущих колеса;
- два ленивца (ведомые колеса);
- два вала для ведомых колес, которые по сути являются просто болтами М3 с неполной резьбой;
- четыре гайки М3 и две шайбы.
Ведущие колеса могут использоваться совместно с энкодерами, для чего они снабжены специальными выступами по бокам. Отверстие в колесах рассчитано под родные двигатели от pololu. У меня как раз было два таких мотора с отношением 298:1 и приставкой HP, что означает High Power — с повышенной тягой.
Платформа
После того как гусеницы наконец пришли, встал вопрос о том куда же их приделать?:) Был и другой вопрос, как их приделать? Немного погрустив о том что у меня нет 3D принтера, а фрезер расчехлять вообще никак не хочется, я решил слепить платформу для гусениц из того, что попадется под руку.
В качестве основы платформы решено было использовать карбоновый лист, которых у меня вагон кусок ламината. К вырезанной из ламината пластине со стороны ведущих колес были прижаты мотор-редукторы. Прижаты они были с помощью кусочков пластика. С другой стороны, из этого же ламината были изготовлены хитрые крепления для валов ведомых колес.
Сверху я закрепил две маленькие макетные платы: одну над другой. Рядом с ними, большая часть пластины была оставлена под аккумуляторную батарею из 6 АА элементов, для крепления которой я установил две 40мм стойки.
Управление
Платформа готова. Теперь нужно было её оживить, и задать роботу какое-то простое поведение для демонстрации работы гусениц. В качестве микроконтроллера я выбрал MSP430, который был приобретен мной еще в прошлом году в составе комплекта LaunchPad. По сути, MSP430 — это аналог Atmega168.
На верхнюю палубу был установлен драйвер двигателей Pololu TB6612FNG и датчик препятствия Sharp GP2Y0D810Z0F.
Для питания всего этого добра подошел мощный регулятор Pololu D15V35F5S3, который может работать в двух режимах: 5В и 3.3В. Поскольку для MSP нужно как раз 3.3В, и большее напряжение он не выдержит, то регулятор был установлен именно в этот режим. Двигатели же рассчитаны на напряжением 6В, и поэтому будут работать не в полную силу при такой схеме питания.
Собрав все воедино, получился такой робот. Немного похож на трактор 🙂
Использование MSP430 вне LaunchPad
TI LaunchPad устроен также как и Arduino Uno — чип можно достать из программатора и использовать его отдельно. Именно такой вариант я и хотел попробовать в данном проекте. Вот тут-то меня и ждали грабли.
Написав черновик кода управляющей программы, я запустил её на LaunchPad, не доставая чип. Выходы на драйвер двигателей были соединены со светодиодами, чтобы убедиться что контроллер правильно реагирует на сигналы датчика препятствия. В общем, программа работала как надо.
На следующем этапе я вытащил чип MSP430 из LaunchPad и обвязал его на макетной плате робота согласно первой попавшейся схеме из гугла. Схема была такая:
- Vcc к питанию;
- Gnd на землю;
- RST через резистор 47 кОм к питанию.
Подсоединил драйвер двигателей и датчик препятствия. Наконец, подключил схему к питанию и… и понял что она ни черта не работает 🙁 Причем, укоротив код программы до простого мигания светодиодам, система стала запускаться, что сильно меня смутило. Вроде как, с одной стороны, проблема была аппаратная — ведь на LaunchPad все работало. С другой стороны — то что контроллер всё-таки запускался с простым кодом, говорило о программных корнях проблемы.
Потеряв кучу времени на отладку, я таки нашел причину этой аномалии. Всему виной была линия RST. Оказывается, нужно было добавить керамический конденсатор между RST и землей! Вот как это должно выглядеть:
Программа
Как я уже говорил, робот был снабжен примитивным поведением. Смысл его жизни состоит в обнаружении препятствий и маневрировании, с целью их обойти. Программа была составлена в IDE Energia.
int m1FPin = 2;
int m1BPin = 3;
int m2FPin = 5;
int m2BPin = 6;
int m1PWM = 9;
int m2PWM = 10;
int sensPin = 11;
int ledPin = 12;
int buzzPin = 13;
int sens_raw;
const byte DIR_FORWARD = 0;
const byte DIR_BACKWARD = 1;
const byte DIR_LEFT = 2;
const byte DIR_RIGHT = 3;
const byte DIR_STOP = 4;
void blink( byte iter, int time ){
for( byte i=0; i<iter; i++ ){
digitalWrite( ledPin, HIGH );
digitalWrite( buzzPin, HIGH );
delay(time);
digitalWrite( ledPin, LOW );
digitalWrite( buzzPin, LOW );
delay(time);
}
}
void initMotors(){
pinMode(m1PWM, OUTPUT);
pinMode(m2PWM, OUTPUT);
pinMode(m1FPin, OUTPUT);
pinMode(m1BPin, OUTPUT);
pinMode(m2FPin, OUTPUT);
pinMode(m2BPin, OUTPUT);
analogWrite( m1PWM, 255 );
analogWrite( m2PWM, 255 );
walkDir( DIR_FORWARD );
}
void walkDir( byte dir ){
if( dir==DIR_FORWARD ){
digitalWrite( m1FPin, LOW );
digitalWrite( m1BPin, HIGH );
digitalWrite( m2FPin, LOW );
digitalWrite( m2BPin, HIGH );
}
else if( dir==DIR_LEFT ){
digitalWrite( m1FPin, HIGH );
digitalWrite( m1BPin, LOW );
digitalWrite( m2FPin, LOW );
digitalWrite( m2BPin, HIGH );
}
else if( dir==DIR_STOP ){
digitalWrite( m1FPin, LOW );
digitalWrite( m1BPin, LOW );
digitalWrite( m2FPin, LOW );
digitalWrite( m2BPin, LOW );
}
}
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buzzPin, OUTPUT);
blink(5,50);
initMotors();
}
void loop() {
sens_raw = digitalRead( sensPin );
if( sens_raw )
walkDir( DIR_FORWARD );
else {
walkDir( DIR_LEFT );
blink(1,50);
}
}
А теперь, действие! Для демонстрации высокой проходимости робота я построил небольшой маршрут с препятствиями.
Примечание. Статья была написана в 2013 и перенесена с моего сайта poprobot.ru. Некоторые компоненты с тех пор, вероятно, устарели.