Працюємо з 09:00 до 19:00 без вихідних.
Самовивіз - Київ біля ТЦ Квадрат бул.Перова

Шум аналогового входа

Любой аналоговый датчик, соединительные провода, да и сам аналоговый вход контроллера вносят в результирующее измеренное значение множество шумов. Они мешают нам получить реальное значение параметра с повторяемой точностью.


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

Давайте рассмотрим два интересных способа программной фильтрации этих шумов. 

Следующая программа для контроллера Arduino считывает аналоговый вход и выводит в монитор порта нефильтрованное значение, и два значения отфильтрованные двумя разными способами.

int sensorPin = A0; // номер аналогового входа

// функция считывает аналоговый вход заданное количество раз
// и возвращает отфильтрованное значение
int readMean(int pin, int samples){
// переменная для хранения суммы считанных значений
int sum = 0;
// чтение и складывание значений
for (int i = 0; i < samples; i++){
sum = sum + analogRead(pin);
}
// делим сумму значений на количество измерений
sum = sum/samples;
// возвращаем среднее значение
return sum;
}
// функция считывает аналоговый вход заданное количество раз
// и возвращает медианное отфильтрованное значение
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 = i; 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(){
// выводим значение на аналоговом входе в монитор порта
Serial.print(analogRead(sensorPin));
Serial.print(" ");
// выводим среднеизмеренное значение
Serial.print(readMean(sensorPin, 15));
Serial.print(" ");
// выводим медианное отфильтрованное значение
Serial.println(readMedian(sensorPin, 15));
delay(100);
}

Изобретено множество программных фильтров, но мы здесь рассматриваем два самых испоьзуемых типа: фильтр по среднему значению и медианный фильтр.

Первый - фильтр по среднеизмеренному значению

Данный алгоритм собирает несколько значений и вычисляет по ним среднее значение. Он довольно хорошо убирает шум, но требует больших затрат времени цикла от контроллера. Из-за того, что необходимо сделать несколько выборок сигнала с аналогового входа. Таким образом увеличивается время ответа при опросе входного значения главной программой. Но медленное получение значения лучше чем скачущее значение.

1) Объявляем функцию с двумя параметрами: первый содержит номер аналогового входа Arduino, куда подключен датчик; а второй задает количество выборок.

2) Далее мы циклически считываем значение аналогового входа и каждый раз прибавляем его к переменной sum
int sum = 0;
for (int i = 0; i < samples; i++){
sum = sum + analogRead(pin);
}

3) Дальше находим среднее значение. Сумму всех значений выборок делим на количество выборок
sum = sum/samples;

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

Алгоритм этого программного фильтра немного сложнее, но действеннее. Он не делает математических вычислений над выборками. Фильтр основан на допущении, что выбросы шума расположены равномерно как в позитивную сторону так и в негативную по отношению к реальному значению. Этот алгоритм считывает ряд значений с аналогового входа контроллера Arduino, сортирует их по возрастанию и выбирает значение, стоящее в центре полученного списка. В общем случае, если выбросы шума расположены равномерно с двух сторон от реального значения, то получим точную величину.

1) Объявляем функцию медианного фильтра, принимающую номер аналогового входа и количество выборок
int readMedian (int pin, int samples){
2) Дальше объявляем массив для хранения данных и в цикле заполняем этот массив считываемыми с аналогового входа данными
int raw[samples];
for (int i = 0; i < samples; i++){
raw[i] = analogRead(pin);
}

Дальше алгоритм делает сортировку массива по значению. Для этого используется так называемый пузырьковый алгоритм. Он выстроит ячейки массива по порядку от меньших значений до больших.

И в конце функции возвращаем значение средней ячейки отсортированного массива.

return raw[samples/2];

Основной цикл программы

В основном цикле программы мы просто циклически выводим полученные данные в монитор порта, чтобы проследить за изменениями измеряемого параметра во времени. В одну строку программа должна выводить нефильтрованное значение и два фильтрованных разными алгоритмами значения. Таким образом мы сможем оценить качество фильтрации разными способами.

Здесь задано считывание 15 выборок, но вы можете поэкспериментировать и с другим количеством, наблюдая за изменением качества фильтрации сигнала.

Serial.print(analogRead(sensorPin));
Serial.print(" ");
Serial.print(readMean(sensorPin, 15));
Serial.print(" ");
Serial.println(readMedian(sensorPin, 15));
delay(100);

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Помпа для отсоса припоя

Помпа для отсоса припоя

Инструмент для отбора лишнего припоя с печатной платы.Необходимо предварительно разогреть припой при..

57.90грн.

Двигатель с редуктором 10RPM 12В

Двигатель с редуктором 10RPM 12В

Двигатель постоянного тока с редуктором. При питании 12 В - скорость вращения оси 10 об./минСко..

209.50грн.

Концевик для 3D принтера или CNC ramps 1.4

Концевик для 3D принтера или CNC ramps 1.4

Концевой выключатель для установки на 3D-принтер или CNC-станок системы ramps 1.4В комплекте ка..

25.57грн.

Датчик для измерения напряжения сети 220В

Датчик для измерения напряжения сети 220В

Датчик используется в системах умный дом для преобразования и дальнейшего измерения величины перемен..

71.84грн.

Мини кнопка 12 x 12 x 4,3 мм

Мини кнопка 12 x 12 x 4,3 мм

Миниатюрная кнопка для установки на плату через отверстияРазмеры 12 x 12 x 4,3 мм..

3.22грн.