Простой робот
Материал из LicrymWiki
За основу взяты статьи «шаг за шагом» с myrobot.ru, проект conqeror [1] с Железного феникса, но немного переработаны под имеющиеся реалии.
Строить робота с нуля мы не будем, так как это довольно сложно и хлопотно, и потребует слесарных навыков. Мы сделаем проще, мы возьмем готовую китайскую радиоуправляемую машинку, и сдерем с нее всё лишнее, оставив только шасси, а управлять шасси будет созданный нами электронный блок с микроконтроллером и драйвером.
Итак, Прогулявшись в ашан были закуплены:
Машинка радиоуправляемая китайская. 289р.
Аккумуляторы «космос» 1,5 А*ч 4 шт. по 87 руб за пару. Настоятельно рекомендую купить аккумуляторы, так как батареек надолго хватать не будет.
[править] Аппаратная часть
Снимем с машинки пластмассовый кузов, он всё равно не играет никакой роли:
Задние колеса крутятся мотором через редуктор. Передние поворачиваются на небольшой угол электромотором. Система такая: когда подаем напряжение на мотор руля, то мотор через шестеренку смещает тягу, которая поворачивает колеса. Как только тяга сместилась на максимум, вал мотора не может вращаться дальше, потому остается неподвижен. Как только напряжение с мотора снимаем – пружина поворачивает колеса в нейтральное положение. Отсюда вытекает важная особенность. Если мы хотим увеличить мощность машинки, то мы можем подать большую мощность на задний двигатель, но подавать большую мощность на передний нельзя, так как мотор, находясь по сути в заклиненном состоянии будет сильно греться, что может привести к его разрушению. Поэтому, если мы будем форсировать машинку, нужно будет принять меры к ограничению протекающего через передний двигатель тока.
Заберемся поглубже. Снимем крышку и извлечем радиомодуль. Отложим его, когда-нибудь для чего-нибудь он понадобится. Включать в схему робота я его не стал. Радиомодуль собран на микросхеме «RX-2 -G» Именно с пробелом после 2. Даташит найти не удалось, почему можно предположить, что эта микросхема сделана под заказ конкретно для этого производителя игрушек.
Итак, с механикой разобрались, приступим к электронике. На куске макетной платы соберем схему. В качестве микроконтроллера воспользуемся ATMEGA8, в качестве микросхемы драйвера L293DNE. За основу взята схема с myrobot.ru:
Что мы изменим. Во-первых, добавим светодиод. Он нам будет нужен для диагностики и отладки программ. По-разному мигая светодиодом, можно сообщить много информации, например какая функция выполняется в данный момент. Во вторых, подключим драйвер не к порту С а к порту В, так как на порте С находятся аналогово-цифровые преобразователи, которые нам понадобятся в будущем. На порту В находятся 2 внешних прерывания, поэтому желательно бы еще и их оставить свободными, но в данном случае я их пока не использовал и занял ножки.
Модифицированная схема:
Линии питания, кварцевый резонатор и колодка программатора не показана. Вход питания аналогово-цифрового преобразователя AVCC подключен к питанию, сейчас это не нужно, но делаем заранее, так как в следующем проекте (ИК бампер) он нам понадобится.
Аккуратно соберем схему на макетной плате. На фото шасси, старый радиомодуль и собранная нами плата:
Небольшое примечание. Обратите внимание, что провода моторов, питания не подпаиваются напрямую к плате, а подпаиваются к специально сделанным штырькам. Это позволяет во первых упростить процедуру установки платы, а во вторых предохранить пятачки платы от отслаивания – они не любят частой перепайки.
Установим ее на шасси:
Полдела готово, осталось программное обеспечение.
[править] Программная часть
Начнем с того, что нам нужно запрограммировать fuse биты микроконтроллера.
FUSE биты в микроконтроллере – что то вроде перемычек, которые задают глобальные настройки самого микроконтроллера. Например, какой источник тактового сигнала использовать, отключить ли вход reset, защитить ли содержимое микроконтроллера от чтения программатором и т.д. Подробнее можно прочитать в даташите.
Изначально, сделанные на заводе микроконтроллеры запрограммированы использовать в качестве тактового сигнала внутренний RC генератор. Он хорош тем, что не нуждается вообще ни в каких внешних элементах, но проблема в том, что у него низкая стабильность и частота около 1 МГц. Мы же хотим использовать кварцевый резонатор, поэтому нам нужно переключить фьюзы на использование кварцевого резонатора. Для этого запустим PonyProg, выберем Command – Security and Configuration Bits… и выставим их также как и на картинке (Внимание, актуально только для mega 8, у других моделей микроконтроллеров другая комбинация, указана в даташите)
Внимание, грабли У фьюзов всё шиворот на выворот. Не запрограммированным считается 1, запрограммированным считается 0, поэтому там, где нет галочки – это 1, где галочка есть это 0.
После того как мы запрограммировали фьюзы – микроконтроллер начал работать с кварцем, и его тактовая частота равна частоте кварца. В моей схеме это 16 МГц, так как микроконтроллер MEGA8-16PU. Можно брать кварц на меньшую частоту, на большую - нельзя.
За основу была взята программа их проекта conqeror с сайта «Железный Феникс», но была доработана, так как шасси отличается. Также была переписана функция проверки по таблице вероятностей. Робот будет ездить в случайном порядке, причем вероятность перехода из одного действия в другое задается таблицей вероятностей, тем самым можно например предотвратить бессмысленное дерганье вперед-назад.
Программа:
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7 beta 5 Professional
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 17.02.2008
Author : Spiritus Sancti
Company : Licrym.org
Comments:
Chip type : ATmega8
Program type : Application
Clock frequency : 16,000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
#include <stdlib.h>
unsigned int gtime;
unsigned char d[7][7]={ /*таблица вероятностей переходов,
строки - текущее движение, столбцы - следующее.*/
// STO F FR FL B BR BL
/*STO*/ {1, 18, 18, 18, 18, 17, 13},
/*F */ {7, 26, 21, 21, 10, 8, 7},
/*FR */ {7, 23, 23, 27, 8, 6, 6},
/*FL */ {7, 23, 7, 43, 8, 6, 6},
/*B */ { 4, 10, 10, 5, 28, 22, 21},
/*BR */ { 6, 13, 9, 8, 35, 22, 7},
/*BL */ {16, 8, 6, 6, 35, 8, 21}
};
unsigned char now, h;
int gTimeOfMove = 1000; //время элементарного хода в мсек
interrupt [TIM1_COMPA] void timer1_compa_isr(void) //прерывание раз в 1/1041 сек (1041,666 Гц)
{
if (gtime!=0)--gtime;
}
void delay (unsigned int time){ //на вход задержка милисекундах, макс 65535
gtime=time;
while(gtime!=0){};
}
//далее функции управления двигателями
void f(int t){ // Вперед
PORTD.1=0;
PORTD.2=1;
PORTD.3=0;
PORTD.4=0;
if(t!=0) delay(t);
}
void b(int t){ // назад
PORTD.1=1;
PORTD.2=0;
PORTD.3=0;
PORTD.4=0;
if(t!=0) delay(t);
}
void fl(int t){ // вперед налево
PORTD.1=0;
PORTD.2=1;
PORTD.3=0;
PORTD.4=1;
if(t!=0) delay(t);
}
void fr(int t){ // вперед направо
PORTD.1=0;
PORTD.2=1;
PORTD.3=1;
PORTD.4=0;
if(t!=0) delay(t);
}
void bl(int t){ // назад налево
PORTD.1=1;
PORTD.2=0;
PORTD.3=0;
PORTD.4=1;
if(t!=0) delay(t);
}
void br(int t){ // назад направо
PORTD.1=1;
PORTD.2=0;
PORTD.3=1;
PORTD.4=0;
if(t!=0) delay(t);
}
void stop(int t){ //стоп
PORTD.1=0;
PORTD.2=0;
PORTD.3=0;
PORTD.4=0;
if(t!=0) delay(t);
}
void led_on(void){ //Включить светодиод
PORTD.0=1;}
void led_off(void){ //Выключить светодиод
PORTD.0=0;}
void go(unsigned char napr){ //Выборка направления и отдача команды двигателям
switch(napr){
case 1:
stop(gTimeOfMove);
break;
case 2:
f(gTimeOfMove);
break;
case 3:
fr(gTimeOfMove);
break;
case 4:
fl(gTimeOfMove);
break;
case 5:
b(gTimeOfMove);
break;
case 6:
br(gTimeOfMove);
break;
case 7:
bl(gTimeOfMove);
break;
};
}
unsigned char next_move(void){ //выясняем следующий ход
int a, b, c;
a = rand()/327; //0..99 число
c=0;
for (b=1; b<=7; b++){ //поик по таблице
if(a > c && a < (d[now][b]+c) ) break;
c=c+d[now][b];
};
if (b==8)b=1; /*если b будет 8 то контроллер зависает,
нужно искать ошибку в алгоритме, пока просто закроем эту дыру */
now = b;
return b;
};
void start(void){ //начинаем движение. пока без датчиков
while(1){
h=next_move();
go(h);
led_on();
delay(100);
led_off();
}
};
void main(void)
{ int i;
//Инициализация портов
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x7F;
PORTD=0x00;
DDRD=0xFF;
TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x0D;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00; //коэфф деления таймера
OCR1AL=0x0F; //
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
now=1;
for (i=0;i<=5;i++) { /*Помигаем светодиодом после включения,
заодно задержка перед троганием что бы успеть отбежать*/
led_on();
delay(500);
led_off();
delay(500);
};
start();
};
}
Программа неплохо откомментирована, поэтому рабочий алгоритм не разбираем.
Так как у робота пока нет датчиков, мы строим его программу таким образом, что бы при въезжании в препятствие он рано или поздно всё таки дал задний ход с поворотом. Это достигается подбором коэффициентов в таблице.
Прошьем полученную программу в микроконтроллер и наблюдаем за ездой нашего первого робота.
Что можно сделать в дальнейшем. Некоторое пришлось сделать в реальности.
1) Оказалось что задний двигатель кушает почти 1.5 А при трогании с места, при том что драйвер рассчитан всего на 600 мА. В результате на 4 MOSFET был сделан Н мост.
2) Был добавлен еще один отсек с батарейками, общее количество пальчиковых аккумуляторов было увеличено с 3 до 4
3) Питание микроконтроллера и логических цепей было сделано через микросхему-стабилизатор, что бы иметь возможность форсировать двигатели просто повышая напряжением питания.
4) Можно выводы ENABLE драйвера завести на ножку микроконтроллера и подавать на них ШИМ сигнал, тем самым получив возможность варьировать мощность двигателя от 0 до 100%, что даст возможность, например плавного трогания или торможения.
5) Естественно следующим шагом стоит оснастить робота какими либо органами чувств, будь то контактные или бесконтактные датчики препятствий.
6) Можно добавить роботу модуль связи с компьютером, например по Bluetooth, и через этот модуль управлять роботом, а также получать с него сведения о текущем положении дел.
Это первое что пришло в голову. Нет предела совершенству, поэтому робота можно развивать дальше и дальше.
[править] Ссылки
http://www.ironfelix.ru/modules.php?name=Pages&pa=showpage&pid=117
http://roboforum.ru Хороший сайт роботостроителей, на форуме всегда можно получить компетентный ответ.
Ключевые слова: как сделать робота, простой робот, самодельный робот, робот из машинки.










