В этом посте я хотел бы рассказать о своем опыте создания робота(мобильной платформы способной выполнять заложенную в него программу).
Начнем
Голова
В качестве управляющего центра робота была выбрана Arduino Uno. Почему? Только потому, что это уже готовая плата с выведенными пинами и удобной прошивкой контроллера. Саму программу под микроконтроллер atmega328p я писал в AtmelStudio на Си с использованием библиотек производителя.

Моторы
Для управления колесами мобильной платформы мне потребовался драйвер двигателя. Я остановился на Pololu TB6612FNG Dual Motor Driver Carrier(этом), потому что он компактен, легко устанавливается на макетную плату, удовлетворяет все мои потребности.

Два комплекта мотор-колесо-энкодер были приобретены там же. В нем кстати говоря очень интересно работает энкодер.

Питание
В качестве источника питания используется Li-ion аккумулятор, подключенный через преобразователь, кстати говоря той же фирмы.

Ну и датчики
Помимо двух энкодеров о которых говорилось выше, на роботе установлен ультразвуковой дальномер hc-sr04. Как он работает я считаю тут рассказывать смысла нет.
Ну вот, думаю я описал основные элементы робота. Я не стал детально описывать все в деталях, потому что пост получился бы достаточно объемным, а тот кому это действительно интересно может написать мне на почту.
Напишем программу
Изначальной задачей, стоявшей передо мной написать программу по выходу из простенького лабиринта. Для того что бы реализовать эту задачу мне понадобилось использовать такой встроенный функционал контроллера:
- ШИМ — для регуляции скорости моторов
- Внешние прерывания — для получения информации о препятствиях от датчика(hc-sr04)
- 16 битный таймер — для измерения длинны импульса с Echo порта дальномера
- Ну и управление портами ввода-вывода — здесь объяснять я думаю не стоит
Из программных функций мне потребовались лишь задержки и переменные. Много? Нет! Все просто!
Вот собственно код, который получился в итоге:
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define motor1_0 0 #define motor1_1 1 #define motor2_0 4 #define motor2_1 7 //#define F_CPU 16000000L void work_func(); int getDist(); volatile int readTrue = 0; volatile unsigned int d = 0; int main() { DDRD = 255; //Настройка ШИМ для управления скоростью двигателей TCCR0A = (0<<COM0A0)|(1<<COM0A1)|(0<<COM0B0)|(1<<COM0B1)|(1<<WGM01)|(1<<WGM00); TCCR0B = (1<<FOC0A)|(1<<FOC0B)|(0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02); OCR0A = 255; //2 двигатель OCR0B = 248; //1 двигатель // Прерывания DDRD &= ~(1 << DDD2); PORTD |= (1 << PORTD2); EICRA = (0 << ISC01) | (1 << ISC00); // set INT0 to trigger on ANY logic change EIMSK |= (1 << INT0); // Turns on INT0 cli(); //Возможно не нужно //Настройка TRIG DDRD |= (1 << PORTD3); // Настройка LED DDRB = 0b11111111; while(1) { work_func(); } } void work_func() { if(getDist() <= 10) { //Если препятствие ближе чем 8 см, то поврот на 90 град врпаво PORTB |= (1 << PORTB5); PORTD &= ~((1 << motor1_0) | (1 << motor2_0)); PORTD |= (1 << motor1_0) | (1 << motor2_1); _delay_ms(250); PORTD &= ~((1 << motor1_0) | (1 << motor2_1)); if(getDist() <= 10) { //Если препятствие ближе чем 10 см, то поврот на 180 град влево PORTD |= (1 << motor1_1) | (1 << motor2_0); _delay_ms(515); PORTD &= ~((1 << motor1_1) | (1 << motor2_0)); if(getDist() <= 10) { //Если препятствие ближе чем 10 см, то поврот на 90 град влево PORTD |= (1 << motor1_1) | (1 << motor2_0); _delay_ms(250); PORTD &= ~((1 << motor1_1) | (1 << motor2_0)); } } } else { // Если препятсвия нет, то едем вперед. PORTB &= ~(1 << PORTB5); PORTD |= (1 << motor1_0) | (1 << motor2_0); } //PORTB &= ~(1 << PORTB2); _delay_ms(120); } int getDist() { PORTD |= (1 << PORTD3); _delay_us(10); PORTD &= ~(1 << PORTD3); sei(); while(readTrue == 0); cli(); readTrue = 0; short int cm =(short) d/2/58; // return cm; } ISR (INT0_vect) // Обработчик прерывания (используется для получения данных с датчика) { if((PIND & 4) != 0) { TCCR1B = 2; } else { d = TCNT1; TCCR1B = 0; TCNT1 = 0; readTrue = 1; } }
Таким образом робот едет вперед пока не увидит препятствие. Как только он увидит препятствие находящееся ближе 10 см., он поворачивается вправо на 90 градусов. Далее если после поворота препятствия не обнаружено, то он едет вперед до следующего препятствия, а если там тоже препятствие то робот делает разворот на 180 градусов влево и опять проверяет есть там препятствие или нет. Если и там препятствие то робот поворачивается еще на 90 градусов влево(назад от начального направления) и едет назад.
Заключение
С помощью данного поста я хотел поделится опытом и показать, что это не такая сложная задача. Тем более, что я для написания программы пользовался AtmelStudio. Если же использовать Arduino Sketch то количество кода и сложность программы сократятся в разы.
P.S. Это мой первый пост, поэтому прошу сильно не пинать и если где-то найдете ошибки/опечатки писать лично.
ссылка на оригинал статьи http://habrahabr.ru/post/211919/

Добавить комментарий