Воспроизведение смоделированных температурных данных с помощью Arduino

Я начинаю тест с помощью Arduino, чтобы воспроизвести набор значений температуры в воде каждые три часа, и мне нужна помощь с этим.

Я буду использовать два датчика ds18b20 для управления двумя термостатами, подключенными к реле. Идея состоит в том, что Arduino может получить доступ к данным из файла, в котором есть смоделированные данные для каждого дня в будущем. Что-то вроде этого:

Date,Time,Temperature
01/01/2070,00:00:00,27.229211807251
30/12/2070,21:00:00,24.6133060455322
01/01/2070,06:00:00,22.1697025299072
01/01/2070,09:00:00,20.3209171295166
01/01/2070,12:00:00,27.7610721588135
01/01/2070,15:00:00,33.6277084350586
01/01/2070,18:00:00,34.5402450561523
01/01/2070,21:00:00,31.9973392486572
02/01/2070,00:00:00,26.2283573150635
02/01/2070,03:00:00,21.5823612213135
02/01/2070,06:00:00,18.6461429595947
02/01/2070,09:00:00,17.2126712799072
02/01/2070,12:00:00,24.8096561431885
02/01/2070,15:00:00,30.6440677642822
02/01/2070,18:00:00,33.8463973999023
02/01/2070,21:00:00,31.3529300689697
03/01/2070,00:00:00,25.2961673736572
03/01/2070,03:00:00,20.8135623931885

На основе этой информации датчик будет контролировать термостат, чтобы уменьшить или увеличить температуру в течение трех часов (8 различных температур днем). Я собираюсь начать с 1 недели (7 дней х 8 температур = 56 симуляций), но хочу увеличить ее до 3 месяцев (720 симуляций).

Учитывая использование if/else if, кажется, что это было бы огромное количество условных выражений.

Есть ли у кого-нибудь хорошее решение для запуска этого температурного моделирования на основе предопределенных данных?

Заранее благодарю.

, 👍3

Обсуждение

Мне непонятно, для чего именно вы рассматривали выражения if/else if. У вас есть x кортежей данных со временем и заданной температурой термостата. Таким образом, вы можете поместить их в массив, сохранив текущий индекс элемента в переменной. Затем вы сравниваете время текущего элемента с текущим временем и соответственно устанавливаете уставку термостата. И вы переходите к следующему элементу, если для этого пришло время. Это то, чего ты хочешь?, @chrisl

Спасибо за ответ @christl. Кажется вполне разумным то, что вы предлагаете, и именно то, что я ищу! Я никогда не работал с этим подходом, поэтому мне нужно найти некоторую документацию и ссылки на нее., @s_tatus3

нет смысла хранить температуру, используя значения с плавающей запятой ... вы используете 32 бита для хранения 12-разрядного значения, @jsotola


1 ответ


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

2

Вы можете использовать массив, чтобы пройти через времена.

Создайте структуру с полями время и температура (вы должны думать о сохранении времени как UNIX эпохи, то есть секунд с 1970 года, чтобы сохранить память).

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

Затем вы можете объявить массив типа SetPoint для хранения кубиков времени и температуры:

#define DATA_SIZE  720
SetPoint data[DATA_SIZE] = {
    {<time1>, <temp1>},
    {<time2>, <temp2>},
    ...
    };

В приведенном выше, вам нужно заменить <timeX><timeX> и <tempX><tempX> вашими данными. Затем объявите переменную положения, которая является индексом элемента, который будет вызван следующим образом:

unsigned int pos = 0;

Мы начинаем с первого элемента (индекс 0) и сравниваем его время с текущим. Если оно равно (или текущее время после времени элементов), мы установим термостат на температуру элементов и увеличим переменную положения. Что-то вроде этого:

if(pos < DATA_SIZE && current_time >= data[pos].time){
    set_thermostat(data[pos].temperature);
    pos++;
}

Примечание: Я использовал переменную current_time здесь как подставку для вашего способа получения текущего времени, а функцию set_thermostat() как подставку для вашего способа установки термостата. Кроме того, я вставил проверку в оператор if, чтобы предотвратить дальнейшее развитие кода, когда он достигнет конца массива данных.


Тем не менее, в зависимости от используемой платы вы можете легко попасть в проблемы с памятью здесь. Arduino Uno не имеет достаточно памяти, чтобы сохранить 720 точек данных выше. float и unsigned long берут по 4 байта каждый, так что 8 байт на элемент, что составляет 8*720 = 5760 байт. Uno имеет всего 2048 байт в оперативной памяти. Есть достаточно плат, которые имеют больше оперативной памяти. ESP32, например, было бы достаточно (хотя есть много других; ESP32-только первый, чтобы войти в мой разум здесь).

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

Тогда рабочий процесс будет немного другим. Предположим, что вы сохраняете одну точку данных на строку в виде текста:

  • Откройте файл и прочитайте одну строку. Закройте файл.
  • Разбор прочитанного текста на 2 переменные (время и температура)
  • Используйте эти переменные для оператора if сверху
  • если время загруженной точки данных было достигнуто, снова откройте файл, прочитайте следующую строку и проанализируйте ее в переменные
  • Оператор if теперь использует следующую точку данных

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

Есть готовые к использованию модули SD-карты, чтобы купить там, и вы можете найти много учебников о том, как их использовать в Интернете.


Как правильно выразился в комментариях Эдгар Бонет, можно значительно уменьшить необходимую оперативную память, если предположить регулярные интервалы (3 ч в вашем случае). Тогда вам не нужно экономить время для каждой точки данных. Вам нужно только одно время начала серии. Также выше я использовал float для температуры (как я и предполагал, что в этот момент вам будет легче всего). Но поскольку настройки температуры для термостатов в основном работают только до 1 цифры после десятичной точки, вы можете сэкономить место в памяти, используя другое представление. Например, вы можете сохранить температуру в виде целого числа со знаком в один байт с единицей измерения 0,1°C и разумным смещением (например, 25°C равно нулю). Таким образом, некоторые примеры значений будут следующими:

Temp | value
------------
18°C | -70
20°C | -50
22°C | -30
25°C | 0
27°C | 20
35°C | 100

Это даст вам точность одной цифры после десятичной точки и диапазон от 12,3°C до 37,8°C. При изменении коэффициента 0,1°Cвы также можете изменить диапазон (и точность с ним), как вам это действительно нужно.

Так что с вышеизложенным вам понадобится только 720 байт для фактических данных, что хорошо для Uno.

НО: я бы все равно предложил заглянуть в устройство чтения SD-карт. У вас будет больше работы по созданию проекта, но у вас не будет таких же хлопот с включением или обновлением данных. Это может быть особенно удобно, если вы хотите использовать для дальнейшего использования устройство после 3 месяцев. Просто загрузить на него новые данные (может быть, даже намного больше данных, например, на целый год) проще с помощью SD-карты.

,

Обратите внимание, что если время регулярно разнесено (одно заданное значение каждые 3 часа), их не нужно хранить. Температуры могут храниться в 16 битах с разрешением 0,001 °C, что, скорее всего, уже перебор., @Edgar Bonet

@EdgarBonet Спасибо, я добавил абзац об этом в свой ответ., @chrisl

@s_tatus3 Если вы собираетесь подключить ESP32 к своему Wi-Fi, вы также можете сохранить данные в SPIFFS и написать код, который позволит вам обмениваться данными через веб-сайт, размещенный на ESP32. Также может быть интересно для вас., @chrisl

Если вы считаете мой ответ правильным, вы можете принять его :), @chrisl

Фантастика! Да, определенно заменит Arduino на ESP32 и будет использовать данные на SD-карте. Уже установлено время эпохи (с ним лучше работать). Только что добавлена функция set_thermostat() для управления реле, и теперь вы увидите лучший способ установить время, чтобы легко использовать его много раз. void set_thermostat() { если (температура < данные[поз].температура) { Цифровая запись (реле, ВЫСОКАЯ); } иначе, если (температура > данные[поз].температура) { Цифровая запись (реле, НИЗКИЙ уровень); } } Вернусь сюда, чтобы добавить весь код, как только это будет сделано. Спасибо всем за комментарии и поддержку, @s_tatus3

@chrisl только что открыл этот вопрос связано с анализом SD-файла. Если у вас есть какое-то отличное представление о них, они будут приветствоваться! :), @s_tatus3