Описание: ничего не происходит после АЦП |
Поиск в теме | Версия для печати |
Vaspit |
Отправлено: 26 Августа, 2011 - 11:11:41
|
Полковник
Сообщений всего: 70
Дата рег-ции: Июль 2010
|
Идея такая: когда датчик видит препятствие, робот отъезжает назад или поворачивает. Само по себе АЦП отлично работает. Но вот, на днях, решил прикрутить ко всему этому делу ШИМ, чтоб на поворотах робот работал плавнее. Но вот незадача, при попадании предмета в поле зрения датчика почему-то ничего не происходит. Возможно всё дело в том, что я как-то не так работаю с регистром OCR1A или не правильно задал цикл ожидания переполнения Таймера 1. В инете есть несколько примеров работы с ШИМ, но либо они написаны на ассемблере, либо написаны под общий случай, т.е. только настройка и ожидание прерывания в цикле while(1), что в моём случае не допустимо, ибо прерывание и запуск таймера мне нужно включать в определённый момент времени. Собственно, проблема в том, что робот едет вперёд и перед ним появляется препятствие, но ничего не происходит (а должен отъезжать назад).
P.S. Насколько в процессе выполнения цикла ожидания установки флага переполнения таймера должно вызваться 2 прерывания по совпадению, т.к. таймер работает в режиме Phasec Correct PWM и в этом случае он (флаг) устанавливается по достижении значения BOTTOM, т.е., насколько я понимаю, 0x00 (по умолчанию).
Код такой:
/***************************************************
CODE:Chip type : ATmega16
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega16.h>
unsigned int adc_data1;
unsigned int adc_data2;
unsigned int adc_data3;
unsigned int i; //переменная для направления движения
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
if (i==0){ //прямо
if (PORTB==0b00001001) PORTB=0x00;
else PORTB=0b00001001;
}
else
if (i==1){ //налево
if (PORTB==0b00000101) PORTB=0x00;
else PORTB=0b00000101;
}
else
if (i==2){ //напрво
if (PORTB==0b00001010) PORTB=0x00;
else PORTB=0b00001010;
}
else
if (i==3){ //назад
if (PORTB==0b00000110) PORTB=0x00;
else PORTB=0b00000110;
}
}
//Процедура ШИМ
void Start_PWM(unsigned int ocr_data)
{
TCNT1=0; //сброс счётного регистра
OCR1A=ocr_data; //Настройка регистра сравнения
TCCR1B=0x05; //установка делителя частоты (запуск таймера)
while(TIFR != 0x80); //ожидания переполнения (TOV1==1)
TCCR1B=0x00; //выключение таймера
}
void Backward(unsigned int ocr_data)
{
i=3; //движение назад
Start_PWM(ocr_data); //Запуск ШИМ
}
void ReadADC_1(unsigned int adc_setup)
{
ADCSRA=0x87;
ADMUX=adc_setup;
ADCSRA.6=1;
while(ADCSRA.4==0);
adc_data1=ADCW;
}
void ReadADC_2(unsigned int adc_setup)
{
ADCSRA=0x87;
ADMUX=adc_setup;
ADCSRA.6=1;
while(ADCSRA.4==0);
adc_data2=ADCW;
}
void ReadADC_3(unsigned int adc_setup)
{
ADCSRA=0x87;
ADMUX=adc_setup;
ADCSRA.6=1;
while(ADCSRA.4==0);
adc_data3=ADCW;
}
void main(void)
{
// Declare your local variables here
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0xFF; //0b00001111
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: ШИМ корректный по фазе
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x03;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
ReadADC_3(0b01000010);
if (adc_data3 > 300) Backward(43200);
else PORTB=0b00001001;
};
}
Выглядит всё это так:
http://s2.ipicture.ru/uploads/20110826/ux1K1USh.jpg(Отредактировано автором: 26 Августа, 2011 - 11:19:38) |
|
|
Vaspit |
Отправлено: 27 Августа, 2011 - 01:36:42
|
Полковник
Сообщений всего: 70
Дата рег-ции: Июль 2010
|
Цитата:Есть изменения в поведении робота?
Нет. Видимо он даже до процедуры Start_PWM не дошёл. Но, повторюсь, датчики исправны и это подтверждено 2мя фактами:
1)Переключился на другой канал (соответственно и на другой датчик) - аналогичная ситуация (нечего не работает);
2)убираю ШИМ (ставлю старую прошивку только с АЦП) - всё работает отлично; [/quote]
Цитата:Какой предделитель таймера?
clk/1024
За какое время он переполняется?
Точно, у меня ж clk/1024 => 8 сек !!!! Ёмана рот)))
(Добавление)
Тааак. Работает. Но как-то неадекватно. Т.е. после того, как я убираю препятствие от датчика, он ещё через 2-3 секунды, на долю секунды переключает моторчики на вращение назад и потом норм. Вообще делитель поставил на clk/8. Или может его совсем не делить?(Отредактировано автором: 27 Августа, 2011 - 01:52:42) |
|
|
Vaspit |
Отправлено: 28 Августа, 2011 - 11:06:09
|
Полковник
Сообщений всего: 70
Дата рег-ции: Июль 2010
|
Цитата:У драйвера двигателя, скорее всего, имеется ограничение на максимальную частоту ШИМ.
У меня есть набор IE-Robopica. Там стоит такой же 293D. Там ШИМ работает отлично. Или я чего-то не понял? Что имеется в виду под ограничением на максимальную частоту? Т.е. мне делитель надо больше ставить?
А во время прерывания счётчик таймера останавливается?
У меня просто сама схема ШИМ такова:запуск таймера -> таймер отсчитывает вверх -> достигает значения OCR1A -> вызывается прерывание, где изменияются сигналы порта Б -> выход из оброботчика прерывания -> продолжение счёта вверх, пока не достигнет значения TOP (0x03FF) -> изменияется направление отсчёта таймера -> снова достигает значения OCR1A -> вызывается прерывание, где изменияются сигналы порта Б -> выход из оброботчика прерывания -> ожидание пока не достигнет значения BOTTOM (0x0000) -> выключение таймера -> выход из процедуры ШИМ.
Это вообще правильно я делаю?
P.S.
Заметил, что робот вообще внезапно входит в процедуру ШИМ, хотя я не подносил препятствий к датчику. Т.е. полнейший хаос.
Как на языке Си можно задать ожидание, пока не установится 7й бит регистра TIFR? Т.е не как у меня While(TIFR != 0x80), а как-нибудь вроде while(TIFR.7 == 0) <--- так он почему-то не понимает, хотя работаю в CV AVR.
Как на языке Си организовать выход из процедуры, как в Дельфи с помощью "continue"?(Отредактировано автором: 28 Августа, 2011 - 11:31:36) |
|
|
|
Поиск в теме | Версия для печати |
Страниц (1): [1] |
« Программирование микроконтроллеров » |
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
|
|
|
|
|