Среднее арифметическое для датчика

Это код, который я использую в настоящее время, но хочу добавить арифметику для него. Моя цель: когда булавка A0 считывает 5 значений, я получаю среднее значение на котором вентилятор и светодиод будут зависеть от включения и выключения, вместо 5 отдельных измерений.

 int tempPin = A0;
int fan = 3;
int led = 8;
int temp;
int tempreal;
int tempMin = 20;
int tempMax = 30;

void setup() 
{
  Serial.begin(9600);
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(tempPin, INPUT);
}

void loop() 
{
  temp = analogRead(tempPin);
  tempreal = temp * 0.48828125;
  delay(1);
  if(tempreal > tempMax)
  {
    digitalWrite(fan,HIGH);
    digitalWrite(led,LOW);
    delay(1);
  } 
  else if (tempreal < tempMin)
  {
    digitalWrite(fan,LOW);
    digitalWrite(led,HIGH);
    delay(1);
  } 
  else if (tempreal >  tempMin && tempreal <  tempMax)   
  {
    digitalWrite(fan,LOW);
    digitalWrite(led,LOW);
    delay(1);
  }
}

Редактировать Эдгар Бонет - OP добавлен в комментарий к моему ответу:

«Я попробовал [усреднение последовательных чтений]. Он работал так, как вы ожидали но он все еще не решает мою проблему. Мой датчик только поправляется значения в начале сканирования, а затем меняется. Поэтому Я хотел сделать среднюю ценность, но она все еще не работает. К сожалению, я думаю Я не смогу изменить датчик, но есть ли другой способ камуфлировать эту проблему? "

Ниже приведен скриншот, показывающий правильные (✓) и неправильные (✗) Показания:

Примеры чтения

2 голоса | спросил najkulime 27 PMpThu, 27 Apr 2017 19:15:21 +030015Thursday 2017, 19:15:21

5 ответов


1

Кажется, слишком просто. я что-то пропустил?

--- arithmetic-mean.ino.orig    2017-04-27 19:37:01.386458500 +0200
+++ arithmetic-mean.ino 2017-04-27 19:38:14.458114972 +0200
@@ -16,8 +16,11 @@

 void loop() 
 {
-  temp = analogRead(tempPin);
-  tempreal=temp * 0.48828125;
+  temp = 0;
+  for (int i = 0; i < 5; i++) {
+    temp += analogRead(tempPin);
+  }
+  tempreal = temp * 0.48828125 / 5;
   delay(1);
   if(tempreal > tempMax)
   {
ответил Edgar Bonet 27 PMpThu, 27 Apr 2017 20:40:29 +030040Thursday 2017, 20:40:29
1

Фиксированное окно выборки может быть трудно справиться, особенно если вы хотите, чтобы расчет был рекурсивным, для соображений пространства и скорости.

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

Y n = (1-α) Y n-1 + α X n

Где Y n - сглаженный результат, X n - это текущее измерение, а α - вес.

С некоторыми мыслями это можно сделать с целыми числами и без потери точности.

edit: я провел сравнение показательного сглаживания против (фиксированного окна) скользящего среднего. Алгоритм скользящей средней был записан как рекурсивный для максимальной скорости.

дискретизированные данные представляют собой симулированную синусоидальную волну:

1000 * sin (2pi * n /100) + 100 * шум. n = 0..19999, а шум = -0,5 ... + 0,5.

Так snr = 1000/50 = 20: 1 или около 5 цифр. гораздо хуже, чем вы столкнулись в 10-битном adc. введите описание изображения здесь

выбранное мной окно - 4.

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

ответил dannyf 28 AMpFri, 28 Apr 2017 00:08:21 +030008Friday 2017, 00:08:21
0

См. Сглаживание учебников Arduino https://www.arduino.cc/en/tutorial/smoothing

Создайте массив для хранения серии показаний. И переменная для хранения суммы.

Инкрементально цикл через массив, вычитая самое старое значение из суммы и заменяя его в массиве текущим чтением. Разделите число показаний для среднего.

Не забудьте оставить задержку в каждом показании, которая подходит для датчика.

ответил DavidJ 28 AMpFri, 28 Apr 2017 02:21:30 +030021Friday 2017, 02:21:30
0

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

 double moving_average(double old_average, double new_value) {
    double new_average = old_average;
    new_average -= old_average/N;
    new_average += new_value/N;
    return new_average;
}

Я отредактировал функцию выше. Я неверно набрал один из аргументов.

ответил vu2aeo 28 AMpFri, 28 Apr 2017 03:29:10 +030029Friday 2017, 03:29:10
0
  

Мой датчик получает правильные значения только в начале сканирования, а затем меняется. Вот почему я хотел сделать среднюю ценность, но она по-прежнему не работает.

У меня была аналогичная проблема. Оказалось, что я читал и писал слишком быстро. Это означает, что, поскольку кажется, что чтение и письмо могут быть прерваны во время «их работы», когда вы читаете переменную и в то же время кто-то пишет, что вы читаете мусор. По-моему, это может быть исправлено приложением «семафоров» или мьютексом или уменьшением вызова чтения. Случайно это произойдет снова, но реже.

Идею можно найти здесь https://forum.arduino.cc/index.php?topic=132813.0

Лучший

Джиан Мария

ответил Gian_Maria 9 Maypm18 2018, 20:05:01

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132