Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
09.04.2009, 15:03
|
|
Частый гость
Регистрация: 07.04.2009
Сообщений: 16
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Сообщение от alexgap
|
Цитата:
|
CVRCON == 0x00C7; // Смена опоры
CVRCON == 0x00CF;
|
Вы используете операторы сравнения для изменения значения? Ай-яй-яй Должно быть так:
Цитата:
|
CVRCON = 0x00C7; // Смена опоры
CVRCON = 0x00CF;
|
Во-вторых я вижу что вы выводите значение частоты в каждом цикле.
Цитата:
|
Display_num((int)(f));
|
Этого делать тоже нельзя, так как будет огромная погрешность, ведь вывод занимает время, а в случае с LCD это время может зависеть и от капризов внешнего контроллера. Делайте так. 100-1000 циклов измерения, усреднение и потом один вывод на экран. Так чтобы период обновления информации был в районе 1 секунды или чуть меньше.
|
Про смену опоры - когда оформлял код для форума напортачил, так, конечно, даже компилятор не допустил бы такого.
Про вывод - сейчас убираю вывод, запускаю с помощью шайбы секунд на 5 программу, потом останавливаю и смотрю в отладчике значение частоты. Каждый раз разное... Но обнадеживает, что попадает точное значение. Эх...
|
|
|
|
09.04.2009, 16:04
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
Хм...ну так... программный фнч, по - бедности...
считаем сумму предыдущего измерения с текущим, делим на 2, кидаем в массив и общую сумму делим на количество элементов массива. Хотя извращение, согласен...
|
|
|
|
09.04.2009, 16:27
|
|
Гражданин KAZUS.RU
Регистрация: 08.07.2006
Сообщений: 886
Сказал спасибо: 119
Сказали Спасибо 1,110 раз(а) в 177 сообщении(ях)
|
Цитата:
|
Про вывод - сейчас убираю вывод, запускаю с помощью шайбы секунд на 5 программу, потом останавливаю и смотрю в отладчике значение частоты. Каждый раз разное... Но обнадеживает, что попадает точное значение. Эх...
|
Усредняйте, выводите и будет вам счастье. Да, и еще. На момент измерения запрещайте все прерывания - иначе будет появляться погрешность.
|
|
|
|
09.04.2009, 16:54
|
|
Частый гость
Регистрация: 07.04.2009
Сообщений: 16
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Сообщение от urry
|
Хм...ну так... программный фнч, по - бедности...
считаем сумму предыдущего измерения с текущим, делим на 2, кидаем в массив и общую сумму делим на количество элементов массива. Хотя извращение, согласен...
|
Когда проект горит на что только не готов пойти, не то что там программный фнч. Но если значения отличаются на порядок, то вообщем-то он мало поможет...
|
|
|
|
09.04.2009, 17:01
|
|
Частый гость
Регистрация: 07.04.2009
Сообщений: 16
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Сообщение от alexgap
|
Цитата:
|
Про вывод - сейчас убираю вывод, запускаю с помощью шайбы секунд на 5 программу, потом останавливаю и смотрю в отладчике значение частоты. Каждый раз разное... Но обнадеживает, что попадает точное значение. Эх...
|
Усредняйте, выводите и будет вам счастье. Да, и еще. На момент измерения запрещайте все прерывания - иначе будет появляться погрешность.
|
Хочу счастья, не могу понять откуда берется погрешность. Смотрите, вот код:
Код:
|
while(1)
{
for (i = 0; i ‹ N; i++)
{
if (CMCONbits.C1EVT == 1) //- Компаратор сработал
{
delay(100);
CMCONbits.C1EVT = 0; //- Сброс флага компаратора
if ((CMCONbits.C1OUT == 1)) // Если компаратор сработал вверх
{
CVRCON = 0x00C7; // Смена опоры
T2CONbits.TON = 0; // Остановка 32 битного таймера счета
tic = TMR3; // Переносим значение 32 битного таймера в tic
tic ‹‹= 16;
tic |= TMR2;
f = 4000000.0/tic; // Находим частоту
TMR2 = 0; TMR3 = 0; // Обнуляем таймер
T2CONbits.TON = 1; // Запуск 32 битного таймера счета
mas_f[i] = f;
}
else if ((CMCONbits.C1OUT == 0)) // Если компаратор сработал вниз
{
CVRCON = 0x00CF; // Смена опоры
}
}
}
j = 0; // Блок усреднения
avg_f = 0;
for (i = 0; i ‹ N; i++)
{
if (mas_f[i] != 0)
{
j++;
avg_f += mas_f[i];
}
}
avg_f /= j;
} |
Вообщем опрашиваем компаратор N раз, каждый раз записываем измеренное значение в mas_f[], после N раз усредняем. Внимание вопрос, почему если, например, измеряем частоту 35 Гц, то без блока усреднения (просто закомментируем его) в массиве mas_f значения с точностью 0,1 Гц и стабильные показания, а если включить блок усреднения погрешность 0,5 Гц и более + нестабильные показания. Ведь усреднение идет уже после измерения. никак не могу понять природу этого явления....
|
|
|
|
09.04.2009, 21:06
|
|
Гражданин KAZUS.RU
Регистрация: 08.07.2006
Сообщений: 886
Сказал спасибо: 119
Сказали Спасибо 1,110 раз(а) в 177 сообщении(ях)
|
Цитата:
|
Внимание вопрос, почему если, например, измеряем частоту 35 Гц, то без блока усреднения (просто закомментируем его) в массиве mas_f значения с точностью 0,1 Гц и стабильные показания, а если включить блок усреднения погрешность 0,5 Гц и более + нестабильные показания. Ведь усреднение идет уже после измерения. никак не могу понять природу этого явления....
|
Элементарно, Ватсон. Самый первый элемент массива mas_f[0] вносит погрешность, так как таймер был либо не запущен, либо хранил старое значение, либо все что угодно. Точные измерения начинают происходить только со второго раза, когда взаимодействие таймера и алгоритма стабилизируется.
Поэтому когда будете усреднять, то не учитывайте первый элемент массива, начинайте со второго.
Код:
|
j = 0; // Блок усреднения
avg_f = 0;
for (i = 1; i ‹ N; i++)
{
if (mas_f[i] != 0)
{
j++;
avg_f += mas_f[i];
}
}
avg_f /= j; |
Обратите внимание, что i = 1 в обьявлении цикла for.
Удачи!
|
|
|
|
10.04.2009, 04:07
|
|
Временная регистрация
Регистрация: 31.01.2005
Адрес: Киев
Сообщений: 78
Сказал спасибо: 0
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
|
глупый децкий вопрос «на всякий случай»: а питание и земля вообще корректно разведены? В особенности AVss?
Всякие там керамические кондёры в непосредственной близости от ножек; дроссельки, если входной сигнал имеет большой размах и может коррелировать с питанием dsPIC`а (AVcc в особенности)...
|
|
|
|
10.04.2009, 07:45
|
|
Гражданин KAZUS.RU
Регистрация: 08.07.2006
Сообщений: 886
Сказал спасибо: 119
Сказали Спасибо 1,110 раз(а) в 177 сообщении(ях)
|
Код:
|
f = 4000000.0/tic; // Находим частоту |
Эта строчка может иметь неопределенное время исполнения. Я не знаю, есть ли в dsPIC операции аппаратного деления, но в большинстве контроллеров их нет.
Под неопределенным временем я подразумеваю, что исполнение операции может занять продолжительное время и сильно зависит от значений входных аргументов.
Для повышения точности измерений лучше вынести деление из цикла измерения в цикл усреднения.
Добивайтесь точных измерений на малой частоте, затем когда добьетесь успеха, повышайте частоту.
|
|
|
|
10.04.2009, 17:08
|
|
Частый гость
Регистрация: 07.04.2009
Сообщений: 16
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Сообщение от gavrik254
|
глупый децкий вопрос «на всякий случай»: а питание и земля вообще корректно разведены? В особенности AVss?
Всякие там керамические кондёры в непосредственной близости от ножек; дроссельки, если входной сигнал имеет большой размах и может коррелировать с питанием dsPIC`а (AVcc в особенности)...
|
Дроссельков нет, а кондер стоит между AVdd и AVss, достаточно близко. Сигнал входной почти от 0 до 3,3 В, т.е. AVdd и питание dsPIC одного порядка.
Сообщение от alexgap
|
Код:
|
f = 4000000.0/tic; // Находим частоту |
Эта строчка может иметь неопределенное время исполнения. Я не знаю, есть ли в dsPIC операции аппаратного деления, но в большинстве контроллеров их нет.
Под неопределенным временем я подразумеваю, что исполнение операции может занять продолжительное время и сильно зависит от значений входных аргументов.
Для повышения точности измерений лучше вынести деление из цикла измерения в цикл усреднения.
Добивайтесь точных измерений на малой частоте, затем когда добьетесь успеха, повышайте частоту.
|
Хочу Вам сказать отдельное спасибо, Выши советы очень помогают, находит просветление и лучшее понимание проблемы. Большинство моих бед от того, что компаратор не стабилен, сейчас добился точности в 0,1 Гц путем ввода прерывания компаратора + в прерывании задержка порядка 0,3 мс + смена порога:
Код:
|
void __attribute__ ((interrupt, auto_psv)) _CMPInterrupt(void)
{
delay(1000);
if (CMCONbits.C1OUT == 1)
{
if (FLAG_CMP == 0)
{
TMR2 = 0;
TMR3 = 0;
T2CONbits.TON = 1;
FLAG_CMP = 1;
}
else
{
T2CONbits.TON = 0;
tic = TMR3;
tic ‹‹= 16;
tic |= TMR2;
FLAG_CMP = 0;
FLAG_TIMER = 1;
}
CVRCON = 0x0087;
}
else if (CMCONbits.C1OUT == 0)
{
CVRCON = 0x008F;
}
_CMIF = 0;
} |
Но опять таки меряю по сути период, усредняю, вывожу. Т.к. надо измерять частоты от 2 Гц, то на низких медленно достаточно, особенно если учесть, что я усредняю, чтобы не прыгало на высоких частотах. Со следующей недели буду реализовывать метод с досчетом.
|
|
|
|
11.04.2009, 05:25
|
|
Прохожий
Регистрация: 11.04.2009
Сообщений: 1
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Сообщение от gavrik254
|
глупый децкий вопрос «на всякий случай»: а питание и земля вообще корректно разведены? В особенности AVss?
Всякие там керамические кондёры в непосредственной близости от ножек; дроссельки, если входной сигнал имеет большой размах и может коррелировать с питанием dsPIC`а (AVcc в особенности)...
|
Совершенно не глупый. Но!!!
Сталкивался с подобной проблемой. Ноги растут из помех по Vref. Лечится легко... Подключаешь Vref к ноге, а между ногой и GND емкости 0,1uF достаточно.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 19:04.
|
|