Нужна помощь новичку с усреднением значения

Доброе время суток, в общем и целом нужна помощь с усреднением значения с потенционометра, много чего перепробовал, но дребезжит всё равно, может есть тупое и простое решение, до которого мой уже сонный мозг не додумался?

void ptns()
{
    potv = analogRead(pin_pot);
    potv = constrain(potv, 0, 680);
    pot = map(potv, 0, 680, 0, NUM_LEDS);
}

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

NUM_LEDS = 288 если что

Простейший вариант - усреднение

void ptns()
{
    potv = (potv * 2 + analogRead(pin_pot)) / 3;
    potv = constrain(potv, 0, 680);
    pot = map(potv, 0, 680, 0, NUM_LEDS);
}

Конденсатор ~0.1мкф между пином и землёй попробуйте

1 лайк
  1. Если речь идет об AVR (ТС забыл упомянуть о том, какой используется контроллер), то при наличии конденсатора (по рекомендации поста 3) результат должен либо стоять, как вкопанный, либо столь же стабильно поочередно воспроизводить два смежных значения. Что теоретически позволяет распознать 2047 уровней. Если этого не происходит, вероятно, дело в том, что напряжение (либо измеряемое, либо опорное, либо оба сразу) на самом деле нестабильно.
  2. Простейший вариант, предложенный @v258, может настраиваться константами вплоть до нескольких десятков.
  3. Усреднение может быть не только таким, как указал @v258, но и просто складывать несколько (2, 4, 8, 16, 32…) результата измерения и по ним находить среднее.
  4. Можно использовать и более сложные схемы обработки (уже, строго говоря, не являющиеся усреднением), например, запоминать старое значение и придерживаться его до тех пор, пока новое не будет отличаться от него на N единиц, где N, опять же, можно подбирать.

Думал как раз над вашим 4 вариантом, нет примера как можно это реализовать?

Сделай 3 сначала. Потом плавно перейдёшь к 4, если понадобится.

Пытался через массив, через цикл for заполнять массив, и так же через цикл for плюсовать значения, то бишь

for(int i; i < 9; i++)
{
  pot = analogRead(pin_pot);
  pott[i] = pot;
  delay(5);
}
for(int i; i < 9; i++)
{
  sum = sum + pott[i];
}

pot = sum/10;

Такой кусок кода выдает почему-то неимоверные значения, доходящие до 1900+, может я что не так прописал?

Конечно не то. Во-первых i нужно инициализировать, т.е. сразу задавать значение 0, во-вторых, если вы делаете 9 итераций, зачем делите на 10? И в-третьих - зачем вам нужен массив, сразу плюсовать вообще не вариант?

Т.к. значение с АЦП 10 битное, то можно суммировать до 64 раз (6 бит), при этом достаточно uint16_t для результата.

Примеры-то есть, только в сеть я их не выкладывал.
В частности, я это использовал в проекте

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

Вообще же, “реализация” любой идеи происходит в два этапа:

  1. Подробно расписать алгоритм по-русски.
  2. Перевести с русского на Си.

Так что могу посоветовать начать с первого этапа.

2 лайка

Все не так:

  • этот кусок не компилируется, потому большая часть несообразностей просто не может быть обсуждаема.
  • зачем здесь массив и два отдельных цикла - совершенно непонятно.
  • переменная цикла не инициализируется. Да и вообще достаточно было бы byte.
  • переменная sum вовремя не обнуляется - насуммировать туда можно сколько угодно вплоть до переполнения.
  • зачем 5-мс паузы также непонятно.
  • про странный выбор констант уже упоминали. И, кстати, из моего сообщения можно было сделать вывод, что рекомендуемые значения - степени двойки, а не непонятно откуда взявшиеся 9 или 10.

А самому подумать? Зачем тут какой-то пример? Логика-то элементарная - если новое значение отличается от старого более чем, например, на пять - запоминаем новое, если нет - используем старое.
Весь пример представляет из себя одну строчку с оператором if.

Отчего то вспомнился анекдот про прапорщика и обезьяну: “Да что там думать! Трясти надо.”)

Так не трясете и не думаете.

Если сильно трясти - отвалится. Писать сидя потом станешь. Как людЯм в глаза смотреть?

Среднее значение можно получить используя примерно такой алгоритм:
1.считываем значения в массив ,длинной=n ,n-раз
2.сортируем массив
3.отбрасываем несколько начальных и конечных элементов массива (часть самых высоких и самых низких значений) (скачки, провалы)
4.находим среднее арифметическое оставшихся значений.

Переведите этот алгоритм в код и будет то, что вам требуется

В пределе это называется медианой.

Медианой это будет, если выкинуть все значения , кроме одного, самого среднего.

Ну да, оставляем некоторое количество значений. В пределе - одно.
Кстати, медиана - не всегда “хорошее” среднее. Вот, например, как “тикает” millis на AVR: за секунду происходит 976 приращений - большая часть на единицу, а несколько - на двойку. В среднем - раз в 1.000 мс. А если посчитать медиану - получится раз в 1.024 мс. Да и вообще любые “отбрасывания!” с двух сторон (после сортировки) приводят к искажению результата.

1 лайк