Здравствуйте!
ардуино , подключен дифференциальный датчик давления XGZP6897A для измерения потока воздуха в системе приточной вентиляции. Сама система представляет собой: на входе канальный вентилятор (355 м.куб/ч (190Па)), далее главный воздуховод, с него отводы через демпферы (на более меньшее ДУ) , на выходах заслонки управляемые SG90. всего таких заслонок 4 (кухня, гостиная, ванная, туалет). Суть дела вот в чем, из-за того что поток воздуха с вентилятора неравномерный, а так же влияют внешние факторы, то сигнал с датчика “пляшет” (скрин прилагается) . в скетче использую три вида фильтрации, лучше конечно, но все-равно не комильфо, хотелось бы лучше, тем более что планируется ПИД регулирование для поддержания одинакового давления в системе. Посоветуйте какую фильтрацию лучше использовать для моего случая. Спасибо!
собственно сама плата управления и заслонка на настоечном стенде.
ну и скетч:
#define DAMPER_MAX 0
#define DAMPER_MIN 99
#define DAMPER_PIN 5 //пин для сервы
#define PRESSURE_SENSOR_PIN A1
#include <Servo.h>
Servo damper;
const float pressureCoeff = 977; // коэффициент преобразования давления
int zeroPressure;// значение нулевого давления
void setup() {
Serial.begin(9600);
zeroPressure = 490;
pinMode(DAMPER_PIN, INPUT);
damper.attach(DAMPER_PIN);
damper.write(DAMPER_MIN);
delay(50);
}
float _Pressure;
void loop() {
if (Serial.available() > 1) {
char incoming = Serial.read();
int value = Serial.parseInt();
switch (incoming) {
case 's':
damper.write(map(value, 0, 100, DAMPER_MIN, DAMPER_MAX));
delay(50);
break;
case 'z':
zeroPressure = value;
break;
}
}
//_Pressure = (analogRead(PRESSURE_SENSOR_PIN) - zeroPressure);
//Serial.println(_Pressure);
Serial.println(getPressure());
}
float getPressure() {
float pressure;
pressure = (analogRead(PRESSURE_SENSOR_PIN) - zeroPressure);
pressure = filtered(runMiddleArifmOptim(pressure));
pressure = expRunningAverageAdaptive(pressure);
// Преобразуем в паскали
float voltage = (pressure / 1023.0) * 5.0; // преобразование значения АЦП в напряжение (В)
pressure = voltage * pressureCoeff; // преобразование напряжения в давление в Па
// Ограничиваем значение давления от 0 до 1000 Па
return constrain(pressure, 0, 1000);
}
static const int NUM_READ = 32; // количество усреднений для средних арифм. фильтров
float runMiddleArifmOptim(float newVal) {
static int t = 0;
static int vals[NUM_READ];
static int average = 0;
if (++t >= NUM_READ) t = 0; // перемотка t
average -= vals[t]; // вычитаем старое
average += newVal; // прибавляем новое
vals[t] = newVal; // запоминаем в массив
return (((float)average / NUM_READ) * 500) / 1024;
}
float _err_measure = 5.0;//разброс измерения
float _err_estimate = 8.0;//разброс оценки
float _q = 0.1;//скорость изменения значений
float _last_estimate = 0.0;
float filtered(float value) {
float _kalman_gain, _current_estimate;
_kalman_gain = _err_estimate / (_err_estimate + _err_measure);
_current_estimate = _last_estimate + _kalman_gain * (value - _last_estimate);
_err_estimate = (1.0 - _kalman_gain) * _err_estimate + fabs(_last_estimate - _current_estimate) * _q;
_last_estimate = _current_estimate;
return _current_estimate;
}
// бегущее среднее с адаптивным коэффициентом
float expRunningAverageAdaptive(float newVal) {
static float filVal = 0;
float k;
// резкость фильтра зависит от модуля разности значений
if (abs(newVal - filVal) > 1.5) k = 0.9;
else k = 0.03;
filVal += (newVal - filVal) * k;
return filVal;
}