|
|
  |
Тахометр на 16меге, не могу разобраться |
|
|
|
May 28 2007, 07:18
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Если хватит диапазона то сделать так: Код g = Speed_p * 166; , а при индикации тупо ставить запятую где надо. Если диапазона int не хватит , то объявить переменную как long int g. Т.е. если у вас и входная и выходная переменные целочисленные, то не к чему делать вычисления с плавающей точкой - все равно потеряете точность и как следствие получите дополнительную погрешность при преобразовании типов.
--------------------
|
|
|
|
|
May 28 2007, 07:22
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(GDI @ May 28 2007, 11:18)  Если хватит диапазона то сделать так: Код g = Speed_p * 166; , а при индикации тупо ставить запятую где надо. Если диапазона int не хватит , то объявить переменную как long int g. Т.е. если у вас и входная и выходная переменные целочисленные, то не к чему делать вычисления с плавающей точкой - все равно потеряете точность и как следствие получите дополнительную погрешность при преобразовании типов. Я вывожу на индикатор целое число. И потом даже при увеличении погрешности если переменная Speed_p не изменяется, то и после умножения на константу любого типа выражение не должно прыгать.... По моему так.. Вообще у меня подозрения что как раз в момент когда выполняется Код Speed_p=TCNT0; ... и тут приходит импульс на вход тактирования таймера TCNT0=0; а я его обнуляю.... возможно здесья теряю единицу.... Может это можно какнибудь отловить....
Сообщение отредактировал DAndy_boy - May 28 2007, 07:27
|
|
|
|
|
May 28 2007, 07:31
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
При умножении константы на константу, конечно результат будет один, вот только Speed_p скорее всего прыгает пусть даже и на единицу, которая и вырастает при умножении и преобразовании типов. Попробуйте просто вывести на индикатор переменную Speed_p и посмотрите - как она меняется при работе. Цитата Speed_p=TCNT0; Это у вас происходит внутри прерывания и все прерывания в данный момент запрещены до выхода из прерывания, т.е. если придет импульс на счетный вход, то сперва завершиться это прерывание, т.е. обнулится TCNT0, затем выполнится одна команда из основного цикла, а затем произойдет вход в новое прерывание.
--------------------
|
|
|
|
|
May 28 2007, 07:50
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(GDI @ May 28 2007, 11:31)  ...Это у вас происходит внутри прерывания и все прерывания в данный момент запрещены до выхода из прерывания, т.е. если придет импульс на счетный вход, то сперва завершиться это прерывание, т.е. обнулится TCNT0, затем выполнится одна команда из основного цикла, а затем произойдет вход в новое прерывание. ну так ведь TCNT0 считает не зависимо от прерывания
|
|
|
|
|
May 28 2007, 07:50
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(DAndy_boy @ May 28 2007, 10:22)  Вообще у меня подозрения что как раз в момент когда выполняется Код Speed_p=TCNT0; ... и тут приходит импульс на вход тактирования таймера TCNT0=0; а я его обнуляю.... возможно здесья теряю единицу.... Может это можно какнибудь отловить.... Да, тут запросто можно потерять. Причём как не старайся - свести вероятность потери к нулю при таком подходе (с обнулением) не выйдет. Нужно дать счётчику бежать свободно и брать разницу двух последовательных показаний за интервал. При этом всё равно в соседние секундные интервалы будут разные значения - при "нецелом" числе импульсов в секунду (скажем, не 100Гц, а 99.5) гарантированно будет, что соседние секундные интервалы содержат разное число импульсов - то 99, то 100. Для 99.9Гц в девяти секундных интервалах будет 100 импульсов, а в одном - 99. Но при свободно бегущем счётчике и взятии разности показаний ни один импульс не будет потерян вообще - он добавится к следующему результату и после фильтрации будет правильная и "твёрдо стоящая" величина. p.s. При таких низких частотах я тоже рекомендую измерение периода и пересчёт. INPUT CAPTURE поможет хватать содержимое счётчика. Чтобы не заморачиваться с ловлей количества переполнений таймера между двумя захватами - выберите предделитель так, чтобы на самой низкой частоте период переполнения таймера был заведомо больше, чем период входного сигнала. Тогда можно брать просто разность двух захватов в ICR и всё.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
May 29 2007, 06:33
|
Участник

Группа: Новичок
Сообщений: 24
Регистрация: 31-05-06
Пользователь №: 17 614

|
Цитата(muravei @ May 28 2007, 13:02)  А может лучше мерять период вх сигнала , а не частоту? А после на "скользящее среднее" я так сделал один раз  работает на ура! а измерять за секунду число имульсов удобно когда их большое число(скажем на валу стоит диск в котором насверлено 1024 дырки тогда получится оч. хорошая разрешающая способность)
|
|
|
|
|
May 29 2007, 10:26
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Начал разбираться с режимом захвата.... и все никак не получается в AVRStudio выставляю флаг на выходе компаратора, а захвата на таймере не происходит.... или это исключительно в симуляции... или я чего не правильно делаю... Может у кого есть какой пример... или скажите где я ошибаюсь, пожалуйста Код #include <avr/io.h> #include <avr/interrupt.h> #include <string.h>
int zahvat;
SIGNAL (ANA_COMP_vect) {
}
SIGNAL (TIMER1_CAPT_vect) {
zahvat=1;
}
int main() {// Declare your local variables here /// Declare your local variables here
// Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00;
// Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00;
// Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00;
// Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x00;
// Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped // Mode: Normal top=FFh // OC0 output: Disconnected TCCR0=0x00; TCNT0=0x00; OCR0=0x00;
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 7372,800 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: On // Input Capture on Rising Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: On // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0xC1; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00;
// External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00; MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x20;
// Analog Comparator initialization // Analog Comparator: On // The Analog Comparator's positive input is // connected to the Bandgap Voltage Reference // Analog Comparator Input Capture by Timer/Counter 1: On ACSR=0x44; SFIOR=0x00;
// Global enable interrupts sei(); while(1) { if(zahvat==1)//произошол захват { // подсчитываем период ... zahvat=0; } }
}
|
|
|
|
|
May 29 2007, 10:52
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(aesok @ May 29 2007, 14:33)  Есть такое волшебное слово: volatile. avr-libc-user-manual FAQ#1, или поиск на форуме.
Анатолий. Я знаю и про первое (хотя и вопрос не в этом) и выполнил второе.... и только потом задал данный вопрос....
|
|
|
|
|
May 29 2007, 11:12
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(DAndy_boy @ May 29 2007, 14:52)  Я знаю и про первое (хотя и вопрос не в этом) и выполнил второе.... и только потом задал данный вопрос.... а почему тогда - int zahvat; - ??? Объясните поодробнее слова "а захвата на таймере не происходит", как вы это определяете. В хелпе на AVRStudio описано какая перефирия не симулируется, уточните там начет компоратора. Анатолий.
|
|
|
|
|
May 29 2007, 11:21
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(aesok @ May 29 2007, 15:12)  а почему тогда - int zahvat; - ??? Это только для примера... Цитата(aesok @ May 29 2007, 15:12)  В хелпе на AVRStudio описано какая перефирия не симулируется, уточните там начет компоратора. Это вы про это? "Analog Comparator (AC) Analog Comparator is not supported." Только сейчас увидел.... даже и не думал.... что такие ограничения.....не ужели не прокатит код Цитата(aesok @ May 29 2007, 15:12)  Объясните поодробнее слова "а захвата на таймере не происходит", как вы это определяете. ну как как? в симуляторе смотрю что регистр захвата не обновляется .... как был 0x0 так и остается... при любом изменениии(естественно мною) регистра ACO
Сообщение отредактировал DAndy_boy - May 29 2007, 11:26
|
|
|
|
|
Jun 1 2007, 04:43
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Господа, опять прошу помощи…. Почитав описание компаратора и режим захвата таймера я пришел к выводу, что при использовании внутреннего опорного напряжения захват будет идти только по срезу входного сигнала… Что не очень удобно, по крайне мере в моем случае. По этому пришлось использовать внешнее опорное напряжение и поменять местами входы компаратора, т.е. на не инвертирующий вход подавать измеряемый сигнал, а на другой - внешнее опорное напряжение? поскольку входной сигнал имеет форму пилы (от 0 до 100 Гц). И все-таки в процессе работы появились подозрения, что бывают моменты, когда захват происходит как по срезу, так и по фронту. И в результате никак не могу получить стабильные результаты, значения прыгают на 1,2 герца. Или тут не обойтись без усреднения за несколько интервалов? Прилагаю код, может кто увидит косяк… Код #define QZ 7372800L #define TIME_OCR1A ((QZ / 1024)) volatile long Zahvat1=0;// захват первого фронта volatile long Zahvat2=0;// захват первого фронта volatile long TOVER=0;// то количество импульсов которое насчитали до //сброса таймера на секунде и до прихода фронта измеряемого сигнала long Zah_end;// количество тактов Таймера между фронтами volatile int k=0; // указывает на каком этапе находимся
SIGNAL (TIMER1_CAPT_vect) { // здесь происходит захват значения таймера if(k==0) {// захватываем первый фронт Zahvat1=ICR1+TOVER; TOVER=0; k=1; } else if(k==1) {// захватываем второй фронт Zahvat2=ICR1+TOVER; TOVER=0; //данные готовы для преобразования и вывода k=5; } }
SIGNAL (TIMER1_COMPA_vect) { // прерывание каждую секунду // поскольку значение таймера сбрасывается, то сохраняем количество импульсов которые насчитали if(k!=5 && TOVER!=0){Zahvat1=Zahvat2=0;k=0;} if(k==0) {TOVER+=TIME_OCR1A-Zahvat1;Zahvat1=0;} else if(k==1) { TOVER+=TIME_OCR1A-Zahvat2;Zahvat2=0;} else if(k==5)TOVER=0; }
/**************************************************************************** Timer1_init() Функция инициализации Timer1. ****************************************************************************/ void Timer1_init(void) { OCR1A = TIME_OCR1A; /* прерывание раз в секунду */ TCCR1A = 0x00; TCCR1B = (1 << 3) | 0x05; TIMSK |= 1 << 4; /* разрешить прерывание OCIE1A */ TIMSK |=1<<5; // режим захвата }
int main() { int g; Timer1_init();
PORTC=0x00; DDRC=0xFF;
// Input/Output Ports initialization // Port A initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=0 State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0xC0;
DDRA|=(1<<4);
// Port B initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=0 State6=0 State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0x00;
// Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=T State2=T State1=0 State0=0 PORTD=0x0C; DDRD=0xF3;
// Analog Comparator initialization // Analog Comparator: On // Analog Comparator Input Capture by Timer/Counter 1: On ACSR=0x04; SFIOR=0x00;
sei(); do { if(k==5) {// значения готовы if(Zahvat2>Zahvat1) { // значения верны str_out[0]=0; // выводим флаг ошибки (все удачно) Zah_end=(Zahvat2-Zahvat1); g=(TIME_OCR1A)/Zah_end; // вычисляем период TOVER=0; str_out[5]=g%10;g/=10; str_out[4]=g%10;g/=10; str_out[3]=g%10;g/=10; str_out[2]=g%10;g/=10; } else // значения не верны след. не учитываем их str_out[0]=1; // выводим флаг ошибки k=0; }
reload(); // динамическая индикация }while(1);
}
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|