Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как внести иннерционность в измерение?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
hwdev
Есть измерительная система, измеряемый параметр имеет свойство "дрожать" около динамически меняющейся средней точки. Т.е. например значение параметра начинает нарастать, но нарастание это происходит "шаг вперед и 2 назад, потом наоборот". Или остановится около какого-то значения и давай болтаться.

Я хочу внести инерционность с некой регулируемой постоянной времени, чтобы настроить, как мне нужно. Дайте, пожалуйста, ссылку на теорию с примерами или сюда напишите готовый код.

Спасибо!
Deka
Про готовый код не скажу, но применяется такое например в электронных спидометрах. Какая-то разновидность усреднения... где-то видел на форуме. Попробуйте поиск.
Stanislav
Цитата(hwdev @ Dec 2 2008, 22:11) *
...Дайте, пожалуйста, ссылку на теорию с примерами или сюда напишите готовый код.
Спасибо!
Простейшая адаптивная система:

,

где - выходные отсчёты; - входные отсчёты (измерения); - константа адаптации.
rezident
В зависимости от наличия имеющихся ресурсов (ОЗУ) и равномерности отсчетов можно посоветовать простое скользящее среднее (SMA) или экспоненциальное (EMA). Про них даже в справке к MS Excel можно почитать.
hwdev
Цитата(Deka @ Dec 3 2008, 00:06) *
Про готовый код не скажу, но применяется такое например в электронных спидометрах. Какая-то разновидность усреднения... где-то видел на форуме. Попробуйте поиск.

Да, только у меня электронный тахометр. Дрожит зараза wacko.gif
Dog Pawlowa
Цитата(hwdev @ Dec 2 2008, 23:11) *
или сюда напишите готовый код.


Паскаль устроит?

Код
Function TempQuick(mVolt,K:integer):integer;

var LI:longint;
    Temp1:integer;
begin
//рассчитали
  Temp1:=....

//положили в буфер
  TempBuf[TempBufIndex]:=Temp1;

//изменили индекс
  Inc(TempBufIndex);
  If TempBufIndex>TempBufSize then
    begin
      TempBufIndex:=1;
      TempBufReady:=True;
    end;
//сложили буфер
  LI:=0;
  If TempBufReady then  EndIndex:=tempBufSize
                  else  EndIndex:=TempBufIndex-1;
  FOr MyBufIndex:=1 to EndIndex DO  LI:=LI + TempBuf[MyBufIndex];
  If LI<0 then LI:=0;
//поделили на количество элементов
  LI:=LI div EndIndex;
//вернули
  TempQuick:=Integer(LI);
end;
drovik
А что такое К в данном примере ? Или это какой-то доп параметр, "не имеющий отношения к делу" ? И не будет ли прыгать значение от того, что периодически (при сбросе индекса) за среднее значение берем только что измеренное ? Или я чего-то не догоняю ?
777777
Цитата(Stanislav @ Dec 3 2008, 00:17) *
Простейшая адаптивная система:

,

где - выходные отсчёты; - входные отсчёты (измерения); - константа адаптации.

А почему >0.5? Можно и меньше, нужно лишь, чтобы этот коэффициент был больше нуля.
В программе эта формула кодируется так:

y += (xn - y)*alpha;

правда, в этом случае альфа приобретает иной смысл - чем она меньше, тем сильнее сглаживание, при 1 сглаживание полностью отсутствует.

Можно даже вычслить этот коэффициент, если известна требуемая постоянная времени

,

где - период следования входных отсчётов; - требуемая постоянная фильтра в секундах. Эта формула реализует цифровой аналог RC-цепочки с постоянной времени ,
Stanislav
Цитата(777777 @ Dec 4 2008, 10:11) *
А почему >0.5? Можно и меньше, нужно лишь, чтобы этот коэффициент был больше нуля.
Чтобы было хоть какое-нить сглаживание.
Можно и меньше, но это не имеет смысла. Вообще, обычно выбирают в районе 0,9 и больше.

Цитата(777777 @ Dec 4 2008, 10:11) *
...В программе эта формула кодируется так:

y += (xn - y)*alpha;

правда, в этом случае альфа приобретает иной смысл - чем она меньше, тем сильнее сглаживание, при 1 сглаживание полностью отсутствует.
Ну да, то же самое.

Кстати, забыл написать.
Инициализировать адаптивную систему можно так:
,
т.е., выбрать в качестве начального приближения первый же входной отсчёт, а потом уже усреднять. Иначе долго ждать придётся. smile.gif
hwdev
Цитата(Stanislav @ Dec 4 2008, 10:42) *
Чтобы было хоть какое-нить сглаживание.
Можно и меньше, но это не имеет смысла. Вообще, обычно выбирают в районе 0,9 и больше.

Ну да, то же самое.

Кстати, забыл написать.
Инициализировать адаптивную систему можно так:
,
т.е., выбрать в качестве начального приближения первый же входной отсчёт, а потом уже усреднять. Иначе долго ждать придётся. smile.gif

Спасибо!
Буду применять. А как этот алгоритм переделать в целые числа? Алгоритм всё таки на контроллере будет крутиться, не пентиум smile.gif
rezident
Цитата(hwdev @ Dec 4 2008, 20:40) *
А как этот алгоритм переделать в целые числа? Алгоритм всё таки на контроллере будет крутиться, не пентиум smile.gif
Если коэффициент будет константой, а диапазон изменения параметра заранее известен, то дробный коэффициент можно представить как целое число домноженное на 2^N. После умножения достаточно будет арифметическими сдвигами на N разрядов вправо привести результат к правильному значению.
Stanislav
Цитата(rezident @ Dec 4 2008, 19:04) *
Если коэффициент будет константой, а диапазон изменения параметра заранее известен, то дробный коэффициент можно представить как целое число домноженное на 2^N. После умножения достаточно будет арифметическими сдвигами на N разрядов вправо привести результат к правильному значению.
Я бы ещё посоветовал использовать для накопления результата Yn арифметику повышенной (двойной) точности, чтобы не было потери разрядов при усечении (округлении).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.