А вот тут нужен гистерезис на полразряда.
Алгоритм сглаживания шумов АЦП микроконтроллера.
[uquote="Alex_641",url="/forum/viewtopic.php?p=4367545#p4367545"]Показания ИНОГДА прыгают в пределах единицы младшего разряда, и если число ровное например 100 , то прыгают соответственно все 3 его разряда.[/uquote]
А вот тут нужен гистерезис на полразряда.
А вот тут нужен гистерезис на полразряда.
- Реклама
- Сообщения: 2314
- Зарегистрирован: Вт янв 26, 2021 22:33:21
Ну ... жду алгоритм реализации.
Не спрашивай по ком звонит колокол, он звонит по тебе !
Алгоритм очень простой. Переключение на следующее значение в одну сторону происходит на полразряда позже, чем в другую. Для этого нужно сделать экспоненциальный фильтр сглаживания с коэффициентом 0,5. Это даст на выходе один лишний разряд после точки. Он позволит получить разрешение в 0,5 единицы измерений. Когда текущее измерение больше предыдущего на 0,5 - прибавляем единицу, если меньше на такую же величину - вычитаем единицу. Если внутри этих значений - не изменяем.
- Сообщения: 2314
- Зарегистрирован: Вт янв 26, 2021 22:33:21
А где взять "пол разряда" то ? был бы 11 бит в ацп, а его нет.
Не спрашивай по ком звонит колокол, он звонит по тебе !
[uquote="Alex_641",url="/forum/viewtopic.php?p=4367568#p4367568"]А где[/uquote]
Я же вам сказал - экспоненциальный фильтр сглаживания S[t+1]=((1-β)*S[t])+A[t+1] c коэффициентом β=0,5.
S[t+1]=(0,5*S[t])+A[t+1], где:
S[t+1] - текущее значение фильтра в формате 15.1
S[t] - предыдущее значение фильтра в формате 15.1
A[t+1] - текущее измерение uint16_t (10 значащих разрядов)
Таким образом, разрядность фильтра больше на 1 разрядности измерений. Лишний младший разряд - это дробная часть числа. 1 в нем означает 0,5 в десятичном формате. Например десятичное число 10,5 в двоичном виде (uint16_t) будет 000000000001010.1
Если выбрать коэффициент 0,25 - формула примет вид S[t+1]=(0,75*S[t])+A[t+1], то получите два дробных разряда в формате 14.2. Число 5,25 будет выглядеть как 00000000000101.01.
Это и есть фикспойнты.
Умножение на 0,5 - это арифметический сдвиг на один разряд вправо.
Умножение на 0,25 - это арифметический сдвиг на два разряда вправо.
Умножение на 0,75 - это сумма двух предыдущих значений.
ЗЫ. И учтите, как и любой рекурсивный фильтр, этот в целых числах НЕ РАБОТАЕТ. В целых числах фильтр не будет реагировать на входные значения разрядностью меньше дробной. Поэтому фикспойнты или флоаты обязательны.
Я же вам сказал - экспоненциальный фильтр сглаживания S[t+1]=((1-β)*S[t])+A[t+1] c коэффициентом β=0,5.
S[t+1]=(0,5*S[t])+A[t+1], где:
S[t+1] - текущее значение фильтра в формате 15.1
S[t] - предыдущее значение фильтра в формате 15.1
A[t+1] - текущее измерение uint16_t (10 значащих разрядов)
Таким образом, разрядность фильтра больше на 1 разрядности измерений. Лишний младший разряд - это дробная часть числа. 1 в нем означает 0,5 в десятичном формате. Например десятичное число 10,5 в двоичном виде (uint16_t) будет 000000000001010.1
Если выбрать коэффициент 0,25 - формула примет вид S[t+1]=(0,75*S[t])+A[t+1], то получите два дробных разряда в формате 14.2. Число 5,25 будет выглядеть как 00000000000101.01.
Это и есть фикспойнты.
Умножение на 0,5 - это арифметический сдвиг на один разряд вправо.
Умножение на 0,25 - это арифметический сдвиг на два разряда вправо.
Умножение на 0,75 - это сумма двух предыдущих значений.
ЗЫ. И учтите, как и любой рекурсивный фильтр, этот в целых числах НЕ РАБОТАЕТ. В целых числах фильтр не будет реагировать на входные значения разрядностью меньше дробной. Поэтому фикспойнты или флоаты обязательны.
- Реклама
а разве A[t+1] не нужно сдвигать влево на 1 разряд (или 2 разряда)?КРАМ писал(а):A[t+1] - текущее измерение uint16_t (10 значащих разрядов)
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
[uquote="Starichok51",url="/forum/viewtopic.php?p=4367799#p4367799"]а разве A[t+1] не нужно ?[/uquote]
Категорически нет. Это приведет выражение к целочисленной форме и входящие значения меньше 2 или 4 будут игнорироваться. Мы получим мертвую зону входных сигналов. Ну и не получим дробную часть у фильтра.
Просто нужно понимать, что входящие значения с АЦП уже приведены к формату фильтра. Их сдвигать не требуется.
Категорически нет. Это приведет выражение к целочисленной форме и входящие значения меньше 2 или 4 будут игнорироваться. Мы получим мертвую зону входных сигналов. Ну и не получим дробную часть у фильтра.
Просто нужно понимать, что входящие значения с АЦП уже приведены к формату фильтра. Их сдвигать не требуется.
если использовать тип флот, то сдвигать, конешно, не нужно.
а если использовать фиксированную точку, то как получится младший разряд в формате 15.1 без сдвига?
я так понимаю, что при фиксированной точке произведение 0,5*S[t] будет целым числом, и с этой "половинкой" в младшем разряде результат измерения нужно сдвинуть (удвоить).
или ты фиксированную точку понимаешь не так, как я?
а если использовать фиксированную точку, то как получится младший разряд в формате 15.1 без сдвига?
я так понимаю, что при фиксированной точке произведение 0,5*S[t] будет целым числом, и с этой "половинкой" в младшем разряде результат измерения нужно сдвинуть (удвоить).
или ты фиксированную точку понимаешь не так, как я?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
[uquote="Starichok51",url="/forum/viewtopic.php?p=4367918#p4367918"]если использовать тип флот, то сдвигать, конешно, не нужно.[/uquote]
Тип float позволяет использовать каноническую форму такого фильтра вида:
S[t+1]=(α*S[t])+(β*A[t+1]), где α+β=1.
Но есть один нюанс. При α+β>1 фильтр перестает быть устойчивым. А использование float не гарантирует, что это условие не возникнет из-за нелинейного разрешения float.
Поэтому с float придется вручную вычислить α=1-β, затем проверить, что сумма α+β МЕНЬШЕ единицы (равна она не может быть по определению) и при вычислениях использовать первичную каноническую форму с двумя коэффициентами.
[uquote="Starichok51",url="/forum/viewtopic.php?p=4367918#p4367918"]я так понимаю, что при фиксированной точке произведение 0,5*S[t] будет целым числом[/uquote]
Нет, не будет. Все числа в приведенной мной в предыдущих сообщениях формуле ДРОБНЫЕ и имеют ОДИНАКОВЫЙ ФОРМАТ. Просто при таком формате данные с АЦП УЖЕ ПРЕДСТАВЛЕНЫ КАК ДРОБНЫЕ формата 15.1
То есть умножение на 0,5 не делает число целым, оно просто делит его пополам, СОХРАНЯЯ РАЗРЯДНОСТИ ЦЕЛОЙ И ДРОБНОЙ ЧАСТИ.
И не следует путать вычисления самого фильтра с приведением РЕЗУЛЬТАТА фильтрации к целому (отсечение дробной части) для целей вывода. Формально это выглядит тоже как деление на 2, но суть становится совершенно другой. И, кстати, по правилам математического округления такое приведение должно быть выполнено с предварительным увеличением результата фильтрации на 0,5 для положительных чисел и вычитанием 0,5 для отрицательных.
Тип float позволяет использовать каноническую форму такого фильтра вида:
S[t+1]=(α*S[t])+(β*A[t+1]), где α+β=1.
Но есть один нюанс. При α+β>1 фильтр перестает быть устойчивым. А использование float не гарантирует, что это условие не возникнет из-за нелинейного разрешения float.
Поэтому с float придется вручную вычислить α=1-β, затем проверить, что сумма α+β МЕНЬШЕ единицы (равна она не может быть по определению) и при вычислениях использовать первичную каноническую форму с двумя коэффициентами.
[uquote="Starichok51",url="/forum/viewtopic.php?p=4367918#p4367918"]я так понимаю, что при фиксированной точке произведение 0,5*S[t] будет целым числом[/uquote]
Нет, не будет. Все числа в приведенной мной в предыдущих сообщениях формуле ДРОБНЫЕ и имеют ОДИНАКОВЫЙ ФОРМАТ. Просто при таком формате данные с АЦП УЖЕ ПРЕДСТАВЛЕНЫ КАК ДРОБНЫЕ формата 15.1
То есть умножение на 0,5 не делает число целым, оно просто делит его пополам, СОХРАНЯЯ РАЗРЯДНОСТИ ЦЕЛОЙ И ДРОБНОЙ ЧАСТИ.
И не следует путать вычисления самого фильтра с приведением РЕЗУЛЬТАТА фильтрации к целому (отсечение дробной части) для целей вывода. Формально это выглядит тоже как деление на 2, но суть становится совершенно другой. И, кстати, по правилам математического округления такое приведение должно быть выполнено с предварительным увеличением результата фильтрации на 0,5 для положительных чисел и вычитанием 0,5 для отрицательных.
понятно.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
- Сообщения: 2314
- Зарегистрирован: Вт янв 26, 2021 22:33:21
Я так понял , не надо искать среднее арефметическое. Надо найти количество показаний отличающихся на единицу в предыдущем цикле, и в данном . И если есть разница на единицу АЦП , то просто выводить старую информацию. Это проще чем ...всё что написано выше "умными людьми" , которые так и не смогли привести пример )))
Не спрашивай по ком звонит колокол, он звонит по тебе !
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Alex_ka перелогинься.
[uquote="Alex_641",url="/forum/viewtopic.php?p=4369415#p4369415"]Это проще чем ...всё что написано выше "умными людьми" , которые так и не смогли привести пример )))[/uquote]
Вы не в состоянии написать простейший код по несложной формуле?
Так много разговоров было о медиане и так все проблематично с самым простым фильтром сглаживания...
Кстати, чтобы исключить нечитаемое дрожание показаний можно не гистерезисом озаботиться, а простым увеличением интервала вывода показаний.
Самым лучшим вариантом будет тот же экспоненциальный фильтр, только с коэффициентом 0,125 или 0,0625. Будет комфортное "резиновое" отображение - плавное (например за 0,5...1 сек) нарастание/падение показаний и практически незаметное глазу переключение на границе значений.
Гистерезис на единице младшего разряда даст потерю минимум одного младшего разряда.
Фильтр для коэффициента 0,0625:
Где:
Расчет делается на каждое преобразование АЦП.
Вы не в состоянии написать простейший код по несложной формуле?
Так много разговоров было о медиане и так все проблематично с самым простым фильтром сглаживания...
Кстати, чтобы исключить нечитаемое дрожание показаний можно не гистерезисом озаботиться, а простым увеличением интервала вывода показаний.
Самым лучшим вариантом будет тот же экспоненциальный фильтр, только с коэффициентом 0,125 или 0,0625. Будет комфортное "резиновое" отображение - плавное (например за 0,5...1 сек) нарастание/падение показаний и практически незаметное глазу переключение на границе значений.
Гистерезис на единице младшего разряда даст потерю минимум одного младшего разряда.
Фильтр для коэффициента 0,0625:
Код: Выделить всё
S_IIR=S_IIR-(S_IIR>>4)+resultADC; // S[t+1]=((1-β)*S[t])+A[t+1], где β=0,0625=1/16
outputResult=(S_IIR+8)>>4; // округление и приведение к целому
Код: Выделить всё
uint16_t S_IIR; //тело фильтра (максимум 14 значащих разрядов)
uint16_t resultADC; // результат преобразования АЦП (10 разрядов)
uint16_t outputResult; // выводимый результат фильтрации (10 разрядов)- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Если я не ошибаюсь, ТС, возможно, персонаж, мелькавший под ником alex_ka. Тот товарищ не совсем в теме. Финансы. Электроника хобби, не более того. Ключевое слово "умные". Как тот товарищ сам признался, очень уж любит покомпостировать мозги участникам форума.
Я к чему. Неважно, клон или с похожим отношением к участникам форума. Отныне придется десять раз подумать
Отвечать на вопросы или нет...
Я к чему. Неважно, клон или с похожим отношением к участникам форума. Отныне придется десять раз подумать
Отвечать на вопросы или нет...
Такая реализация экспоненциального фильтра тоже имеет подводные камни. Например, если сначала resultADC было 5, затем стало 3.
outputResult в этом случае устаканивается на 4.
https://ideone.com/FkALck
outputResult в этом случае устаканивается на 4.
https://ideone.com/FkALck
mont-oriol, а кто тебе сказал, что вывод на экран будет сделан ровно через две итерации?
КРАМ, я проанализировал и простимулировал экспоненциальный фильтр по твоей формуле.
и сейчас реализовал в одном своем изделии такой фильтр именно с коэффициентом 0,0625 (1/16).
сделано на ассемблере в целых числах, без типа флот.
до этого у меня там было среднее из суммы 256 измерений.
а симуляция с 0,0625 показала, что установившийся результат с максимальным числом 1023 получается через 140 итераций. и чем меньше число, тем быстрее результат устаканивается.
КРАМ, я проанализировал и простимулировал экспоненциальный фильтр по твоей формуле.
и сейчас реализовал в одном своем изделии такой фильтр именно с коэффициентом 0,0625 (1/16).
сделано на ассемблере в целых числах, без типа флот.
до этого у меня там было среднее из суммы 256 измерений.
а симуляция с 0,0625 показала, что установившийся результат с максимальным числом 1023 получается через 140 итераций. и чем меньше число, тем быстрее результат устаканивается.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Какие две итерации? В моём примере по ссылке их по 50.
[uquote="mont-oriol",url="/forum/viewtopic.php?p=4369698#p4369698"]Такая реализация экспоненциального фильтра тоже имеет подводные камни. Например, если сначала resultADC было 5, затем стало 3.
outputResult в этом случае устаканивается на 4.[/uquote]
Это результат округления.
Можно уменьшить смещение округления.
outputResult в этом случае устаканивается на 4.[/uquote]
Это результат округления.
Можно уменьшить смещение округления.
- Сообщения: 2314
- Зарегистрирован: Вт янв 26, 2021 22:33:21
Написать код не проблема. Я не нашёл "несложных формул".КРАМ писал(а):Вы не в состоянии написать простейший код по несложной формуле?
Добавлено after 2 minutes 23 seconds:
Ошибаешься. Я не менял ник с момента регистрации.Demiurg писал(а):Если я не ошибаюсь
Не спрашивай по ком звонит колокол, он звонит по тебе !
вот эти две:mont-oriol писал(а):Какие две итерации?
mont-oriol писал(а):Например, если сначала resultADC было 5, затем стало 3.
outputResult в этом случае устаканивается на 4.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.


