РРМ индикатор

Mishanya

Хочу сделать РРМ индикатор с тестером серво машинок.
На данный момент я стою в самом начале изучения AVRов.
Принцип работы самого индикатора представляю себе так.
PPM с приёмника подаю на ножку INT0 прерывание срабатывает при любом изменение на входе.
Таймер подщитывает длину импульса и если длина в приделе от 1-2ms выводим результат на LCD в ms
или в градусах поворота серво машинки.
Проблемма на данный момент в конфигурации таймера и фюзов.
Вот тут вариант схемки:

serg111

Вчем конкретно проблемма? Таймер не считает или инт0 не отрабатывает?

Mishanya
serg111:

Вчем конкретно проблемма? Таймер не считает или инт0 не отрабатывает?

Таймер считает, но результат каждый раз разный, такое впечатление, что он живёт своей жизнью, не обращая внимание на INT0.

PigTail

Хм… конкретнее алгоритм, что и как считаете, зачем любое изменение на входе, а не конкретный фронт, какой таймер пользуете, установки таймера, почему на INT0, а не на ICP1, если хотите работающую вещь получить ставьте кварц.

Boroda
Mishanya:

Таймер считает, но результат каждый раз разный

Так и есть, таймер выдаёт лишь текущее значение “своего” времени. Надо считать значение по восходящему фронту INT, а затем вычесть его из значения, считанного по падающему фронту. Разность и будет длительностью импульса. Ещё можно по возрастающему фронту обнулить таймер, тогда на прерывании по спаду он будет содержать уже правильное значение PPM. Думайте, пишите, Вы идёте в правильном направлении!
Бывает, что прерывание INT временно заблокировано другим, а таймер продолжает считать. К моменту разблокировки он будет содержать ошибку времени ожидания. Для борьбы с такой неприятностью AVR содержит механизм захвата внешнего ШИМ. При событии на ноге ICP, текущее значение таймера сохраняется в регистре ICR и выставляется флаг запроса прерывания. В документации всё подробно описано.

Mishanya
Boroda:

Так и есть, таймер выдаёт лишь текущее значение “своего” времени. Надо считать значение по восходящему фронту INT, а затем вычесть его из значения, считанного по падающему фронту. Разность и будет длительностью импульса. Ещё можно по возрастающему фронту обнулить таймер, тогда на прерывании по спаду он будет содержать уже правильное значение PPM.

Как мне в одном прирывании отличить возрастающий фронт, от спадающего?

PigTail

какой таймер пользуете, установки таймера, почему на INT0, а не на ICP1, если хотите работающую вещь получить ставьте кварц.

Какой таймер лучше для моей цели 16 или 8 битный (сейчас пользую timer0 8bit).
ICP1 занят под LCD_RS, кварц нет проблем, поставлю.

EagleB3
Boroda:

AVR содержит механизм захвата внешнего ШИМ

Как эта штука называется в даташитах? Чтобы поиском в даташите найти…

Хвост_Слона

16-битный таймер, кварца для Ваших целей не надо, фузы ставить под внутрений генератор на 8 мгц, таймер тактировать 1000 кгц. 1тик=1 микросекунда. Из-за двухбайтовой арифметики таймер можно не сбрасывать, а просто вычислять duration=timer-old_timer; (переменные int)

Boroda
Mishanya:

Как мне в одном прирывании отличить возрастающий фронт, от спадающего?

Прочитать значение PIND.2 (INT0)

EagleB3:

Как эта штука называется в даташитах? Чтобы поиском в даташите найти…

Input Capture Unit

VRV

скажу пару слов:
даже если с таймером разберетесь и он правилоьно определит длительность каналов- показания всеравно будут прыгать, т.к в пачке идет 6-8 импульсов, соответствующих каждому каналу. Т.о. примерный алгоритм следующий:
1- найти синхроимпульс, длительность которого больше 2.5 мс(у отдельных передатчиков на канал может идти больше 2 мс)
2-начать измерение длительности импулсов, до седующего синхро. данные измерения писать в массив,
3- вывести значения длительности для выбранного канала.

Сама програма расчета(не считая сервиса вывода на жки) займет от силы 10-20 строк и уместится в обработчике прерывания.
Для отладки попробуйте симуляцию в протеусе(отлов ошибок, да и жки тоже отладить можно:))

EagleB3
Mishanya:

Хочу сделать РРМ индикатор с тестером серво машинок.
На данный момент я стою в самом начале изучения AVRов.

Загляни сюда. Исходники там есть, а превратить декодер в сервотестер, КМК, задачка в самый раз для начинающего.

Mishanya

Спасибо, почитаю. Жаль, что коментарии не видно, белеберда какая-то.

VRV
Mishanya:

Спасибо, почитаю. Жаль, что коментарии не видно, белеберда какая-то.

в блокноте открой-скорее всего с кодировкой трабл
а вооще сам проект для разбора не самый удачный(хотя если разберешся-останеться ток жки подцепить)

8 days later
Mishanya

Таймер бежит, результат на LCD каждый раз другой и разброс большой.
Где-то ошибаюсь. Может, подскажите где?
Прошу сильно не ругать.

#include <mega8.h>
#include <delay.h>
#include <stdio.h>
#include <lcd.h>

void ppm_display (void);

char lcd_buffer[33];
int lcd_1,lcd_2;

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (PIND.2 == 1)
{
TIMSK=0x04; // Timer1 Overflow Interrupt Enable
TCCR1A=0x00; // Timer1 Control Register A
TCCR1B=0x01; // Start Timer1
TCNT1H=0x00; // Timer1 TCNT1H
TCNT1L=0x00; // Timer1 TCNT1L
}
else
{
TCCR1B=0x00; // stop Timer1
lcd_1 = TCNT1L;
lcd_2 = TCNT1H;
ppm_display();
}
}

//Timer 0 interrupt
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

}

void main(void)
{
// Port B initialization
PORTB=0xFF;
DDRB=0xFF;

// Port C,D initialization
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 1 initialization
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
GICR|=0x40; // INT0: On
MCUCR=0x01; // INT0 Mode: Any change
GIFR=0x40; // INT1: Off

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x04;

lcd_init(16); // LCD module initialization

#asm(“sei”) // Global enable interrupts

while (1)
{
}
}

void ppm_display (void)
{
#asm(“cli”)
lcd_gotoxy(0,0);
sprintf(lcd_buffer,“PPM L=%dms”,lcd_1);
lcd_puts(lcd_buffer);
lcd_gotoxy(0,1);
sprintf(lcd_buffer,“PPM H=%dms”,lcd_2);
lcd_puts(lcd_buffer);
delay_ms(200); //delay 200ms
lcd_clear(); //Lcd clear
lcd_1 = 0x00;
lcd_2 = 0x00;
#asm(“sei”)
}

VRV

прочитай 10 пост.
а вобще то сервртестер сам предполагает генерацию импульсов(те передатчик ненужен!), т.о. осушествляется генерация импульсов длительностью 1-2 мкс(например от данных крутилки->ацп) и периодом 20 мс.

Mishanya
VRV:

а вобще то сервртестер сам предполагает генерацию импульсов(те передатчик ненужен!), т.о. осушествляется генерация импульсов длительностью 1-2 мкс(например от данных крутилки->ацп) и периодом 20 мс.

В том-то и дело, что мне передатчик нужен. А 10й пост я читал, но только мне он не как не помог.

PigTail

Для начала вынести ppm_display(); из прерывания в main, пока Вы там отображаете на индикаторе что угодно может происходить, так никто не делает. И кстати на какой частоте у Вас все это происходит и что Вы в действительности смотрите канальный импульс или пакет PPM ?