реклама на сайте
подробности

 
 
> Частотомер на Atmega8 (CVAVR)
ps1x
сообщение Jun 9 2010, 17:23
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284



Делаю (пытаюсь сделать) частотомер по методу предложеному =GM= тут: http://electronix.ru/forum/index.php?showtopic=29796. Но вот что то не получается. Верней получается но не совсем. Во первых если я меняю задержку между началом и концом измерения то получаю существенно разные варианты. Но в то же время, если задержка ровно 1 сек (delay_ms(1000)wink.gif то результат выводится либо равный расчетному либо чуть больше. Причем как будто бы не хватает одного переполнения таймера 1 т.е. Perepol_Timer1++; и число N1 получается на 65536 меньше. Из за чего результат чуть больше. Но куда оно может пропасть?

код вообще то взят в основном отсюда http://pro-radio.ru/controllers/5978/(с комментариями) но там не работает регистрация поэтому спрашиваю тут.

Код
char gate;
static float Fx;
unsigned long int N, N0, M, M0, N1, M1;
unsigned int Perepol_Timer0=0, Perepol_Timer1=0, count_T1, count_T0,Perepol_Timer1_real;

//Прерывание по переполнению Timer/Counter 0
interrupt [TIM0_OVF] void timer0_ovf_isr(void){
Perepol_Timer0++;//Увеличение переменной на 1
}

//Прерывание по переполнению Timer/Counter 1
interrupt [TIM1_OVF] void timer1_ovf_isr(void){
if (gate){
        Perepol_Timer1++;//Увеличение переменной на 1
}
}

//Прерывание по захвату Timer/Counter 1
interrupt [TIM1_CAPT] void timer1_capt_isr(void){                  
count_T1=ICR1;//Значение регистра ICR1 переписывается в переменную
count_T0=TCNT0;//Значение регистра TCNT0 переписывается в переменную
TIMSK&=0xDF;//Запрет прерывания по захвату                          
if (TIFR&0b00000100==1){
Perepol_Timer1++;
TIFR&=0b00000100;
}
}


while (1){//Бесконечный цикл
#asm("cli")  
gate=0;
Perepol_Timer1=0;//Обнуление переменной
Perepol_Timer0=0;//Обнуление переменной
#asm("sei")//Разрешения прерываний
TIMSK|=0x20;//Разрешили захват
gate=1;
while ((TIFR&0x20)==0x20){}//Ожидание прерывания по захвату
Perepol_Timer1_real = Perepol_Timer1;
N0=(((unsigned long int)(Perepol_Timer1_real))<<16)+count_T1; //Расчет общего количества тиков системной частоты
M0=(((unsigned long int)(Perepol_Timer0))<<8)+count_T0;//Расчет общего количества тиков входной частоты
//sprintf(lcd_buffer, "PT1=%u;CT1=%u;PT0=%u;CT0=%u;\r", Perepol_Timer1_real, count_T1, Perepol_Timer0, count_T0);
//puts(lcd_buffer);
delay_ms(1000);//Задержка на 1 с
TIMSK|=0x20;//Разрешили захват
gate=0;
while ((TIFR&0x20)==0x20){}//Ожидание прерывания по захвату  
Perepol_Timer1_real = Perepol_Timer1;
N1=(((unsigned long int)(Perepol_Timer1_real))<<16)+count_T1; //Расчет общего количества тиков системной частоты
M1=(((unsigned long int)(Perepol_Timer0))<<8)+count_T0;//Расчет общего количества тиков входной частоты
sprintf(lcd_buffer, "PT1=%u;CT1=%u;PT0=%u;CT0=%u;\r", Perepol_Timer1_real, count_T1, Perepol_Timer0, count_T0);
puts(lcd_buffer);
N=(N1-N0);//Расчет количества тиков системной частоты за время измерения
M=(M1-M0);//Расчет количества тиков входной частоты за время измерения

Fx=12000000.0*(float)M/(float)N;//Вычисление частоты входного сигнала
putchar('c');
sprintf(lcd_buffer, "F=%0.6fHz", Fx);
lcd_clear();
lcd_puts(lcd_buffer);
puts(lcd_buffer);
putchar(13);
} }
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
=GM=
сообщение Jun 10 2010, 21:36
Сообщение #2


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



У вас ошибка: второе прерывание TOV1 никогда не даст инкремента, поскольку GATE=0. Число N1 естественно будет меньше на 2^16.

Далее, счётчик T0 у вас 8-битный, а переменная count_T0 у вас int, ну и добавляете вы ее, как int, а надо только 8 бит. Для вашего компилятора может и пройдёт, но лучше по-честному добавлять 8-битное число.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ps1x
сообщение Jun 11 2010, 08:54
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284



Цитата(=GM= @ Jun 11 2010, 01:36) *
У вас ошибка: второе прерывание TOV1 никогда не даст инкремента, поскольку GATE=0. Число N1 естественно будет меньше на 2^16.

Таким образом пишем gate=0; после while ((TIFR&0x20)==0x20){}?
Цитата(=GM= @ Jun 11 2010, 01:36) *
Далее, счётчик T0 у вас 8-битный, а переменная count_T0 у вас int, ну и добавляете вы ее, как int, а надо только 8 бит. Для вашего компилятора может и пройдёт, но лучше по-честному добавлять 8-битное число.

а здесь пишем count_T0=(int)TCNT0; с приведением типа. (хотя компилятор сам это делает, не делает а пишет варнинги если написать char*2, например, то он ругнется на переполнение чара.)

В общем результат тот же. sad.gif И число N1 то меньше на 65536 то ровно столько сколько надо. От чего это зависит не понимаю. 3 измерения так - 3 так.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Jun 11 2010, 21:28
Сообщение #4


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Структура вашей программы в некотором смысле эклектична.

1) Вроде бы работаете по прерываниям, но и ждёте флаг прерывания ICF1 в фоне, и явно это будет другое прерывание, поскольку по завершению прерывания флаг ICF1 сбрасывается в самом прерывании. Зачем тогда его ждёте?

2) В начале цикла измерения вы разрешаете прерывания по захвату, но не учитываете, что физически захват как молотил со скоростью входной частоты, так и молотит. Следовательно, после разрешения прерывания TOIE1=1 надо бы сбросить флаг ICF1, также и в конце измерения.

Кстати, каков диапазон частот вы хотите измерять, какой проц и тактовая?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ps1x
сообщение Jun 12 2010, 11:43
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284



Цитата(=GM= @ Jun 12 2010, 01:28) *
Структура вашей программы в некотором смысле эклектична.
Кстати, каков диапазон частот вы хотите измерять, какой проц и тактовая?

Да, программа такова, ибо сначала я пытался измерять методом ворот, но удачи не достиг smile.gif Вот код моего варианта:
Код
float result;
char buff[16], tim, numizm=2, state=0;

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
        tim++; // увеличиваем счетчик переполнений.
}

// Timer 1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
        if (state==0){  // первый фронт сигнала
                tim=0;  // обнуляем переменные и таймер
                TCNT1=0;
        }
        state++; // прибавляем счетчик
        if (state == numizm){ // если счетчик и кол-во измерений равны, то вычисляем частоту
                result = 12000000 / ((float)tim*65535+ICR1); // вычисляем "частоту"
                result *= (int)numizm; // и умножаем на кол-во измерений, получая действительную частоту

                numizm = 255; //выставляем число измерений
                if (numizm < result){ // если оно меньше полученной частоты то ставим ее равной частоте ( т.о. измерение будет длиться меньше секунды)
                        numizm = result;
                }                      
                sprintf(buff,"F = %0.3f Гц",result); // выводим на экран и в UART
                puts(buff);
                putchar(13);
                lcd_clear();
                lcd_puts(buff);
                state = 0; // Обнуляем состояние
        }                    
}

На мой взгляд совершенно логичный, но не работающий. Потом мне объяснили что таким способом, разрешающая способность будет не велика. Поэтому я решил пойти по пути Вашего метода. Ну и взял 2 варианта кода и их объединил smile.gif

Ну а частоты которые мне нужно измерять - 2 кГц -- 10 кГц. Насколько я понимаю, Вашим методом можно достичь очень хорошей точности, что для струнного датчика (линейный размер -> частота) было бы очень неплохо smile.gif

МК Atmega8 частота не принципиальна, но вот сейчас под рукой кварц на 12 мГц.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Jun 12 2010, 12:51
Сообщение #6


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Для вашего случая погрешность измерения приблизительно будет +-0.0002 Гц без учёта нестабильности кварца. Вы не плодите варианты, а сконцентрируйтесь на первом, он вполне работоспособен. Как вы струну возбуждаете?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ps1x
сообщение Jun 12 2010, 21:51
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284



Цитата(=GM= @ Jun 12 2010, 16:51) *
Как вы струну возбуждаете?

Для этого используется автогенератор. На выходе его 300 мВ 2 -10 кГц прямоугольные импульсы. Но вообще эти старые железки хочется переделать и встроить в свое устройство.

Кстати говоря, вы своим вопросом породили во мне другой вопрос: можно ли использовать в Вашем алгоритме компаратор встроенный в мегу8 для захвата и будет ли его достаточно для детектирования столь низкого по амплитуде сигнала?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Jun 13 2010, 22:22
Сообщение #8


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ps1x @ Jun 12 2010, 20:51) *
можно ли использовать в Вашем алгоритме компаратор встроенный в мегу8 для захвата и будет ли его достаточно для детектирования столь низкого по амплитуде сигнала?

В принципе, думаю можно, хотя оффсет у компаратора достаточно большой, посмотрите на рис. 167-168 док. 2486.

Думаю, что для ваших целей подойдёт более простой код для измерения частоты, это модификация вашего варианта, я только немного упорядочил и заменил названия "непроизносимых" переменных. Есть правда один нюанс, но об этом позже. Компилятор WinAVR-20100110
CODE
static float volatile Fx;
uint32_t volatile N,N1,N2,M,M1,M2;
uint16_t volatile mtick1,mtick2,mover=0;
uint16_t volatile ntick1,ntick2,nover=0;

ISR (TIMER0_OVF_vect) //переполнение счётчика0 входных тиков
{
mover++; //учтём в mover
}

ISR (TIMER1_OVF_vect) //переполнение таймера1 системных тиков
{
nover++; //учтём в nover
}

int main(void)
{
TIMSK=(1<<TOIE1)|(1<<TOIE0); //разрешим TOV1 и TOV0
asm volatile("sei\n\t":smile.gif; //разрешим прерывания
while(1) //цикл непрерывного измерения частоты
{
TIFR=(1<<ICF1); //сбросим флаг захвата
while((TIFR&0x20)==0x20); //ждём начала измерения
ntick1=ICR1; //запомним ICR1 и TCNT0
mtick1=TCNT0; //в начале измерения
ntick2=nover;
mtick2=mover&0x00FF;
N1=((uint32_t)(ntick2)<<16)+(uint32_t) ntick1; //системные тики
M1=((uint32_t)(mtick2)<<8) +(uint32_t) mtick1; //входные тики
delay_ms(1000); //задержка на 1 с
TIFR=(1<<ICF1); //сбросим флаг захвата
while((TIFR&0x20)==0x20); //ждём конца измерения
ntick1=ICR1; //запомним ICR1 и TCNT0
mtick1=TCNT0; //в конце измерения
ntick2=nover;
mtick2=mover&0x00FF;
N2=((uint32_t)(ntick2)<<16)+(uint32_t) ntick1; //системные тики
M2=((uint32_t)(mtick2)<<8) +(uint32_t) mtick1; //входные тики
N=N2-N1; //системные тики за время измерения
M=M2-M1; //входные тики за время измерения
Fx=12000000.0*(float)M/(float)N; //вычисление частоты входного сигнала

// <<здесь должен быть код вывода на индикатор>>

}
}


Обращаю внимание СИСАДМИНА: при редактировании тег [ / codebox ] самопроизвольно меняется на тег < / div >, возникает ошибка.

Сообщение отредактировал rezident - Jun 14 2010, 22:29
Причина редактирования: Редактирование тэгов цитаты исходника.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ps1x   Частотомер на Atmega8 (CVAVR)   Jun 9 2010, 17:23
- - Сергей Борщ   Вы учитываете остаток в регистре таймера на момент...   Jun 10 2010, 06:02
|- - ps1x   Цитата(Сергей Борщ @ Jun 10 2010, 10:02) ...   Jun 10 2010, 09:01
|- - ps1x   Цитата(=GM= @ Jun 14 2010, 02:22) В принц...   Jun 14 2010, 18:46
|- - =GM=   1) Оффсет влияет на начало фронта, многое зависит ...   Jun 15 2010, 09:11
- - ps1x   CODE#include <mega8.h> //Подключение #incl...   Jun 15 2010, 09:38
|- - =GM=   1) Для начала неплохо. Каков был номинал входной ч...   Jun 15 2010, 10:34
|- - ps1x   Входная частота 1019.02173 Гц. Расчетная. По осцил...   Jun 15 2010, 11:36
|- - =GM=   Разница М2-М1 всё время где-то 1033-1034, это прие...   Jun 15 2010, 12:03
- - ps1x   Кодreset aN1=65536 M1=98 ntick1=0 ntick2=1 N2=125...   Jun 15 2010, 12:50
|- - =GM=   Теперь мне не нравится, что ntick1 всё время равен...   Jun 15 2010, 14:05
|- - ps1x   Цитата(=GM= @ Jun 15 2010, 18:05) Признав...   Jun 15 2010, 14:58
|- - =GM=   Цитата(ps1x @ Jun 15 2010, 13:58) Входной...   Jun 15 2010, 15:35
- - ps1x   А DDR соответствующих ножек влияет? Подтяжка? Сейч...   Jun 15 2010, 16:02
|- - =GM=   Да, надо соединить Т0 и ICP с генератором меандра....   Jun 15 2010, 16:23
- - ps1x   Появилась стабильность Значения 1018.8184 - 1018....   Jun 15 2010, 19:22
|- - =GM=   Ну, я рад за вас. Выбросы происходят из-за того са...   Jun 15 2010, 19:36
- - ps1x   Автогенератор в институте, и схемы от него нет, да...   Jun 15 2010, 20:21
|- - =GM=   Цитата(ps1x @ Jun 15 2010, 19:21) Может б...   Jun 16 2010, 10:10
|- - ps1x   Цитата(=GM= @ Jun 16 2010, 14:10) 4) Пров...   Jun 16 2010, 13:31
|- - =GM=   Не понял, по-подробнее можно?   Jun 16 2010, 14:33
|- - ps1x   Ваш пост из того топика.   Jun 16 2010, 14:51
|- - =GM=   Ну что, ps1x, есть подвижки? В принципе, я нашёл р...   Jun 21 2010, 15:31
|- - ps1x   Цитата(=GM= @ Jun 21 2010, 19:31) Ну что,...   Jun 23 2010, 18:37
|- - =GM=   Попробуйте следующий код, для ваших целей должен п...   Jun 24 2010, 21:56
|- - ps1x   Работает прекрасно +/- 0.0001 мкС Большущее спаси...   Jun 25 2010, 10:27
|- - =GM=   На здоровье. Но 0,0001 мкс - это 0,1 нс, вы не ош...   Jun 25 2010, 11:19
|- - demiurg_spb   Цитата(=GM= @ Jun 25 2010, 15:19) На здор...   Jun 25 2010, 12:00
||- - =GM=   Цитата(demiurg_spb @ Jun 25 2010, 11:00) ...   Jun 25 2010, 13:06
||- - demiurg_spb   Цитата(=GM= @ Jun 25 2010, 17:06) Я уж ис...   Jun 27 2010, 19:19
||- - =GM=   1) В чём конкретно вы видите лёгкое неудобство от ...   Jun 28 2010, 11:34
||- - demiurg_spb   Цитата(=GM= @ Jun 28 2010, 15:34) 1) В чё...   Jun 28 2010, 17:34
||- - =GM=   Цитата(demiurg_spb @ Jun 28 2010, 16:34) ...   Jun 28 2010, 21:56
|- - ps1x   Цитата(=GM= @ Jun 25 2010, 15:19) Но 0,00...   Jun 26 2010, 09:13
- - ps1x   Пожалуй, подниму тему из глубин форума. Встала зад...   Nov 3 2010, 11:50
- - akl   В mega8 есть аналоговый компаратор, имеющий доступ...   Nov 3 2010, 16:19
|- - ps1x   Цитата(akl @ Nov 3 2010, 20:19) В mega8 е...   Nov 3 2010, 18:15
- - akl   Цитата(ps1x @ Nov 3 2010, 15:50) Судя по ...   Nov 3 2010, 18:39
|- - =GM=   Если измерять частоты надо одновременно, то вот ва...   Nov 3 2010, 20:40
- - ps1x   Но ведь вроде T0 и T1 асинхронные, и считают незав...   Nov 3 2010, 20:50
|- - =GM=   Ну, вот вам ещё вариант: берёте МК с тремя таймера...   Nov 3 2010, 22:55
- - horoc   =GM= Заинтересовался Вашим способом, давно хотел с...   Nov 7 2010, 13:54
|- - =GM=   Ну, трудно обьяснить, попробую. Цикл do ... whil...   Nov 7 2010, 18:52
- - horoc   Я поэкспериментировал немного, сделал вот так. К...   Nov 7 2010, 19:16
- - horoc   Вот еще на танцевал с бубном =GM= благодарю...   Nov 7 2010, 21:06
- - Pikt   Приветствую. Я плохо разбираюсь пока что в микроко...   Jun 19 2011, 11:32
- - =GM=   Пойдёт. Выходной сигнал - двоичное число в операт...   Jun 20 2011, 13:05


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 07:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.01518 секунд с 7
ELECTRONIX ©2004-2016