Ошибка при попытке динамического моделирования температуры

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

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

Я что-то упускаю в своем коде?

#include <OneWire.h>
#include <DallasTemperature.h>
#include <NTPClient.h>
#include <WiFi.h>
#include <WiFiUdp.h>


WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000); //UTC+1 (Europe)


unsigned long current_time;

#define WIFI_AP "xxxxx"
#define WIFI_PASSWORD "xxxxx"
//WiFi SETUP
WiFiClient wifiClient;
int status = WL_IDLE_STATUS;
unsigned long lastSend;


const int oneWireBus1 = 0;
OneWire oneWire1 (oneWireBus1);
DallasTemperature sensors1 (&oneWire1);

const int relay1 = 02;


struct SetPoint {
  unsigned long time;
  float temperature;
};


#define DATA_SIZE  17

SetPoint scen1[DATA_SIZE] = {
  {1622652330,26.97},//18h
  {1622652390,25.62},
  {1622678400,24.87},
  {1622689200,24.16},
  {1622700000,23.86},
  {1622710800,25.17},
  {1622721600,26.41},
  {1622732400,27.22},
  {1622743200,26.78},
  {1622754000,25.83},
  {1622764800,25.1},
  {1622775600,24.6},
  {1622786400,24.24},
  {1622797200,26.81},
  {1622808000,29.35},
  {1622818800,29.38},
  {1622829600,30.5}
};

unsigned int pos = 0;


void setup() {
  Serial.begin(115200);
  sensors1.begin();
  pinMode(relay1, OUTPUT);
  InitWiFi();
  lastSend = 0;
  timeClient.begin();

  

void loop() {

  sensors1.requestTemperatures();
  float temperature1 = sensors1.getTempCByIndex(0);

  timeClient.update();

  long current_time =  timeClient.getEpochTime();

  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if (temperature1 < scen1[pos].temperature) {
      digitalWrite (relay1, HIGH);
    }
    else if (temperature1 > scen1[pos].temperature) {
      digitalWrite (relay1, LOW);
    }
    pos++;
  }

  Serial.println(timeClient.getEpochTime());
  Serial.println(timeClient.getFormattedTime());
  Serial.println(pos);
  Serial.println(scen1[pos].temperature);
  Serial.println(scen1[pos-1].temperature);
  Serial.print("Temperature Censius - Sensor 1: ");
  Serial.print(temperature1);
  Serial.println(" ºC ");
  delay(3000);


}

(ОБНОВЛЕНИЕ)

Замена первого if на while ничего не меняет.

Код работает при выводе if / else if из вложенного if, но в этом случае я не могу увеличить время (pos++ также комментируется) и определить ограничения в соответствии с размером массива.

//  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if ((temperature1 < scen1[pos].temperature)&& (current_time >= scen1[pos].time)) {
      digitalWrite (relay1, HIGH);
    }
    else if ((temperature1 > scen1[pos].temperature)&&(current_time >= scen1[pos].time)) {
      digitalWrite (relay1, LOW);
    }
//    pos++;
//  }

, 👍2

Обсуждение

Попробовал заменить " if " на "while" на " while (pos < DATA_SIZE && current_time >= scen1[pos].time)`. Но никаких изменений, @s_tatus3

Еще, если "может быть просто" еще. Я бы начал с того, что убедился, что вводится оператор "если", а затем проверил бы вменяемость двух температур в сравнении. также может быть полезно настроить испытательную установку, которая сжимает время и подделывает данные датчика., @Dave Newton

Спасибо, @DaveNewton. Да, изменил "else if", используя только "else", но, похоже, работает аналогично. Кроме того, время сжатия (в моем случае я установил интервал 1 минута и 2 минуты) реле не меняется с моделируемыми временными данными., @s_tatus3

Поэтому я думаю, что сброс temperature1 и scen1[pos].temperature был бы хорошей идеей для проверки всех предположений. В данный момент нет ничего очевидного, что бросалось бы мне в глаза. (Переход от else if к else не был исправлением, просто упрощением.) Я бы нормализовал все значения времени до "unsigned long" (в настоящее время вы смешиваете сравнения "long" и "unsigned long", но старший бит не установлен, поэтому не имеет значения., @Dave Newton

Мне удалось отбросить if (pos < DATA_SIZE && current_time >= scen1[pos].time) "и использовать только" if " и if else/else`. Я сохранил как "temperature1", так и "scen1[pos].temperature", и цикл работает нормально. Таким образом, я мог бы определить, в чем проблема. Очевидно, теперь я должен увидеть, как добавить оператор/цикл для времени, @s_tatus3

Я не уверен, что вы только что сказали, но если вы сравниваете жестко закодированное время с фактическим временем, вам может быть лучше иметь только time *offsets* в scen1.time и добавлять известное смещение "реального"времени, чтобы они были в будущем. Мне не очень понятно, что вы пытаетесь здесь сделать, но если вы пытаетесь что-то проверить, то я бы не использовал ничего "реального", кроме простой проверки разницы во времени на борту., @Dave Newton

Спасибо, @DaveNewton. Извини, я не совсем ясно выразился. Просто обновил пост с предыдущей информацией, так что теперь легче показать, как я тестировал и в чем текущая проблема., @s_tatus3

Таким образом, сравнение времени, скорее всего, терпит неудачу (или оно очень быстро проходит через цикл, если время всегда >=). Следовательно, вычеркните значения сравнения, чтобы проверить предположения., @Dave Newton


1 ответ


Лучший ответ:

1

Я должен удалить pos++ из оператора if, чтобы digitalWrite снова работал в соответствии с захваченной температурой:

  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if (temperature1 < scen1[pos].temperature) {
    digitalWrite (relay1, HIGH);
    }
    else if (temperature1 > scen1[pos].temperature) {
    digitalWrite (relay1, LOW);
    }
   }

Очевидно, что это не время обновления, и система застревает во времени 0 массива.

(ОБНОВЛЕНИЕ)

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

Проблема была устранена с помощью оператора if, который управляет реле изнутри оператора, управляющего временем.

Теперь я могу смоделировать временной интервал, определенный с помощью массива, и использовать температуру (также присутствующую в массиве) для включения/выключения реле, которое управляет нагревателем и имитирует температуру окружающей среды:

Сначала я создал функцию, которая будет работать как термостат:

void set_thermostat() {
  sensors1.requestTemperatures();
  float temperature1 = sensors1.getTempCByIndex(0);

  if (temperature1 < scen1[pos].temperature) {
    digitalWrite (relay1, HIGH);
  }
  else if (temperature1 > scen1[pos].temperature) {
    digitalWrite (relay1, LOW);
  }
}

Тогда я могу это сделать в функции цикла, вне оператора, который увеличивает время, основываясь на том, которое определено массивом:

  if (pos < DATA_SIZE && current_time >= scen1[pos].times) {
    pos++;
  }

  set_thermostat(); 

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

,

Таким образом, он проходит через петлю, что все еще означает, что сравнение времени терпит неудачу. Отсюда и неоднократное предложение проверить свои предположения, посмотрев на время. Мы никак не можем помочь вам, не зная, какие значения данных сравниваются, и вы не станете ими делиться. Это не ответ на проблему, это обходной путь, который ломает программу., @Dave Newton

Спасибо. Да, я проверил "таймс". Я сравнил current_time и scen1[pos].time. Упростил код и проверил, равен ли current_time или больше scen1[pos].time. Выход правильный (с использованием разных времен и интервалов). Поэтому я ожидаю, что заявление будет работать нормально. Я не знаю, означает ли проверка предположений что-то еще из того, что я уже сделал., @s_tatus3

Я имел в виду, что *мы* не можем проверить ваши предположения или предоставить какой-либо значимый вклад, не зная, что происходит на самом деле. Сравнения обычно просто работают, поэтому, если удаление pos++ "исправляет" его (ergo pos < DATA_SIZE forever) это означает, что есть проблема в сравнении времени. Но мы не можем видеть ни одно из сравниваемых значений, поэтому все, что мы можем сделать, это догадаться., @Dave Newton

Я вижу и согласен. Обновил ответ решением (это действительно воспроизводит то, что я хочу)., @s_tatus3