медианный фильтр

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
Друзья Всем привет!
Нужна помощь в написании фильтра для аналогового сигнала.
Программа управляет работой гидравлики и от шумов на аналоговом пине А0 происходят рывки при небольшом угле отклонения управляющего рычага.
Я трижды прочитал статью на этом сайте о фильтрации. Но моих навыков не хватает на адаптацию примеров указанных в статье для моей программы.
Программу писал сам (в первый раз) не кидайтесь тапками...

Помогите написать медианный фильтр для analogValue, пожалуйста. Или скиньте программу с примером использования такого фильтра.

// These constants won't change:
const int analogPin = A0; // Вход с датчика положения рукоятки
const int OutA = 10; // Выход на твердотельное реле
const int OutB = 11; // Выход на твердотельное реле
const int LimA = 462; // начало срабатывания клапана на движение влево
const int LimB = 562; // начало срабатывания клапана на движение вправо
const byte averageFactor = 5;
int sensorValue = 0;

void setup() {
pinMode(OutA, OUTPUT);
pinMode(OutB, OUTPUT);
// initialize serial communications:
Serial.begin(9600);
}

void loop() {


if (analogValue > LimB) { //если напряжение больше лимита
int val = analogRead(0);
val = map(val, 562, 1023, 0, 30); //подается шим пропорционально отклонению, поворот вправо
analogWrite(OutA, val);
Serial.println(val);
} else if (analogValue < LimA) { //если напряжение меньше лимита
int val = analogRead(0);
val = map(val, 0, 462, 40, 0);
analogWrite(OutB, val); //подается шим пропорционально отклонению, поворот вправо
Serial.println(val);
} else {
analogWrite(OutA, 0); // в нейтральном положении не подавать ШИМ
analogWrite(OutB, 0);

// print the analog value:
Serial.println(analogValue);
delay(50);
}
}
 

Вложения

bort707

★★★★★★✩
21 Сен 2020
3,056
910
дайте ссылку на статью, о которой вы говорите
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Нужен фильтр на 5-7 значений.
на 5-7 значений лучше скользящее среднее использовать, медиана слишком кода много.
А какие проблемы у вас - в статье приведены готовые функции фильтрации, ничего "адаптировать" не надо, просто копируете их в скетч и все
 

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
на 5-7 значений лучше скользящее среднее использовать, медиана слишком кода много.
А какие проблемы у вас - в статье приведены готовые функции фильтрации, ничего "адаптировать" не надо, просто копируете их в скетч и все
Ну очевидно я не так выразился. Под "адаптацией" я имел ввиду подружить код в статье с моим сетчем.
если я просто копирую его в скетч он не будет работать.
1614774026270.png

"newVa"l - это значения с моего датчика?

И что эта функция вернет? "runMiddleArifm"?
мне "runMiddleArifm" подставить вместо "analogValue" ?
 

Nikanor

★★✩✩✩✩✩
1 Окт 2020
178
51
C++:
const int sensorPin = A0;

int samples = 15;  ///  кол-во выборок, не чётное
int pot_val;


////////////  медианное отфильтрованное значение  ////////////////////

int readMedian (int pin, int samples)
{
  int raw[samples];

  for (int i = 0; i < samples; i++)
  {
    raw[i] = analogRead(pin);
  }

  int temp = 0;

  for (int i = 0; i < samples; i++)
  {
    for (int j = 0; j < samples - 1; j++)
    {
      if (raw[j] > raw[j + 1])
      {
        temp = raw[j];
        raw[j] = raw[j + 1];
        raw[j + 1] = temp;
      }
    }
  }
  return raw[samples / 2];
}



void setup()
{
  Serial.begin(9600);
}


void loop()
{
  pot_val = readMedian(sensorPin, 15);

  Serial.println(pot_val);
  delay(100);
}
 
  • Лойс +1
Реакции: ЮрийI||X

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
C++:
const int sensorPin = A0;

int samples = 15;  ///  кол-во выборок, не чётное
int pot_val;


////////////  медианное отфильтрованное значение  ////////////////////

int readMedian (int pin, int samples)
{
  int raw[samples];

  for (int i = 0; i < samples; i++)
  {
    raw[i] = analogRead(pin);
  }

  int temp = 0;

  for (int i = 0; i < samples; i++)
  {
    for (int j = 0; j < samples - 1; j++)
    {
      if (raw[j] > raw[j + 1])
      {
        temp = raw[j];
        raw[j] = raw[j + 1];
        raw[j + 1] = temp;
      }
    }
  }
  return raw[samples / 2];
}



void setup()
{
  Serial.begin(9600);
}


void loop()
{
  pot_val = readMedian(sensorPin, 15);

  Serial.println(pot_val);
  delay(100);
}
Вроде бы почти понял...
Смущает "void setup()" и "void loop()" после кода фильтра. Так должно быть?
Или в моем примере мне лучше в loop поместить?
 

Nikanor

★★✩✩✩✩✩
1 Окт 2020
178
51
Так должно быть.
Я вам привёл рабочий пример .
Берите и пользуйтесь.
 

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
Не сочтите за офтоп,
Мне известно : все что находится в "void setup()" выполняется один раз, все что в "void loop()" выполнятся по кругу бесконечно.
Что насчет функции которую мы расположим до "void setup()"? как будет работать она?
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
@ЮрийI||X, вам бы стоило почитать какую-то книжку для самых чайников, по вашим вопросам очевидно, что вы не в курсе самых элементарных вещей. Например, вот этот ваш вопрос появился от того, что вы ничего не знаете про процедуры в языке Си.
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Я вам привёл рабочий пример .
с точки зрения синтаксиса - да.
Но вообще приведенный Вами код не имеет к медиане никакого отношения :)
Однократная попарная сортировка соседних элементов в массиве (строчки 20-30) вовсе не делает массив сортированным :)
И потому среднее значение такого массива никак не будет медианой.
Для проверки можете попробовать свой алгоритм на массиве {6,3,4,12,1, 6, 9} - ваш код возвращает 1, что явно никакая не "медиана", а для данного набора значений скорее "выброс"
 
Изменено:

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
@ЮрийI||X, вам бы стоило почитать какую-то книжку для самых чайников, по вашим вопросам очевидно, что вы не в курсе самых элементарных вещей. Например, вот этот ваш вопрос появился от того, что вы ничего не знаете про процедуры в языке Си.
Может посоветуете чего то конкретного?
Я читал все что нашел по ардуино, пробую начать читать про Си (как то там все по другому смотрится)...
Надо начинать с Си?
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
язык скетчей Ардуино - это С++
Вам будут полезны первые главы любого учебника по С/С++ - переменные, операторы, функции, циклы и тд
 

Nikanor

★★✩✩✩✩✩
1 Окт 2020
178
51
с точки зрения синтаксиса - да.
Но вообще приведенный Вами код не имеет к медиане никакого отношения :)
Однократная попарная сортировка соседних элементов в массиве (строчки 20-30) вовсе не делает массив сортированным :)
И потому среднее значение такого массива никак не будет медианой.
Для проверки можете попробовать свой алгоритм на массиве {6,3,4,12,1, 6, 9} - ваш код возвращает 1, что явно никакая не "медиана", а для данного набора значений скорее "выброс"
проверил.
возвращает 6.
 

poty

★★★★★★✩
19 Фев 2020
3,230
940
@ЮрийI||X, любая программа (а скетч - это программа) имеет точку входа. В "обычном" С или С++ это функция main(). Что такое точка входа? Это точка, куда передаётся управление после загрузки программы в память. Заканчивается функция main() - заканчивается выполнение программы, управление передаётся операционной системе, программа выгружается из памяти.
В упрощённом варианте, использующемся в Ардуино, в качестве операционной системы выступает фиксированный код, загруженный в микропроцессор. Фактически, функция main() уже написана и состоит она в простейшем случае из двух строк:
setup();
while (1) {loop();}

Как видно, завершение main() невозможно.

Что касается функции, которая находится выше setup(): исходя из вышесказанных рассуждений она выполняется только тогда, когда будет явно вызвана откуда то из setup() или loop().
 
  • Лойс +1
Реакции: ЮрийI||X

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
Попытался прикрутить фильтр к своему скетчу. Не работает.
В мониторе порта совсем пропал датчик положения рычага, видно только что на "OutB" приходит Val=40.
Подскажите в чем я накосячил?
 

Вложения

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
C++:
{

const int analogPin = A0;    // Вход с датчика положения рукоятки
const int OutA = 10;       // Выход на твердотельное реле
const int OutB = 11;        // Выход на твердотельное реле
const int LimA = 462;    // начало срабатывания клапана на движение влево
const int LimB = 562;     // начало срабатывания клапана на движение вправо
int samples = 15;  ///  кол-во выборок, не чётное
int pot_val;
int readMedian (int pin, int samples)
  {
    int raw[samples];

    for (int i = 0; i < samples; i++)
    {
      raw[i] = analogRead(0);
    }

    int temp = 0;

    for (int i = 0; i < samples; i++)
    {
      for (int j = 0; j < samples - 1; j++)
      {
        if (raw[j] > raw[j + 1])
        {
          temp = raw[j];
          raw[j] = raw[j + 1];
          raw[j + 1] = temp;
        }
      }
    }
    return raw[samples / 2];
  }

void setup() {
  // initialize the LED pin as an output:
  pinMode(OutA, OUTPUT);
  pinMode(OutB, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop() {
 int readMedian; 




  if (readMedian > LimB) {   //если напряжение больше лимита
    int val = readMedian;
    val = map(val, 562, 1023, 0, 30);   //подается шим пропорционально отклонению, поворот вправо
    analogWrite(OutA, val);
    Serial.println(val);
  } else if (readMedian < LimA) { //если напряжение меньше лимита
    int val = readMedian;
    val = map(val, 0, 462, 40, 0);
    analogWrite(OutB, val);  //подается шим пропорционально отклонению, поворот вправо
    Serial.println(val);
  } else {
    analogWrite(OutA, 0);         // в нейтральном положении не подавать ШИМ
    analogWrite(OutB, 0);

    // print the analog value:
    Serial.println(readMedian);
    delay(50);
  }
}

}
 

poty

★★★★★★✩
19 Фев 2020
3,230
940
@ЮрийI||X, Вы в функции loop() объявили локальную переменную readMedian и её проверяете. Функцию readMedian Вы не вызываете. Думаю, что совет @bort707 всё ещё очень актуален. Есть уроки на сайте Алекса (на форум которого Вы написали), можно их почитать, они совсем не страшные и не сложные. Посмотрите также, что Вам написал @Nikanor, как вызывается в loop() нужная Вам функция.
 

ЮрийI||X

✩✩✩✩✩✩✩
3 Мар 2021
9
0
@ЮрийI||X, Вы в функции loop() объявили локальную переменную readMedian и её проверяете. Функцию readMedian Вы не вызываете. Думаю, что совет @bort707 всё ещё очень актуален. Есть уроки на сайте Алекса (на форум которого Вы написали), можно их почитать, они совсем не страшные и не сложные. Посмотрите также, что Вам написал @Nikanor, как вызывается в loop() нужная Вам функция.
Короч, вывод: пока я не научусь разговаривать с вами на одном языке, толков не будет :unsure:
Пошел учить синтаксис
Всем спасибо за понимание к чайникам)После выходных вернусь.