ARRAY массивы

Sirocco
Offline
Зарегистрирован: 28.09.2013

Нужен код, который бы снимал показания с датчика температуры в течении пулучаса, а потом вычислял среднюю. Я сделал это:

float twArray[10]={0,0,0,0,0,0,0,0,0,0};

long previousMillis = 0;        // храним время изменения 
long interval = 4000;           //интервал
float tw = 0; //Температура трубы
int m = 0; // Переменная считающая циклы массива

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

   unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > interval) //проверяем не прошел ли нужный интервал, если прошел то
     {
      previousMillis = currentMillis;      // сохраняем время 

      twArray[m] = tw;       //пишем текушее значение температруры в массив в ячейку с номером "m"
     m++;
      if(m>=10) // если записана последняя девятая ячейка, обнуляем, и начинаем писать с нулевой ячейки
       {
         m = 0;
       }     
     }
Serial.print("      m =         ");
Serial.print(m);
Serial.println("   ");
Serial.print("[");
Serial.print(twArray[0]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[1]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[2]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[3]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[4]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[5]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[6]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[7]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[8]);
Serial.print("] ");
Serial.print("[");
Serial.print(twArray[9]);
Serial.println("]");
}

А вот лог:

TW = 26.75      m =         0   
[0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00]
TW = 27.25      m =         1   
[27.25] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00]
TW = 27.94      m =         2   
[27.25] [27.94] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00]
TW = 28.37      m =         3   
[27.25] [27.94] [28.37] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00]
TW = 28.69      m =         4   
[27.25] [27.94] [28.37] [28.69] [0.00] [0.00] [0.00] [0.00] [0.00] [0.00]
TW = 28.87      m =         5   
[27.25] [27.94] [28.37] [28.69] [28.87] [0.00] [0.00] [0.00] [0.00] [0.00]
TW = 29.00      m =         6   
[27.25] [27.94] [28.37] [28.69] [28.87] [29.00] [0.00] [0.00] [0.00] [0.00]
TW = 29.12      m =         7   
[27.25] [27.94] [28.37] [28.69] [28.87] [29.00] [29.12] [0.00] [0.00] [0.00]
TW = 29.19      m =         8   
[27.25] [27.94] [28.37] [28.69] [28.87] [29.00] [29.12] [29.19] [0.00] [0.00]
TW = 29.19      m =         9   
[27.25] [27.94] [28.37] [28.69] [28.87] [29.00] [29.12] [29.19] [29.19] [0.00]
TW = 29.19      m =         0   
[27.25] [27.94] [28.37] [28.69] [28.87] [29.00] [29.12] [29.19] [29.19] [29.19]
TW = 28.56      m =         1   
[28.56] [27.94] [28.37] [28.69] [28.87] [29.00] [29.12] [29.19] [29.19] [29.19]
TW = 27.94      m =         2   
[28.56] [27.94] [28.37] [28.69] [28.87] [29.00] [29.12] [29.19] [29.19] [29.19]

Почему за первый проход при m=0 в ячейку ноль ничего не пишется? А при m=1 запись идёт не в первую ячейку, а в нулевую? Откуда отставиние взялось?

boban_
Offline
Зарегистрирован: 09.10.2013

По моему при первом проходе это условие выполняется всегда:

if(currentMillis - previousMillis > interval)

мне кажется копать надо здесь.

Araris
Offline
Зарегистрирован: 09.11.2012

Sirocco пишет:

Почему за первый проход при m=0 в ячейку ноль ничего не пишется?

Может 4-ре секунды еще не прошло ?

Sirocco пишет:

А при m=1 запись идёт не в первую ячейку, а в нулевую? Откуда отставиние взялось?

Вы сначала пишете в массив (m=0), потом изменяете m (m=1), потом выводите новое значение - Serial.print(m);

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Я думаю что расчет среднего можно свести к паре условий и формуле:

[среднее] = ([среднее]*[число измерений]+[текущие показания])/([число измерений] + 1)

И не тратить на это массив.

Sirocco
Offline
Зарегистрирован: 28.09.2013

Araris пишет:

Вы сначала пишете в массив (m=0), потом изменяете m (m=1), потом выводите новое значение - Serial.print(m);

Точно!

Sirocco
Offline
Зарегистрирован: 28.09.2013

NeiroN пишет:

Я думаю что расчет среднего можно свести к паре условий и формуле:

[среднее] = ([среднее]*[число измерений]+[текущие показания])/([число измерений] + 1)

И не тратить на это массив.

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

А очень просто:

Посчитав среднее  и умножив его на какое-то число измерений  мы как-бы знаем что наш "массив" состоит из этого количества измерений и все измерения равны среднему. Поэтому зачем помнить каждое измерение?

Они все равны  среднему...

NeiroN  прав  ,  но более "читабельно и понятно "

[среднее] = ( [среднее] * [число измерений - 1] + [ текущее показание ] ) / ( [число измерений] )

Sirocco
Offline
Зарегистрирован: 28.09.2013

trembo пишет:

А очень просто:

Посчитав среднее  и умножив его на какое-то число измерений  мы как-бы знаем что наш "массив" состоит из этого количества измерений и все измерения равны среднему. Поэтому зачем помнить каждое измерение?

Они все равны  среднему...

А как среднее посчитать? Сложить, например, десять значений, и разделить на десять. Будет среднее. Но ведь эти десять значений, которые нужно сложить, нужно где-то хранить. Как их хранить, если не в массиве? Я чёт не улавливаю Вашу мысль.

Мне нужно каждые 20 минут отправлять значения на сервер. Я не могу отправлять текущие значения, ибо иногда они выбиваются из нормы случайным образом. Так я решил делать 10 измерений, каждые две минуты, потом высчитывать среднее за эти 20 минут и слать в БД.

Как это решить не массивами, просто не пойму. Может Вы и правы, но я чёт не догоняю.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Делаем первое измерение. Так как оно у нас одно то и его среднее значение ему и равно.

Следующее измерение считаем по "формуле" . 

Причём " количество измерений " можем брать ЛЮБОЕ!!!!! ( это всё условно...., хоть мильён ) . Главное помнить о возможности переполнения, поэтому float вам в руки

От выбора "количества измерений" зависит "скорость изменения" среднего: при двух она максимальна, а при миллионе-миллиарде  - сами понимаете .....

http://arduino.ru/forum/proekty/dosvetka-v-teplitse#comment-49692

faraddin
Offline
Зарегистрирован: 11.08.2013

trembo пишет:

Делаем первое измерение. Так как оно у нас одно то и его среднее значение ему и равно.

Следующее измерение считаем по "формуле" . 

Причём " количество измерений " можем брать ЛЮБОЕ!!!!! ( это всё условно...., хоть мильён ) . Главное помнить о возможности переполнения, поэтому float вам в руки

От выбора "количества измерений" зависит "скорость изменения" среднего: при двух она максимальна, а при миллионе-миллиарде  - сами понимаете .....

http://arduino.ru/forum/proekty/dosvetka-v-teplitse#comment-49692

Ваша схема выдаст только общее среднее, например если первые пол часа имеют показания -10, а вторые пол часа +10 то среднее за вторые пол часа высчитать не получится, у нас будет только общее значение равное 0

step962
Offline
Зарегистрирован: 23.05.2011

faraddin пишет:

Ваша схема выдаст только общее среднее, например если первые пол часа имеют показания -10, а вторые пол часа +10 то среднее за вторые пол часа высчитать не получится, у нас будет только общее значение равное 0

Эта "схема" выдает скользящее среднее в диапазоне из число_измерений замеров. "Среднее за вторые полчаса" вы получите, если число_измерений укладывается в полчаса (ровно) один раз. Т.е. при частоте n замеров в час в качестве диапазона вычисления среднего следует взять число_измерений=n/2.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Логично, но кто вам мешает каждые полчаса начать подсчёт сначала?

faraddin
Offline
Зарегистрирован: 11.08.2013

trembo пишет:

Логично, но кто вам мешает каждые полчаса начать подсчёт сначала?

А может ему нужно знать среднее значение за последние пол часа?

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011
faraddin
Offline
Зарегистрирован: 11.08.2013

trembo пишет:

А я что написал?

http://arduino.ru/forum/programmirovanie/array-massivy#comment-86104

Начать каждые пол часа с начала или иметь данные за последние пол часа это разные вещи. Например, начиная каждые пол часа сначала, на 35 минуте мы сможем иметь данные лишь за последние 5 минут, как ему узнать по вашему среднее за периуд с 5 по 35 минуту?

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Sirocco пишет:

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

 

Kvazic
Offline
Зарегистрирован: 29.10.2014


long previousMillis = 0;        // храним время изменения
long interval = 200;//интервал уменьшен для проверки
float twS;   //средняя температура
int m; 
float tw=12 ; //Температура трубы (12 для примера),float tw; 

void setup()
    {

      Serial.begin  (9600);
    }
void loop()
{
 
   unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > interval) //проверяем не прошел ли нужный интервал, если прошел то
     {
      previousMillis = currentMillis;      // сохраняем время
	
	twS+=tw;        	
	m++;                  
    Serial.println(twS); //для проверки   
	if(m>=10)
      {         
	twS=twS/m;        
        Serial.print("twS:  ");
       Serial.println(twS); 
        twS=0;       
        m = 0;
          }
       }

  }

 

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

А зачем накапливать сумму измерений и только на десятый раз получать наше среднее?

А если измереня идут раз в минуту? И если это газовый котёл? Он за десять минут работы так всё прогреет...

Вся вкусность подсчёта среднего сразу- легко регулировать время реакции сменой " количества измерений" и возможность установить порог допустим 0.1 градуса, а не 2-3,  как обычно ставят гистерезис в терморегуляторах и при этом средняя температура действительно будет +- 0.1

Kvazic
Offline
Зарегистрирован: 29.10.2014

Да согласен, можно не накапливать. 

Это так сказать проба пера, я из класса начинающих.

Просто задача не регулировать , а  считать среднее.

"Нужен код, который бы снимал показания с датчика температуры в течении пулучаса, а потом вычислял среднюю." 

Sirocco
Offline
Зарегистрирован: 28.09.2013

Хм. Спасибо за ответы. Нарисовалось два способа, осталось выбрать приемлимый. Цель - хранить историю температуры. Из проведённого опыта видно, что температура при самом резком изменении меняется на 2 градус не чаще раза в 20 минут. Тоесть максимальная скорость изменения температуры примерно 6 градусов в час. При таких вялотекущих процессах не вижу смысла засирать БД показаниями чаще чем в 20 минут. Знающие люди вообще посоветовали раз в час писать.

Таким образом цель одна - максимально сгладить показания, высчитав среднюю температуру за промежуток времени в 20 минут и внести её в БД.

Запись в БД идёт так: ардуино с изернет модулем меняет на своей веб страничке показания раз в 20 минут. (20 минут утрировано, на самом деле 19.5 минут). А скрипт сервера заходит на ардуинку по http, и спарсивает оттуда показания, занося их в базу.

Сейчас это делается массивами. Раз в 19,5 минут меняется веб страничка ардуины, раз в 20 минут скрипт забирает эти данные.

В моём методе получается, что температура храниться только за 20 минут, следущие 20 минут начинается новое накапливание.

Второй способ в любой момент даёт среднее число, с каждым пришедшим значением пересчитывая его.  Я пока ещё не знаю, что именно больше подойдёт для моей задачи. Но оба варианта имеют право на жизнь.