Гусеничный Робот

14-12-2014, 17:27 От: admin Посмотрели: 342
Здравствуйте! Есть гусеничный робот. Спереди на нем стоят два фотодиода. Есть черная линия по которой он должен ездить и поворачивать с помощью ШИМа. У правляющий порт - С. Комбинация PORTC |= 0x82U; заставляет его ехать вперед. Вроде бы ничего сложного, но уже несколько дней не могу понять в чем накосячил. Стоит на месте и не едет. При этому, если без ШИМа подать на ножки напряжения, то начинает ехать прямо как ему и положено.

Я не прошу разбирать весь код (но и не откажусь Гусеничный Робот), но не могли бы вы окинуть свежий взгяд на листинг программы ? Вдруг увидите что-нибудь. Спасибо!




#include <mega32.h>
#include <delay.h>

unsigned char x = 0, y = 0;
unsigned char K = 0;

/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Объявленияе функций //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

//Заставляем робот ехать вперед (настройка портов)
//-----------------------------------------------------------------------------------------
void start();

//Настройка АЦП
//-----------------------------------------------------------------------------------------
void init_adc();

//Чтение из АЦП
//-----------------------------------------------------------------------------------------
unsigned int read_adc(unsigned char Pin_ADC);

//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02();

//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer1();

// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void);



/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Функция main //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void main()
{
init_adc();
init_adc();
init_timer02();
init_timer1();

start();

#asm("sei") // Разрешение прерывания
while(1)
{


}
}




/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Описание функций /////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

// Установка АЦП
//-----------------------------------------------------------------------------------------
void init_adc()
{
ADMUX = 0x40U; //выбираем источник питания АЦП 5v
ADCSRA |= 0x07U; // устанавливаем предделитель 128 (ADPS2, ADPS1, ADPS0), он нужен из-за того, что ацп занимает много тактов
ADCSRA |= 0x80U; // Включаем АЦП (ADEN)
}

// Чтение из АЦП
unsigned int read_adc(unsigned char Pin_ADC)
{
ADMUX |= Pin_ADC & 0x07U; // Разрешаем менять только 3 последний бита
delay_us(10); // Задержка на 10 микросек по даташиту
ADCSRA |= 0x40U; // Выставлем бит ADIF для запуска преобразования
while((ADCSRA & 0x10) == 0); // Ждем пока оно совершится

return ADCW; // Возвращем сразу значение старшего и младшего бита АЦП
}

// Порты
//-----------------------------------------------------------------------------------------
void start()
{

DDRD |= 0x80U;
DDRB |= 0x08U;

DDRC |= 0x82U;

PORTC |= 0x82U;
}

// Таймеры 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02()
{
// Указываем явным образом начальное значение регистра счета
TCNT0 = 0x00U;
TCNT2 = 0x00U;

// Укахываем начальное значение регистра сравнения
// Впоследствии оно будет меняться ШИМом
OCR0 = 0x3F;
OCR2 = 0x3F;

// Регистр настройки
TCCR0 = 0x48U; // Fast PWM
TCCR0 |= 0x20U; // Сброс в 0 при прямом счете
TCCR0 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

TCCR2 = 0x48U; // Fast PWM
TCCR2 |= 0x20U; // Сброс в 0 при прямом счете
TCCR2 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

}

// Таймера 1
//-----------------------------------------------------------------------------------------
void init_timer1()
{
TCCR1B |= 0x04U; // устанавливаем режим СТС (сброс по совпадению
TIMSK |= 0x10U; // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

OCR1AH = 0b00000111; // определяем число сравнения. Определяем как часто делать прерывания
OCR1AL = 0b00000000;

TCCR1B |= 0x01U; //запуск таймера без предделителя
}

// Прерывание
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности

if (x < y)
OCR0 = OCR0 - K * 10;
else
OCR2 = OCR2 - K * 10;


}

Раздел: AVR

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться, либо войти на сайт под своим именем.

Обсудить на форуме


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


Опрос

Ваши предпочтения в TRX


Одинарное преобразование
Двойное преобразование
Прямое преобразование
SDR
Другое
Мне всё равно

Популярные новости
Календарь новостей
«    Апрель 2024    »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
2930