Теплый пол на Ардуино с Блютуз управлением

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

Для этого проекта потребуется:

  • Arduino Micro / Arduino Mega
  • SSR твердотельное реле
  • блютуз модуль HC-05 (HC-06)
  • модуль часов RTC DS1307
  • библиотеки EEPROM.h, iarduino_RTC.h и SoftwareSerial.h
  • андроид приложение tepluy_pol.apk

Перед тем, как собирать схему, установите на модуле часов реального времени DS1307 или DS3231 время и дату. В приложении не будет возможности изменить или настроить время. О том как настроить RTC модуль часов реального времени читайте здесь — Часы реального времени Ардуино. И прошейте Bluetooth модуль HC-05/HC-05 при необходимости, как это сделать читайте здесь — Прошивка Bluetooth модуля Ардуино

Теплый пол на Arduino с Bluethoot управлением

Схема управления теплым полом от Arduino с Bluethoot
Схема управления теплым полом от Arduino с Bluethoot
OLED i2c 0,96 Arduino Micro Arduino Mega
GND GND GND
VDD 5V 5V
SDA 2 20
SCL 3 21

В проекте используется плата Arduino Micro, так как на Uno и Nano недостаточно памяти для скетча. Обратите внимание, что на плате Arduino Micro порты SDA и SCL расположены на цифровых пинах 2 и 3. А для подключения выводов TX и RX у Блютуз модуля с библиотекой SoftwareSerial.h следует использовать порты на плате Micro, поддерживающие внешние прерывания (цифровые пины 8, 9, 10 или 11).

Сохранение настроек и переменных в памяти EEPROM

После сборки схемы следует записать в память ЕЕПРОМ настройки работы электрического теплого пола по умолчанию (потом их можно будет изменить через приложение на смартфоне). Переменные необходимо сохранить в EEPROM Arduino, чтобы при перезагрузке микроконтроллера после отключения электричества, все настройки не сбились, а были прочитаны из энергонезависимой памяти.

#include "EEPROM.h"

// === настройка температуры по умолчанию === //
int t_day = 16;           // температура пола днем
int t_night = 12;        // температура пола ночью
int t_light = 17; // температура при включении света
int air_day = 24;        // температура воздуха днем
int air_night = 20;     // температура воздуха ночью

// === настройка времени по умолчанию === //
int h_day = 10;    // время включения дневной температуры
int h_night = 22; // время включения ночной температуры

int delta = 2;  // на сколько градусов увеличить температуру (0, 2 или 3)
int mode = 1; // режим работы (0 - пол выключен, 1 - включен)

void setup() {
  Serial.begin(9600);
  // полностью очищаем еепром
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }
 
  // сохраняем данные в энергонезависимую память
  EEPROM.update(0, t_day);
  EEPROM.update(1, t_night);
  EEPROM.update(2, t_light);
  EEPROM.update(3, h_day);
  EEPROM.update(4, h_night);
  EEPROM.update(5, air_day);
  EEPROM.update(6, air_night);
  EEPROM.update(7, mode);
  EEPROM.update(8, delta);
  delay(1000);
 
  // выводим все данные на монитор порта
  Serial.println("t_day - " + String(EEPROM.read(0)));
  Serial.println("t_night - " + String(EEPROM.read(1)));
  Serial.println("t_light - " + String(EEPROM.read(2)));
  Serial.println("h_day - " + String(EEPROM.read(3)));
  Serial.println("h_night - " + String(EEPROM.read(4)));
  Serial.println("air_day - " + String(EEPROM.read(5)));
  Serial.println("air_night - " + String(EEPROM.read(6)));
  Serial.println("mode - " + String(EEPROM.read(7)));
  Serial.println("delta - " + String(EEPROM.read(8)));
}

void loop() {

}

Пояснения к коду:

  1. температуру пола указывайте на 2 градуса меньше комфортной для вас температуры, так как потом к ней будет добавляться переменная delta. При оптимальном режиме работы пола переменная будет равна двум.

Скетч для управления теплым полом от Arduino с Bluetooth

#include "EEPROM.h"
// подключаем модуль часов времени
#include "iarduino_RTC.h"
iarduino_RTC myRTC (RTC_DS1307);
// подключаем блютуз модуль
#include "SoftwareSerial.h"
SoftwareSerial hcSerial(8, 9); // RX, TX

// === основные настройки для работы программы === //
#define LED 10        // пин подключения светодиода
#define REL 13        // пин подключения реле
#define LM35F A0  // пин подключения датчика lm35
#define LM35A A3  // пин подключения датчика lm35
#define LDR A5       // пин подключения фоторезистора
int ldr = 800;            // уровень освещенности при включении света
float kvt = 0.50;      // мощность теплого пола в Квт
byte period = 10;   // через сколько секунд опрашивать датчик
// === далее, если нет опыта, ничего не меняем === // 

// переменные для счетчика энергии
int SEC, MIN, HOUR, CET;
// переменные для времени и даты
int hours, minuts, days, monts;
// переменные для режимов работы пола
int delta, mode, h_day, h_night;
// переменные для температуры работы пола
int t_day, t_night, t_light, air_day, air_night;
// переменные для опроса датчиков
float temp_f, temp_floor, temp_a, temp_air;
 
// переменные для работы программы
String h, m, d, mo, str, message;
int t_f, t_a;
float k_day, k_mon;
bool r, e;
char val;
unsigned long timer;

void setup() {
  Serial.begin(9600);
  hcSerial.begin(9600);
  myRTC.begin();
  // конфигурация пинов платы
  pinMode(LDR, INPUT);
  pinMode(LM35F, INPUT);
  pinMode(LM35A, INPUT);
  pinMode(REL, OUTPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
 
  // выполняем цикл, если с блютуз модуля пришла информация
  while (hcSerial.available()) {
    val = hcSerial.read();
    // переходим в функцию сохранения температуры
    if (val == '*') {
      temp();
      break;
    }
    // переходим в функцию сохранения времени
    if (val == '^') {
      vremya();
      break;
    }
    // включаем low режим, обновляем переменную delta
    if (val == '=') {
      delta = 0;
      EEPROM.update(8, delta);
      job();
      break;
    }
    // включаем high режим, обновляем переменную delta
    if (val == '%') {
      delta = 3;
      EEPROM.update(8, delta);
      job();
      break;
    }
    // включаем пол, обновляем переменные delta и mode
    if (val == '+') {
      delta = 2;
      mode = 1;
      EEPROM.update(7, mode);
      EEPROM.update(8, delta);
      job();
      break;
    }
    // выключаем пол, обновляем переменные delta и mode
    if (val == '-') {
      delta = 2;
      mode = 0;
      EEPROM.update(7, mode);
      job();
      break;
    }
    str = str + val;
  }
 
  // запускаем отсчет таймера
  if (millis() - timer > 1000) {
    timer = millis();
    CET++;
    // если реле включено, то ведем подсчет секунд
    if (r == 1) { 
      SEC = SEC + 1;
      if (SEC == 59) {
        SEC = 0;
        MIN = MIN + 1;
      }
      if (MIN == 59) {
        MIN = 0;
        HOUR = HOUR + 1;
      }
    }
  }
 
  // ежедневно обновляем и сохраняем киловатты в еепром
  if (hours == 23 and minuts == 58) { e = 1; }
  if (hours == 23 and minuts == 59) {
    SEC = 0; MIN = 0; HOUR = 0;
    if (e == 1) {
      k_mon = EEPROM_float_read(monts * 10);
      k_mon = k_mon + k_day;
      if (days == 1) { k_mon = 0.00; }
      EEPROM_float_write(monts * 10, k_mon);
      k_day = 0.00;
    }
  }
 
  // если прошло заданное количество секунд выполняем функцию job
  if (CET == period) {
    CET = 0;
    job();
  }
}

// === функция сохранения времени в еепром === //
void vremya() {
  message = str;
  message.remove(2, 2);
  h_day = message.toInt();
  message = str;
  message.remove(0, 2);
  h_night = message.toInt();
  EEPROM.update(3, h_day);
  EEPROM.update(4, h_night);
  job();
}

// === функция сохранения температуры в еепром === //
void temp() {
  message = str;
  message.remove(2, 8);
  t_day = message.toInt();
  message = str;
  message.remove(0, 2);
  message.remove(2, 6);
  t_night = message.toInt();
  message = str;
  message.remove(0, 4);
  message.remove(2, 4);
  t_light = message.toInt();
  message = str;
  message.remove(0, 6);
  message.remove(2, 2);
  air_day = message.toInt();
  message = str;
  message.remove(0, 8);
  air_night = message.toInt();
  EEPROM.update(0, t_day);
  EEPROM.update(1, t_night);
  EEPROM.update(2, t_light);
  EEPROM.update(5, air_day);
  EEPROM.update(6, air_night);
  job();
}
 
// === функция опроса датчиков и включения реле === //
void job() {
 
  // несколько раз опрашиваем датчик температуры пола
  temp_floor = 0;
  for (byte i = 0; i <= 4; i++) {
    temp_f = ( analogRead(LM35F) / 1023.0 ) * 5.0 * 1000 / 10;
    temp_floor = temp_floor + temp_f;
  }
  t_f = temp_floor / 5;
 
  // несколько раз опрашиваем датчик температуры воздуха
  temp_air = 0;
  for (byte i = 0; i <= 4; i++) {
    temp_a = ( analogRead(LM35A) / 1023.0 ) * 5.0 * 1000 / 10;
    temp_air = temp_air + temp_a;
  }
  t_a = temp_air / 5;

  // получаем настройки из еепром и модуля часов
  t_day = EEPROM.read(0);
  t_night = EEPROM.read(1);
  t_light = EEPROM.read(2);
  h_day = EEPROM.read(3);
  h_night = EEPROM.read(4);
  air_day = EEPROM.read(5);
  air_night = EEPROM.read(6);
  mode = EEPROM.read(7);
  delta = EEPROM.read(8);
  h = myRTC.gettime("H");
  m = myRTC.gettime("i");
  d = myRTC.gettime("d");
  mo = myRTC.gettime("m");
  hours = h.toInt();
  minuts = m.toInt();
  days = d.toInt();
  monts = mo.toInt();
  k_day = (HOUR * 60 + MIN) / 60.00 * kvt;

  // отправляем всю информацию через блютуз модуль
  hcSerial.println("T-AIR: " + String(t_a) + "°C");
  hcSerial.println("T-POL: " + String(t_f) + "°C");
  hcSerial.println("LDR: " + String(analogRead(LDR)));
  hcSerial.println("t_day = " + String(t_day + delta));
  hcSerial.println("t_night = " + String(t_night + delta));
  hcSerial.println("t_light = " + String(t_light + delta));
  hcSerial.println("h_day = " + String(h_day));
  hcSerial.println("h_night = " + String(h_night));
  hcSerial.println("air_day = " + String(air_day));
  hcSerial.println("air_night = " + String(air_night));
  hcSerial.println(myRTC.gettime("H:i:s"));
  hcSerial.println("time = " + String(HOUR) + "-" + String(MIN));
  hcSerial.println("today = " + String(k_day) + " kv");
  hcSerial.println("month = " + String(EEPROM_float_read(monts * 10)) + " kv");
  hcSerial.println("m = " + String(mode));
  hcSerial.println("d = " + String(delta));

  // в зависимости от времени и температуры меняем переменную r
  if (hours >= h_day and hours < h_night) {
    if (t_f < t_day + delta) { r = 1; }
    if (t_f > t_day + delta or t_a > air_day + 1) { r = 0; }
  }
  if (hours < h_day or hours >= h_night) {
    if (t_f < t_night + delta) { r = 1; }
    if (t_f > t_night + delta or t_a > air_night + 1) { r = 0; }
  }
 
  // проверяем включен ли свет
  if (analogRead(LDR) > ldr and t_f < t_light + delta) { r = 1; }
  if (analogRead(LDR) < ldr and t_f > t_light + delta) { r = 0; }
 
  // проверяем, что пол не был выключен
  if (mode == 0) { r = 0; }

  // в зависимости от переменной r1 включаем или выключаем пол
  if (r == 0) {
    digitalWrite(REL, LOW);
    digitalWrite(LED, LOW);
    hcSerial.println("RELE: OFF");
  }
  if (r == 1) {
    timer = millis();
    digitalWrite(REL, HIGH);
    digitalWrite(LED, HIGH);
    hcSerial.println("RELE: ON");
  }

  str = "";
}

// === функция сохранения киловатт в еепром (переменная float) === //
void EEPROM_float_write(int addr, float val) {
  byte *x = (byte *)&val;
  for (byte i = 0; i < 4; i++) EEPROM.write(i + addr, x[i]);
  e = 0;
}
 
// === функция чтения киловатт из еепром (переменная float) === //
float EEPROM_float_read(int addr) {
  byte x[4];
  for (byte i = 0; i < 4; i++) x[i] = EEPROM.read(i + addr);
  float *y = (float *)&x;
  return y[0];
}

Пояснения к коду:

  1. при необходимости в скетче следует изменить порты подключения датчиков и модулей к микроконтроллеру Ардуино Микро;
  2. также в скетче следует указать значение с аналогового входа A5 к которому подключен фоторезистор при включенном свете (переменная ldr), указать мощность электрического пола в Киловаттах (переменная kvt), а также период опроса датчиков в секундах (переменная period).

Приложение для управления теплым полом со смартфона

Проект позволяет узнать сколько был включен теплый пол в течении суток, Ардуино переводит время в Киловатты и отправляет информацию на смартфон. Ежедневно в 23:59 информация о потраченных Киловаттах суммируется с месячными расходами и сохраняется в EEPROM. Каждый месяц 1 числа месячный расход Киловатт обнуляется. При перезагрузке Ардуино суточный расход электроэнергии обнулится.

Скриншот приложения для управления теплым полом
Скриншот приложения для управления теплым полом со смартфона

Кроме информации с датчиков в режиме реального времени и возможности настройки работы электрического теплого пола по времени суток. Приложение позволяет дистанционно включить или выключить электрический пол (в приложении переменная m, в скетче — mode), а также перевести нагрев в экономный (LOW) режим или усиленный (HIGH) за счет изменения переменной d (в скетче это переменная delta).

Заключение. Обязательно убедитесь, что твердотельное реле сможет выдержать нагрузку от нагревательных матов. Также в программе предусмотрено дополнительное включение светодиода на 10 пине при включении реле (на схеме светодиод не изображен). Это может понадобиться для индикации работы электрического пола. Все вопросы по проекту можно оставлять в комментариях к этой записи.



18 Replies to “Теплый пол на Ардуино с Блютуз управлением”

  1. Перед прошивкой б.т модуль надо отключить.потомучто о передаёт данные через Tx RX

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

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

  3. подскажите какие пины использовать для подключения к плате ( у меня ардуино мега) пины микро и мега немного отличаются

    1. На Ардуино Мега не получится использовать программный порт с библиотекой SoftwareSerial.h, лучше возьмите плату Уно или Нано. Тогда не придется переписывать программу

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

    1. До этого подключали Блютуз к Ардуино? Ищите ошибку в подключении Блютуз модуля.

      1. может ли быть причиной версия Блютуз? НС-05 v3.0, а телефон v4.0 и выше.
        Если использовать модуль НС-08 или НМ10, приложение на телефоне будет работать?

  5. Запустил проект, блютуз работает,с телефоном сопрежен, а в приложение нажимаю подключить влютуз и там открывается окно и тёмный экран

  6. Добрый вечер , все элементы подключил правильно загружаю 2-ой код и ничего не работает в приложении не показывается температура, и в целом всё устройство не работает , даже реле не отрабатывает по команде с телефона , делаю на ардуино уно

        1. На Arduino Micro порты SDA и SCL расположены на пинах 2 и 3, на Arduino Uno порты SDA и SCL расположены на пинах A4 и A5. Если все правильно подключите, может и заработает тогда. Еще попробуйте порты D8 и D9 поменять местами

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

    в общем хочу углубиться конкретно. Благо с запросом все в порядке ))) конкретные проекты есть.

    Посоветуйте литературу.

    еще раз благодарю всех кто развивается сам и делится опытом!

  8. Здравствуйте. Почему Вы говорите, что Нано не подойдёт из-за памяти? Флэшки там одинаково с Микро, а оперативка различается совсем на чуть-чуть.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.