Этап 10. Повышаем точность датчиков.
Все датчики имеют разброс показаний, мой DHT-21, несмотря на то, что не самый дешевый, показывает температуру +/- 1 градус. TDS-метр тоже не отличается высокой повторяемостью показаний.
Для получения более стабильных и точных показателей будем делать несколько десятков замеров, а затем из них уже вычислять итоговое значение.
Здесь есть несколько вариантов. Я буду использовать медиану и скользящее среднеарифметическое.
Сделал три функции Mediana, Sort, Ariphmetic.
Mediana.
Ей мы скармливаем массив дробных чисел, указываем размер этого массива и "фактор" (для корректной работы они должны быть четными).
Она сортирует этот массив по возрастанию, затем берет несколько значений строго со средины уже отсортированного массива (сколько именно, указывает "фактор") и находит из них среднеарифметичское. Например Mediana(array, 20, 4) возьмет массив размером 20 значений, отсортирует его по возрастанию, затем возьмет с 9 по 12 значения из уже отсортированного массива и вернет их среднеарифметическое.
Функция Ariphmetic просто возвращает среднеарифметическое. Sort сортирует.
Для DHT-21, датчика давления и TDS-метр я буду использовать медиану. Dallas имеет высокую повторяемость показаний, единственный минус в их дискретности, поэтому для него будем использовать скользящее среднее.
Объявим для каждого датчика по массиву (для DHT-21 два, для темп. и влажности), и там, где мы получали их значения, теперь будем заносить замеры в массив, а когда он заполнится, вызовем соотв. функции и найдем из массивов итоговое значение.
Результат получается прекрасный, повторяемость показаний увеличивается примерно на 2 порядка.
А.
float baro_array[16];
int baro_array_index;
float DALLAS_array[10];
int DALLAS_array_index;
float DHT_temperature_array[20];
float DHT_humidity_array[20];
int DHT_array_index;
float tds_array[100];
int tds_array_index;
В.
С.
D.
В функции Klimat, заменим на
baro_array[baro_array_index] = bmp.readPressure()/133.322;
baro_array_index++;
if (baro_array_index > 15){
baro_array_index = 0;
baro_pressure = Mediana(baro_array, 16, 4);
}
DHT_temperature_array[DHT_array_index] = dht.readTemperature();
DHT_humidity_array[DHT_array_index] = dht.readHumidity();
DHT_array_index++;
if(DHT_array_index > 19){
DHT_array_index = 0;
DHT_temperature = Mediana(DHT_temperature_array, 20, 6);
DHT_humidity = Mediana(DHT_humidity_array, 20, 6);
}
В TDS:
tds_array[tds_array_index] = tds_calibration * 1000 / (tds_res);
tds_array_index++;
if(tds_array_index > 99) {
tds_array_index = 0;
tds_ppm = Mediana(tds_array, 100, 20);
}
В Dallas:
DALLAS_array[DALLAS_array_index] = (float)raw / 16.0;
DALLAS_array_index++;
if(DALLAS_array_index > 9) DALLAS_array_index = 0;
DALLAS_temperature = Ariphmetic(DALLAS_array, 10);
В
И добавим эти функци:
float Mediana(float array[], int razmer, int factor){
Sort(array, razmer);
int start = razmer/2-factor/2;
float summa =0;
for (int n = start; n < start+factor ; n++){
summa += array[n];
}
return summa/factor;
}
void Sort(float array[], int razmer){
int min;
float smena;
for (int n = 0; n < razmer ; n++){
min = n;
for(int j = n+1; j < razmer ; j++){
if(array[j] < array[min]){
min = j;
}
}
smena = array[n];
array[n] = array [min];
array [min] = smena;
}
}
float Ariphmetic(float array[], int razmer){
float summa =0;
for (int n = 0; n < razmer ; n++){
summa += array[n];
}
return summa / razmer;
}