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

 
 
Wantcan
сообщение Jan 10 2009, 05:35
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 11-12-08
Из: Earth
Пользователь №: 42 366



Подскажите хороший алгоритм для усреднения вычислений АЦП,я сделал так-
Код
// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input){
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;}

while (1){....

   ta++;if(ta==21)ta=0;
   tempADC=(read_adc(0)/5);
   tempADC1=tempADC+(read_adc(0)/5);                  
   if(ta==20)temp=tempADC1/2;tempADC=0;tempADC1=0;
т.е. показывать на индикаторе среднее число из 20 вычислений,но все равно не так сглаженно получается.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
rvk
сообщение Jan 10 2009, 05:57
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 165
Регистрация: 13-05-06
Из: Камышин
Пользователь №: 17 067



Конечно не сглаженно, потому что Вы сняв двадцать значений стираете и начинаете набирать по новой.
И кстати складываете Вы двадцать значений, а делите только на два. Если это такая фишка, чтобы результат в итоге умножить на два,
тогда понятно.
И деление на 5 я провожу в самом конце, всего один раз над переменной temp. Это сделает более точными вычисления.

Поэтому у Вас есть усреднение не скользящее, а среднее на каждые отдельно взятые двадцать значений. Простой способ сделать скользящее, это вычитать самое раннее и прибавлять последнее. Но при этом обязательно накопится ошибка вычислений. Продвинутый способ, как писал в другой ветке resident, это хранить все двадцать последних значений в массиве, и делать среднее по нему, примерно вот так:
unsigned char tempData[20];
unsigned char ta=0;
unsigned char i;
unsigend short temp;

while (1){....

ta++;if(ta==20) ta=0;
tempData[ta]=read_adc(0);// деление на 5 перенесено в расчет temp

temp = 0;
for(i=0;i<20;i++){
temp += tempData[i];
}
temp =temp/100; // 20*5

}

В этом случае, переменная temp будет содержать усреднение последних снятых двадцати значений, и обновляться будет
при каждом чтении АЦП.

Сообщение отредактировал rvk - Jan 10 2009, 06:04
Go to the top of the page
 
+Quote Post
Demeny
сообщение Jan 10 2009, 18:33
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



Цитата(rvk @ Jan 10 2009, 08:57) *
Продвинутый способ, как писал в другой ветке resident, это хранить все двадцать последних значений в массиве, и делать среднее по нему, примерно вот так:
...........

Для усреднения по последним 20 значениям совсем необязательно хранить последние 20 значений в массиве, зачем расходовать память и ресурсы процессора, чтобы их каждый раз суммировать. А если нужно будет усреднять по 10000 значений ?
Вот простой способ получать усреднённое значение каждый раз при получении текущего измеренного значения:
Код
T_average = T_average + (T_current - T_average) / 20.0

где T_average - среднее значение на данный момент времени, T_current - мгновенное измеренное значение, снятое, например, с АЦП в текущий момент времени.
Этот пример НЧ-фильтра измерений практически эквивалентен усреднению последних 20 значений. Однако здесь число усреднений (20) необязательно может быть целым значением. Вообще говоря, в этой формуле число 20.0 является постоянной времени фильтра, которая вкупе с периодом измерений определяет скорость реакции (инертность) этого фильтра на резкие изменения входных измеряемых величин.


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 10 2009, 18:55
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Demeny @ Jan 10 2009, 23:33) *
Этот пример НЧ-фильтра измерений практически эквивалентен усреднению последних 20 значений.
Вообще-то это пример фильтра EMA (экспоненциальное скользящее среднее), а не SMA (простое скользящее среднее). В общем виде EMA выглядит как рекурсия Y(i+1)=Y(i)+(X(i)–Y(i))*K, где K=2/(N+1), Y(i+1) выходное значение фильтра, Y(i) - предыдущее выходное значение фильтра, X(i) - значение текущего отсчета. N имеет тот же смысл, что и "тау" RC-цепочки. Отличие EMA от SMA еще в том, что EMA это фильтр с БИХ, а SMA - с КИХ.
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 11 2009, 07:53
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(rezident @ Jan 10 2009, 21:55) *
Вообще-то это пример фильтра EMA (экспоненциальное скользящее среднее), а не SMA (простое скользящее среднее). В общем виде EMA выглядит как рекурсия Y(i+1)=Y(i)+(X(i)–Y(i))*K, где K=2/(N+1), Y(i+1) выходное значение фильтра, Y(i) - предыдущее выходное значение фильтра, X(i) - значение текущего отсчета. N имеет тот же смысл, что и "тау" RC-цепочки.

Смысл может и тот же, а насчет численного значения я сильно сомневаюсь. Чтобы получить фильтр с постоянной времени tau, коэффициент вычисляется по формуле K = 1 - exp(-T/tau), где T - период следования входных отсчетов.
Go to the top of the page
 
+Quote Post
Microwatt
сообщение Jan 11 2009, 09:03
Сообщение #6


Гуру
******

Группа: Почетный участник
Сообщений: 6 851
Регистрация: 25-08-08
Из: Запорожье
Пользователь №: 39 802



Цитата(777777 @ Jan 11 2009, 11:53) *
Смысл может и тот же, а насчет численного значения я сильно сомневаюсь. Чтобы получить фильтр с постоянной времени tau, коэффициент вычисляется по формуле K = 1 - exp(-T/tau), где T - период следования входных отсчетов.

Вот то-то и оно. Знания и вера входят в конфликт.
Инженер, чтобы устранить мигание цифр на индикаторе, возьмет среднее арифметическое от 2-4 измерений. Или даже в АЦП что-нибудь из двух компонентов придумает.
Программист, ничтоже сумняшеся, будет брать экспоненту. При сем потребуется мощный процессор, плавающая запятая, дополнительные килобайты памяти, цикл решения задачи вырастет... Но он же за это не платит.
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 11 2009, 11:28
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Microwatt @ Jan 11 2009, 12:03) *
Инженер, чтобы устранить мигание цифр на индикаторе, возьмет среднее арифметическое от 2-4 измерений. Или даже в АЦП что-нибудь из двух компонентов придумает.
Программист, ничтоже сумняшеся, будет брать экспоненту. При сем потребуется мощный процессор, плавающая запятая, дополнительные килобайты памяти, цикл решения задачи вырастет... Но он же за это не платит.

Во-первых, вашему "инженеру" для устранения мигания цифр нужно, как я уже писал здесь, не прикрывать свое дерьмо усреднением, а устранять его, потому что если он не в состоянии получить без помех 10 разрядов, то какой он нахрен инженер - самый дешевый китайский мультиметр дает точность в два раза большую.

А во-вторых, если шум имеется в самом сигнале и его надо устранять, то имейте в виду, что цифровая фильтрация - наука несколько более сложная, нежели вычисление среднего арифметического. Для начала надо исследовать характер помех - они могут оказаться не шумовыми, а например, в сигнале могут наблюдаться скачки в одну сторну - такое часто встречается если помеха идет по земле от мощных потребителей. Тогда никаким усреднением вы эту помеху не устраните, а если устраните, то получите неправильный результат. Если помеха действительно представляет собой шумовой сигнал, то небходимо оценить ее спектр - если его частота сравнима со спектром полезного сигнала, то фильтровать ее также бесполезно. Наконец, если частота помехи существенно выше - нужно посмотреть насколько отличаются часоты сигнала и помехи и насколько отличаются их амплитуды и оценить необходимую крутизну характеристики фильтра для гарантированного подавления помехи и, следовательно, его порядок.

Что же касается фильтра T_ave += (T_in - T_ave) / K то для него не требуется никакой плавающей точки - он работает c целыми переменными практически в таком виде как я здесь написал. Если же вы имеете в виду экспоненту для для вычисления K, то она вычисляется один раз на калькуляторе, а если она является степенью двойки, то не требуется даже деления, можно обойтись сдвигами. А дополнительные килобайты нужны как раз при вычислении среднего арифметического - в данном случае кроме текущего и предыдущего отсчетов хранить ничего не требуется.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Wantcan   Усреднение вычислений АЦП   Jan 10 2009, 05:35
||- - Demeny   Цитата(rezident @ Jan 10 2009, 21:55) Воо...   Jan 10 2009, 19:42
|||- - rezident   Цитата(Demeny @ Jan 11 2009, 00:42) Конеч...   Jan 10 2009, 20:26
|||- - Demeny   Цитата(rezident @ Jan 10 2009, 23:26) Да ...   Jan 11 2009, 07:46
|||- - rezident   Цитата(Demeny @ Jan 11 2009, 12:46) Кстат...   Jan 11 2009, 17:04
|||- - Tanya   Цитата(rezident @ Jan 11 2009, 20:04) Для...   Jan 12 2009, 08:02
|||- - 777777   Цитата(rezident @ Jan 11 2009, 20:04) Дей...   Jan 12 2009, 12:44
|||- - demiurg_spb   Цитата(rezident @ Jan 11 2009, 20:04) Для...   Jan 16 2009, 16:04
|- - rvk   Цитата(Demeny @ Jan 10 2009, 21:33) Вот п...   Jan 10 2009, 19:02
- - Wantcan   ЦитатаИ кстати складываете Вы двадцать значений, а...   Jan 10 2009, 06:12
- - rvk   Ну используйте вместо for вложенный цикл while: t...   Jan 10 2009, 06:19
- - Alex11   Есть еще один способ получить скользящее среднее. ...   Jan 10 2009, 09:27
|- - Herz   Цитата(Alex11 @ Jan 10 2009, 11:27) Есть ...   Jan 10 2009, 11:20
- - Wantcan   С последним способом у меня не получилось-цифры ск...   Jan 10 2009, 10:52
- - rvk   Не забывайте только про переполнение temp. Если зн...   Jan 10 2009, 11:23
|- - rezident   Цитата(rvk @ Jan 10 2009, 16:23) Чтобы с ...   Jan 10 2009, 11:34
- - 777777   Цитата(Wantcan @ Jan 10 2009, 08:35) Подс...   Jan 11 2009, 07:46
- - Wantcan   Спасибо за все ответы,на этой неделе не будет врем...   Jan 11 2009, 16:59
- - Папа Карло   Возник вопрос по формуле T_average = T_average + (...   Jan 21 2009, 15:16
|- - 777777   Цитата(Папа Карло @ Jan 21 2009, 18:16) В...   Jan 21 2009, 16:05
|- - Палыч   Цитата(777777 @ Jan 21 2009, 19:05) T_ave...   Feb 13 2009, 07:09
|- - 777777   Цитата(Палыч @ Feb 13 2009, 10:09) Вот, и...   Feb 13 2009, 11:55
|- - Палыч   Цитата(777777 @ Feb 13 2009, 14:55) Получ...   Feb 13 2009, 12:59
|- - 777777   Цитата(Палыч @ Feb 13 2009, 15:59) Матема...   Feb 14 2009, 11:18
|- - ReAl   Цитата(777777 @ Feb 14 2009, 13:18) Тогда...   Feb 14 2009, 15:07
- - haker_fox   Хочу сказать, что для фильтрации данных с АЦП прим...   Jan 23 2009, 15:38
- - Wantcan   haker_fox, прошу тнуть пальцем в то место форума,о...   Feb 12 2009, 17:53
|- - 777777   Цитата(Wantcan @ Feb 12 2009, 20:53) hake...   Feb 13 2009, 06:15
|- - blackfin   Цитата(777777 @ Feb 13 2009, 09:15) То ес...   Feb 13 2009, 06:26
|- - Tanya   Цитата(blackfin @ Feb 13 2009, 09:26) Так...   Feb 13 2009, 07:05
|- - 777777   Цитата(blackfin @ Feb 13 2009, 09:26) Так...   Feb 13 2009, 11:40
|- - blackfin   Цитата(777777 @ Feb 13 2009, 14:40) Да, н...   Feb 13 2009, 11:46
- - xemul   Цитата(Палыч @ Feb 13 2009, 15:59) ... По...   Feb 13 2009, 14:08
- - Wantcan   Пожалуйста,помогите переделать найденный на этом ф...   Mar 2 2009, 16:57
- - Wantcan   Остановился на таком варианте Код ta++; if(ta=...   Mar 16 2009, 11:10
- - Флюктуация ваккума   Нужно создать в оперативной памяти закольцованный ...   Aug 15 2015, 12:22
- - Bronislav   Такой вариант не подойдет? for(i=0;i<20;i++) ...   Sep 4 2015, 06:15


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

 


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


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