Как стать автором
Обновить

Робот-черепашка на АТMega8

Время на прочтение3 мин
Количество просмотров4.4K
Рассказывали тут про свои «робо-поделки» и я тоже решил поделиться своей.
Вдохновился я роботом Polulu 3pi. Но решил сделать своего, хотя как потом оказалось это сложнее и самое главное намного дороже. Но это мелочи )
Наковырял на различных форумах разные схемы: схема управления двигателями, схема управления ИК-датчиками и всё это дело завёл на МК AtMega8.

Вобщем-то получился вот такой зверек
image
Впереди два TSOP-а и 3 ИК-светодиода. Внизу 5 светодиодов и 5 фототранзисторов. Вобщем-то и за линиями следить может и препятствия обнаруживает.

Внутри еще немного о роботе, пара фотографий и видео


Очень много времени я на него убил. Много вечеров. Но зато теперь я знаю как травить монтажные платы, какое противное хлорное железо и как оно плохо отстирывается от одежды и какие нехорошие пятна оставляет на столе. Научился лудить и паять, хотя умел и раньше, но только после робота понял как правильно.
Но это всё мелочи ) Удовольствие от результата скрашивает всё.
Генерацией импульсов ИК для TSOP-ов занимается МК, так же он следит за ответами от них и управлением двигателями.

Сзади
image
и снизу
image
Все детали, моторы, датчики и т.д. расположены все вместе на монтажной плате.

Схему рисовал сам в кореле )
image

Моторчики стоят вот такие
image

А вот небольшое видео — правда на видео робот с небольшой доработкой — батареек стало больше.

Снимал, как полагается, на степлер...


На данный момент я немного заморозил работу над роботом. Времени не стало.
Но в ближайших планах его оживить и произвести некоторые улучшения.
1. поставить аккумуляторы (я уже их купил — от дект-телефонов — самое то), а то батарейки быстро садятся.
2. На вал каждого колеса я повешу колёсико и датчик от старой шариковой мышки. Таким образом я смогу отслеживать количество оборотов колеса и поворачивать колесо на нужный мне угол. Это позволит очень гибко управлять троекторией движения. Да… для этого мне придётся убрать несколько фототранзисторов… Вернее убрать придётся 4 и оставить один посередине. Но вобщем-то задачи двигаться по черной линии уже не стоит. Поэтому одной пары СД+ФТ хватит чтобы обнаруживать, например, край стола.
3. Сделать полноценное раздельное питание для МК и двигателей.

Исходник прошивки.

Собирал из кусков по мануалам, так что не судите строго :)
/************************************************
ПОЕХАЛИ
*************************************************/ 

#include <avr/io.h>
#include <avr/delay.h>

#define F 8000.0  // F, несущая, Гц
#define N 20L      // N, количество импульсов в пачке
#define S 2L       // S, скважность пачек

#define t (unsigned long)((1/F)*1000000.0/2.0)  // t, длительность импульса, мкс
#define Tp (unsigned long)(N*(t*2))    // Tp, длительность пачки, мкс
#define Td (unsigned long)(Tp*(S-1))   // Td, задержка между пачками, мкс
	
	
	void init(void) {
		DDRD = 0x00;
		DDRB = 0xff;
		DDRC = 0xff;
		PORTB = 0xff;
		PORTC = 0xff;
		PORTD = 0xff; 
		PORTB |= _BV(PB1);
		PORTB |= _BV(PB2); 
	}
	void rMotorF(void) {
		PORTC &= ~_BV(PC4); // установить "0"	
		PORTC |= _BV(PC2); // установить "1" 	
	}
	void lMotorF(void) {
		PORTC &= ~_BV(PC5); // установить "0"
		PORTC |= _BV(PC3); // установить "1"
	}
	void rMotorB(void) {
		PORTC &= ~_BV(PC2); // установить "0"	
		PORTC |= _BV(PC4); // установить "1" 	
	}
	void lMotorB(void) {
		PORTC &= ~_BV(PC3); // установить "0"
		PORTC |= _BV(PC5); // установить "1"
	}	
	void IRGenerate(void) {
		int i;	
		for (i = 0; i < N; ++i) // Генерация сигналов ИК-светодиодов
		{
			PORTC |= _BV(PC1);
			_delay_us (t);
			PORTC &= ~_BV(PC1);
			_delay_us (t);
		}		
	}
	int main(void) // начало основой программы
	{
		init(); 
		PORTC |= _BV(PC0); 	
		PORTB |= _BV(PB0); 	

		while (1) {
		
			IRGenerate();
			if (!(PIND & (1	<<PIND7))) // проверить сигнал от левого датчика
				{		
					rMotorB(); // Правый мотор назад
					_delay_ms(50);
				}
			else
				{				
					rMotorF(); // Правый мотор вперед
					_delay_ms(50);				
				}	
			_delay_us(Td); 	
			
			IRGenerate();
			if (!(PIND & (1	<<PIND6))) // проверить сигнал от правого датчика
				{			
					lMotorB(); // Левый мотор назад
					_delay_ms(50);				
				}
			else
				{	
					lMotorF(); // Левый мотор вперед
					_delay_ms(50);				
				}
			_delay_us(Td); // 
		}
   }	

Я сам понимаю, что можно это сделать проще… Но я не программист, поэтому методом научного тыка )
Теги:
Хабы:
Всего голосов 60: ↑58 и ↓2+56
Комментарии25

Публикации