Ардуино среднее значение измерений

Arduino.ru

Среднее значение в интервале

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Добрый день. Подскажите пожалуйста, и если можно то пример кода. Происходит измерение напряжения, но 1 значение 10В, 2 уже 3В, 3, 4. Измерения — стабилене(2.8в-3в). Хочется чтобы выводилось на экран, среднее значение, начиная к примеру с 3 по 10 измерение.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

вопрос не ясен, вам написать программу «среднего арифметического»?

upd раз 10 перечитал и не понял

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

А смысл таких вычислений? И что меряешь?

Может как в фигурном катании . самый большой и самый маленький результат отбрасывать, а с остальных среднеарифметическое?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Гуглите пословам «медианный фильтр». Там не среднее, но технику работы с интервалами подсмотрите.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

А смысл таких вычислений? И что меряешь?

Может как в фигурном катании . самый большой и самый маленький результат отбрасывать, а с остальных среднеарифметическое?

Не буду лукавить, все не много по другому. Но смысл тот же.

в мониторе порта получаем отображение измеряных величин. При запуске программы, приходит максимальное значение, оно нас не устраивает, надо отфильтровать. Вторым делом, надо взять последующие 10 измерений и вывести среднеарефметическое, исключая Min Max.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Чет мне кажется, что для извлечения мин-макс нужен массив всех измерений, а потом уже расчет среднего. Могу ошибаться, по математике тройка.((((

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

в мониторе порта получаем отображение измеряных величин. При запуске программы, приходит максимальное значение, оно нас не устраивает, надо отфильтровать. Вторым делом, надо взять последующие 10 измерений и вывести среднеарефметическое, исключая Min Max.

Ну, если все «немного по-другому» то

вариант 1 ) собираем измерения в массив, применяем функции min и max для поиска «крайних», считаем сумму массива без учета крайних и делим на кол-во (среднее арифметическое) (это если уверены в постановке задачи)

вариант 2) выясняем постоянные времени измеряемого сигнала, подбираем аппаратный фильтр, подбираем под сигнал програмный фильтр — их много и они разные. т.к. вы решили использовтаь среднее арифметическое — выполнив первую чать, выясним необходимое кол-во измерений и интервал опроса АЦП. Не рационально делать 10 измерений с минимальным интервалом на медленной функции и наоборот, для быстроменяющейся функции сигнала можно получить непонятно что. если измерить ШИМ прибором TRMS — амплитуду сигнала можно увидеть только при максимальном заполнении ШИМ — самая частая ошибка новичков тыкать неизвестно что, неизвестно куда и кричать у меня не работает.

Источник

Библиотека фильтров данных для Arduino

ОБНОВЛЕНИЯ

  • v1.6 от 12.11.2019
  • v1.7: исправлен GLinear
  • v1.8: небольшие улучшения
  • v2.0:
    • Улучшен и исправлен median и median3
    • Улучшен linear
    • Смотрите примеры! Использование этих фильтров чуть изменилось
  • v2.1: Исправлен расчёт дельты в линейном фильтре
  • v2.2: Исправлена ошибка компиляции
  • v3.0: Добавлен FastFilter и RingAverage

ТЕОРИЯ

Несколько фильтров подробно разобраны в этом уроке

БИБЛИОТЕКА

GyverFilters v3.0

GyverFilters – библиотека с некоторыми удобными фильтрами для Arduino

  • GFilterRA – компактная альтернатива фильтра экспоненциальное бегущее среднее (Running Average)
  • GMedian3 – быстрый медианный фильтр 3-го порядка (отсекает выбросы)
  • GMedian – медианный фильтр N-го порядка. Порядок настраивается в GyverFilters.h – MEDIAN_FILTER_SIZE
  • GABfilter – альфа-бета фильтр (разновидность Калмана для одномерного случая)
  • GKalman – упрощённый Калман для одномерного случая (на мой взгляд лучший из фильтров)
  • GLinear – линейная аппроксимация методом наименьших квадратов для двух массивов
  • FastFilter – быстрый целочисленный экспоненциальный фильтр
  • RingAverage – бегущее среднее с кольцевым буфером

Поддерживаемые платформы: все Arduino

Источник

Arduino.ru

Усреднение значений с потенциометра

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Мне нужно считать показания потенциометра и вывести в serial monitor.

Подключаем потенциометр к ардуино:

Не значительно меняем скетч из примеров

И получаем значения от 0 до 1023. С этим все понятно и все так работает.

Для практического применения этой конструкции мешает «дребезг» потенциметра (из-за низкого качества последнего в состоянии покоя значения могут немного изменяться — «скакать»).

Теперь вопрос. Как усреднить считывемые значения? Например, взять значения sensorValue за 10 циклов и посчитать среднее из них.

Головой понимаю, что нужно применить счетчик циклов, но вот не доходит, что вставить вместо вопросов :(

Может есть стандартное решение?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Думаю, для даннго случая и усреднения будет достаточно, но, если нужно, то могу поделится классом реализующий скользящий медианный фильтр. Он лучше работает когда есть редкие «большие выбросы в сторону». Фильтрация через среднее, хоть и сгладит «выброс», но все-таки почувствует его, а медиана, если «выброс» был кратковременным — вообще не заметит. Для потенциометра это не столь актуально, а вот для какого-нибудь ультразвукового дальномера. (для чего собственно и делал).

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

> Может есть стандартное решение?

Конечно есть. Вы его и описали. Только почему-то не захотели в коде реализовать

Вот это и будет «лобовое» усреднее. А то что дал Tomasina дал это «скользящие среднее». С практической точки зрение его решение — лучше:

— время затрачиваемое на получение «одного усредненнго замера» не зависит от количества замеров «для усредния»
— не нужно следить за тем, что avg_sum переполнится (в «лобовом варианте», если вы захотите усреднять по очень большому количеству, скажем не 10, а 1000 замеров делать — у вас вылезет переполнение и бред в результатах).

Минус его решения только один: чуть чуть сложнее для понимания «как оно работает».

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Минус его решения только один: чуть чуть сложнее для понимания «как оно работает».

Для честной реализации — надо еще и брать не 5 * old.value, а действительно «пять предыдущих результатов».

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Минус его решения только один: чуть чуть сложнее для понимания «как оно работает».

Для честной реализации — надо еще и брать не 5 * old.value, а действительно «пять предыдущих результатов».

Неа.. тут все «честно». С точки зрения математики это идентично. Вопрос только. Что мы храним, скажем [1,1,2,3,3] (и вычисляем его сумму) что мы храним [1,2,2,2,3], что мы храним old.value=2 — результат один и тот же

Разница может «вылезти», только за счет округления в int. Но, при небольших количествах «старых значений» — она будет не существенной, а при больших достаточно хранить старое сначение в чем-то типа double.

P.S. Я же говорил что «минус в том что чуть сложнее понимать» ;)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Подскажите, а какой смысл в формулу подставлять два одинаковых значения?

этой строкой мы же их уравниваем?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

> Подскажите, а какой смысл в формулу подставлять два одинаковых значения?

Ну, смыслов найти можно много. но скорее всего просто впопыхах человек чуток запутался в именах переменных.

Вот мой вариант «впопыхах», чуток подправленный, не проверял правда.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Опять мимо. первое значение будет в averageFactor (в нашем случае в 5 раз) меньше первого измеренного значения, а потом приближаться к нему по экспоненте. Если измеренное значение не будет меняться.

Имхо, надо первое измерение сделать перед loop<>, как-то.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Имхо, надо первое измерение сделать перед loop<>, как-то.

обычно в сетапе

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

>Имхо, надо первое измерение сделать перед loop<>, как-то.

Это уже зависит от конкретной задачи. Тут нет «правильно» или «не правильно». Начальный этап — это сугубо решение «автора». Волевое. Что считать «начальным состоянием». Если считать что «при выключенном контроллере показание сенсора ноль», то «разогрев датчика» — вполне правомерен и логичен. Если считать «при включении датчик СРАЗУ показывает правильное значение», то да. в setup() нужно впендюрить дополнительный sensorValue= analogRead(analogInPin);

Вообщем, что считать «началом соотворения мира, после подачи питания» — вопрос религии, а не логики :)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Всем ОГРОМНОЕ Спасибо! Даже не думал, что такой простой вопрос поднимет дискуссию. А до решения мне самому не хватило одного шага. Еще раз благодарю всех.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Да, мой косяк, возникший потому что этот пример собран из кусков большого проекта. Немного не в том порядке скопипастено. Правильно так: строку 17 из моего примера вставить после строки 13, т.е.

Это было выкинуто из примера, чтобы не запутывать понимание сути. Данная ситуация у меня реализована следующим образом: первые N показаний, пока они меньше коэффициента сглаживания , выводятся «как есть» и одновременно буферизуются, а как только число измерений превысит коэффициент, выводятся уже сглаженные показания. Таким образом, с момента подачи питания показания сразу отображаются реальными, просто первые N измерений более скачкообразны («дрейфуют»). В некоторых случаях важнее сразу видеть показания, максимально близкие к реальным, нежели плавный отчет от нуля .

P.S. можно даже еще немного смягчить этот дрейф, реализовав сразу и «скользящее среднее» и «скользящий коэффициент сглаживания» — первое измерение выводится как есть, второе усредняется с первым, третье усредняется с предыдущими и так далее до тех пор, пока счетчик не достигнет заданного числа сглаживаний, далее сглаживать по поседним N измерениям, но сейчас, думаю, это избыточно. С позиции отображения показаний это равноценно тому, что предложил leshak , но с точки зрения построения архитектуры программы более правильно — не приходится раскидывать куски кода, отвечающие за одно и то же, в разные идеологические блоки, следовательно проще в отладке и поддержании кода.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

leshak, а можно все же полюбопытствовать у вас, что за алгоритм » скользящий медианный фильтр» ? , примерчик есть?:)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

leshak, а можно все же полюбопытствовать у вас, что за алгоритм » скользящий медианный фильтр» ? , примерчик есть?:)

Не, примерчиков нет пока. оно писалось «для себя побыстрому» (поэтому слегка сыровато). Смогу дать где-то ближе к вечеру (на другом компе исходники того проекта). Поэтому, пока, только саму «идею» алгоритма описать могу.

Первая часть: нахождение медианы числового ряда. Предположим у нас есть набор замеров: [100,50, 90,95, 999]

Что-бы найти медиану этого ряда, нужно:

1. вначале отсортировать его: [50,90,95,100,999]
2. Медианой этого ряда является — серидина ряда (по счету). Третий элемент. То есть 95-ть.

Как видим, абсолютные значения крайних элементов не влияют на «сглаженное значение». Важно просто что «они больше других», и они просто попадают «на края». Рояль играет только «серединка».
Если элементов четное количество, скажем [50,90,95,97,100,999], то медианой будет среднеарефметическое двух средних элементов (95+97)/2=96.

Втора часть — «скольжение». Предположим мы сделали новый замер: 85. Нам нужно добавить его кряду. Но, что-ра длина ряда (размер массива) остался неизменным один элемент из него нужно выкинуть. Выкидываем «самый старый» (то есть 100, в исходных данных он у нас был «самым первым замером»).

Получаем: [50,90,95,999]. Добавляем к нему новый замер 85, имеем: [ 50,90,95,999,85 ] . Опять сортируем [50,85,90,95,999] и берем средние значение.

И так дальше, следующим мы будем выкидивать 50, потом 90, потом 95, потом 999. Если все новые замеры у нас будут «маленькими», то 999 так никода и не попадет в центр ряда. И этот «большой выброс в сторону» так и останется незамеченым.

Ну а можно, конечно и без скольжения. тоже «по тупому»: сделал пять замеров — отсортировали, нашли середину, выкинули все сделали следующие пять замеров, отсортировали нашли их середину и т.д.

Но в этом случае приходится дольше ждать пока «медиана созрела» (при скольжении при каждом новом замере мы имеем сразу новую, актуальную медиану). И нужно сортировку реализовывать полноценную. А при скольжении. мы фактически добавляем только один элемент в уже отсортированный массив. Только один не на своем месте, следовательно сортировку можно оптимизировать под этот случай. Только один не «на на своем месте».

Источник

Adblock
detector