Математическая фильтрация данных с аналогового пина

vavandrik
Offline
Зарегистрирован: 16.01.2019

Есть программка, простенький вольтметр выводящий считываемое напряжение на многоразрядный семисегментный индикатор. Но у меня проблема с некорректным выводом. Понимаю что надо делать мат. фильтр но не сталкивался еще с ними. Нужна помощь знатоков. Снизу программа(на всякий).

 
bool one [10][8] = 
{1, 1, 1, 1, 1, 1, 1, 0}, 
{1, 0, 1, 1, 0, 0, 0, 0}, 
{1, 1, 1, 0, 1, 1, 0, 1}, 
{1, 1, 1, 1, 1, 0, 0, 1}, 
{1, 0, 1, 1, 0, 0, 1, 1}, 
{1, 1, 0, 1, 1, 0, 1, 1}, 
{1, 1, 0, 1, 1, 1, 1, 1}, 
{1, 1, 1, 1, 0, 0, 0, 0}, 
{1, 1, 1, 1, 1, 1, 1, 1}, 
{1, 1, 1, 1, 1, 0, 1, 1} 
};
bool two [10][8] = 
{0, 1, 1, 1, 1, 1, 1, 0}, 
{0, 0, 1, 1, 0, 0, 0, 0}, 
{0, 1, 1, 0, 1, 1, 0, 1}, 
{0, 1, 1, 1, 1, 0, 0, 1}, 
{0, 0, 1, 1, 0, 0, 1, 1}, 
{0, 1, 0, 1, 1, 0, 1, 1}, 
{0, 1, 0, 1, 1, 1, 1, 1}, 
{0, 1, 1, 1, 0, 0, 0, 0}, 
{0, 1, 1, 1, 1, 1, 1, 1}, 
{0, 1, 1, 1, 1, 0, 1, 1} 
}; 
float VoltA;
int VoltB;
int Volt;
int VoltC;
 
void setup() 
for(int pin =2; pin <= 17; pin++) 
pinMode(pin, OUTPUT); 
digitalWrite(pin,LOW); 
}
 pinMode(A5, INPUT); 
  Serial.begin(9600);
 
 
void DigitDraw(int digit)
{
  for(int i = 0; i <= 8; i++)
  {
   if(one[digit][i] == 1) digitalWrite(i + 2, HIGH); else digitalWrite(i + 2, LOW);
  }
}
void DigitDraw2(int digit2)
{
  for(int q = 0; q <= 8; q++)
  {
   if(two[digit2][q] == 1) digitalWrite(q + 2, HIGH); else digitalWrite(q + 2, LOW);
  }
}
void SelectDigit(byte select)
{
 for(int c = 10; c<=12; c++)
 {
  digitalWrite(c, HIGH); 
 }
  digitalWrite(select, LOW);
}
 
void loop() 
   Volt = analogRead(A5);
  VoltA = analogRead(A5);
VoltA = VoltA/204.6;
 Volt = Volt/204.6;
  VoltA=(VoltA-Volt)*10;
  VoltB=VoltA;
  VoltC = Volt/10;
  Serial.println(Volt);
  SelectDigit(10);
  DigitDraw2(VoltA);
  delay(5);
  SelectDigit(12);
  DigitDraw2(VoltC);
  delay(5);
  SelectDigit(11);
  DigitDraw2(Volt);
delay(5);

mixail844
Offline
Зарегистрирован: 30.04.2012

я угадаю проблему с 7 попыток ;)

kalapanga
Offline
Зарегистрирован: 23.10.2016

Нет такого чудо-фильтра, который некорректные значения в корректные превращает. Формулируйте проблему точнее. И прочитайте в первой теме раздела Песочница правила оформления сообщений и конкретно вставки кода.

vavandrik
Offline
Зарегистрирован: 16.01.2019

http://geekmatic.in.ua/filtracia_shumov_analogovogo_signala - вот тот самый чудо-фильтр) Мне надо что-то подобное для моего кода

Nosferatu
Offline
Зарегистрирован: 04.11.2012

Среднее арифметическое. Замеряем N раз в цикле, суммируем.  После цикла делим сумму на N.

PS: Неформатированный код читать лень.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Для нормальной фильтрации нужно, для начала правильно читать. Там обычно важна частота оцифровки.

А так, есть программа, которая генерирует готовый фильтр (исходник) по заданным характеристикам. Правда, как видно из дискуссии вот здесь, при одних условиях она хороша, а при других коллегу не устроила.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Вообще-то обработка результатов экспиримента - это целая наука. Вкратце можно посоветовать следующий алгоритм:

1) Считали некоторое количество данных

2) Вычислили среднее арифметическое

3) Вычислили среднюю погрешность

4) Выбросили результаты, не попадающие в погрешность

5) Вычислили среднее арифметическое из оставшихся данных

Для данной задачи вполне подойдет.

sadman41
Offline
Зарегистрирован: 19.10.2016

Может просто медиану брать - один qsort, а эффект примерно тот же.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:

Может просто медиану брать - один qsort, а эффект примерно тот же.

Не совсем так - надо сеять резко выбивающиеся данные - они сильно портят результат и, соответственно, смещают медиану.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

mykaida пишет:

Вообще-то обработка результатов экспиримента - это целая наука. Вкратце можно посоветовать следующий алгоритм:

1) Считали некоторое количество данных

2) Вычислили среднее арифметическое

3) Вычислили среднюю погрешность

4) Выбросили результаты, не попадающие в погрешность

5) Вычислили среднее арифметическое из оставшихся данных

Для данной задачи вполне подойдет.

Пара замечаний:

- "Считали некоторое количество данных" - это не первый пункт, а где-то десятый: сначала эксперимент нужно спланировать, в частности, понять, что хотим мерять, с какой точностью, каким способом и т.д.

- При наличии значительных выбросов этот алгоритм будет работать плохо. Среднее арифметическое может уйти куда угодно. Для первоначальной оценки лучше использовать медиану. И иногда этого оказывается достаточно.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

mykaida пишет:

sadman41 пишет:

Может просто медиану брать - один qsort, а эффект примерно тот же.

Не совсем так - надо сеять резко выбивающиеся данные - они сильно портят результат и, соответственно, смещают медиану.

Если дело доходит до смещения медианы (а для этого более половины измерений должны быть негодными), следует подумать о выборе другого способа измерения.

sadman41
Offline
Зарегистрирован: 19.10.2016

mykaida пишет:

Не совсем так - надо сеять резко выбивающиеся данные - они сильно портят результат и, соответственно, смещают медиану.

А ежели сама природа сигнала хаотична - как тут определишь норму?

SLKH
Offline
Зарегистрирован: 17.08.2015

ЕвгенийП пишет:

Для нормальной фильтрации нужно, для начала правильно читать. Там обычно важна частота оцифровки.

Сначала - железный ФНЧ на входе. Или же сознательный обоснованный отказ от его применения.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:

А ежели сама природа сигнала хаотична - как тут определишь норму?

А ежели сама природа сигнала хаотична - то достаточно точно Вы сможете померить только верний и нижний уровень сигнала. Но если это реально "белый шум".

FAI4
Offline
Зарегистрирован: 23.09.2016

Нужно всего лишь добавить:

 

float Volt = 0.0;

float VoltNew;

float alpha = 0.2;

// alpha - параметр сглаживания (примерно равен 1/n, где n - параметр усреднения)

// диапазон значений: 1 <= alpha < 0

// подобрать экспериментально в зависимости от характера входящего потока данных

 

void loop() 
   VoltNew = analogRead(A5);
   Volt = Volt * (1- alpha) + alpha*VoltNew;
...