Главная » Arduino
Призовой фонд
на май 2017 г.
1. Тестер компонентов MG328
Паяльник
2. Осциллограф DSO138
Паяльник
3. Регулируемый паяльник 60 Вт
Паяльник
4. 100 руб.
От пользователей

Как СМСнуть обогревателю?

Winter is coming

Winter is coming, господа, а посему нужно начинать готовиться. Как говорится, готовь скетч с обогревателем летом, а скетч с кондиционером – зимой.

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

Подключаем безлимитный тариф SMS и вперед, к прогрессу.

Детали

Для создания нашего устройства нам потребуются:

  • Собственно, обогреватель, самый простой 

 

 

  • Troyka Shield. Уж больно он мне нравится. Все датчики подключаются легко и непринужденно.

  

  • Соединительные провода. Тут все немного сложнее.  Если хочется собрать готовое устройство, то термостат желательно сделать выносной. Для этого нужно сделать провода достаточно длинными, а можно соорудить беспроводной термостат. В целях обучения беспроводной связи я выбрал второй вариант.

Описание устройства

Наше устройство будет состоять из двух частей – термостата и центрального контроллера. Термостат будет посылать данные о температуре на центральное устройство, которое, в свою очередь, будет управлять реле и общаться со смартфоном посредством GPRS Shield.

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

Термостат

Начнем, пожалуй, с создания термостата. Наша задача – считывать показания температуры с DHT11 и передавать их на центральное устройство каждый фиксированный промежуток времени.

Задача поставлена – приступаем к выполнению. Соберем макет термостата.

Для эксперимента, соберем  макет центрального контроллера с единственной функцией – принятие сообщений от термостата. Это вид сверху. Под Troyka Shield находятся GPRS Shield и Arduino.

Может возникнуть вопрос – “А почему у приемника четыре пина, хотя используются только три?” Отвечаю – все просто, пин Data продублирован.

Теперь посмотрим на код передатчика.

//Подключаем библиотеки

#include <TroykaDHT11.h>
#include <VirtualWire.h>

//Определяем пин DHT11

DHT11 dht(11);

void setup() 
{

  Serial.begin(9600); 
  dht.begin();
  //Светодиод для индикации
  pinMode(13,OUTPUT);
  //требуется для DR3100
  vw_set_ptt_inverted(true); 
  //Обозначаем пин, к которому подключили приемник
  vw_set_rx_pin(12);
  //Установим скорость передачи
  vw_setup(4000);  
}

void loop()
{ 
  //Получаем температуру с DHT11
  String temp;
  dht.read();
  temp = dht.getTemperatureC();
  Serial.println(temp);
  //Приводим температуру к нужному для отправки виду
  char msg[10];
  temp.toCharArray(msg, 10);
  Serial.println(msg);
  //Отправляем сообщение
  digitalWrite(13, HIGH);
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx();
  digitalWrite(13, LOW);
  //Ждем немного
  delay(5000);
 
}

А вот код для приемника.

//Подключаем библиотеку

#include <VirtualWire.h>

//Создаем массив для передачи температуры

char temp[3];

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

    //требуется для DR3100
    vw_set_ptt_inverted(true); 
    //Обозначаем пин, к которому подключили приемник
    vw_set_rx_pin(12);
    //Установим скорость передачи
    vw_setup(4000);  
    //Светодиод для индикации
    pinMode(13, OUTPUT);
    //Стартуем
    vw_rx_start();    
    Serial.println("Setup");
}
    void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN]; // Буфер для сообщения
  uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера

  if (vw_get_message(buf, &buflen)) // Если принято сообщение
  {
  Serial.println("Received:"); 
  digitalWrite(13, HIGH);
  //По символу записываем принятое сообщение 
  for(int i = 0; i < buflen; i++)
  {
     temp[i] = buf[i];
  }
  //Выводим сообщение
  Serial.print("Temperature is ");
  Serial.print(temp);
  Serial.println(" C");
  digitalWrite(13, LOW);
 }
}

Как это работает?

Начнем с передатчика. Arduino Pro MINI запрашивает значение температуры с DHT11. Получив температуру, MINI готовит пакет для передачи. Для передатчика важна разрядность, поэтому в коде присутствует странная запись - uint8_t *

Не нужно пугаться -  это другой и более правильный вид записи типа данных byte или unsigned char.

Вот небольшая таблица такой записи типов данных.

 int8_t    |  char    |  от -128 до 127
 uint8_t   |  byte, unsigned char |  от 0 до 255
 int16_t   |  int    |  от -32768 до 32767
 uint16_t  |  unsigned int, word  |  от 0 до 65535 
 int32_t   |  long    |  от  -2147483648 до 2147483647 
 uint32_t  |  unsigned long    |  от 0 до 4294967295

Приведенное к требуемому типу данных, значение температуры начинает передаваться на передатчик, который, в свою очередь, отсылает сообщение в эфир.

Приемник отслеживает эфир на наличие сообщений и, если сообщение пришло, выводит пришедшее значение температуры в Serial Monitor .

Умный обогреватель

Пришло время заняться центральным устройством. Корпус устройства и конечное выполнение зависит только от ваших возможностей и фантазии, поэтому я лишь приведу схему, по которой можно собрать устройство. Под Troyka Shield также находятся GPRS Shield и Arduino.

Если кто не знает, как подключать нагрузку к реле – вот схема. Ну и для общего образования:

  • Коричневый провод – это фаза, синий – ноль.
  • По-хорошему, нужно всегда размыкать фазу, а не ноль. Если выключатель будет размыкать ноль, то может ударить током, если притронутся к фазе, а если это сеть с большим напряжением, то исход может быть летальным. Вы там осторожнее.

 

Запрограммируем устройство. Есть готовая библиотека для работы с GPRS Shield, поэтому передача сообщений становится достаточно тривиальной. Скачать библиотеку можно тут. Один минус – функция отправки SMS не принимает SMS в String, поэтому нам нужно переводить String в char array с помощью функции string.toCharArray(char, number);

//Подключаем необходимые библиотеки
//Для GPRG Shield

#include <GPRS_Shield_Arduino.h>
#include <SoftwareSerial.h>

//Для радиоприемника

#include <VirtualWire.h>

//Определяем пин, к которому подключено реле

#define RELAY 8

//Текущее состояние реле
 
bool stateRelay = false;

//Переменная для определения режима работы

int mode = 0;

//Переменная для ручного управления обогревателем

int m_temp = 0;

//Переменные для температуры
//Температура в данный момент

int curr_temp = 0;

//Температура срабатывания 

int trig_temp = 0;

//Нежелательная температура

int danger_temp = 36;

// создаём объект класса GPRS

GPRS gprs;

//Определяем номер, на который будем посылать сообщения
//Нужно ввести свой номер

#define PHONE_NUMBER "+XXXXXXXXXXX"

//Описываем сообщения для отправки

#define HELLO_MESSAGE "Hello from GPRS Shield! Please, set trigger temperature."
#define MODE_MESSAGE "Send mode's name."
#define READY_MESSAGE "I'm ready!"
#define INC_TRIG "Incorrect trigger value! You only can set - 20, 25 and 28."
#define INC_MODE "Incorrect mode value! You can only set - Auto and Manual"
#define DANGER_MESSAGE "Current temperature is bigger than 38C. Relay is off."
#define ERROR_SMS "Incorrect command. You can only ask for state, set trigger temperature or set mode"
#define HEATERON "OK, heater is on."
#define HEATEROFF "OK, heater is off."
#define AUTOMODE "OK, auto mode."
#define MANUALMODE "OK, manual mode."
#define OKTEMP "OK, trigger temperature changed"

String helloText = "Hello from GPRS Shield!";
String tempText = "Tempreature is ";
String termValue = String(curr_temp);
String degree = " C.";
String heaterOn = "Heater is On.";
String heaterOff = "Heater is Off.";
String message_to_send;
char char_message_to_send[60];

// текст сообщения
char message[160];
// номер, с которого пришло сообщение
char phone[16];
// дата отправки сообщения
char datetime[24];

void setup()
{
  //Определяем пины реле, светодиода, приемника
  
  pinMode(RELAY, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(RELAY, LOW);
  vw_set_ptt_inverted(true);
  vw_set_rx_pin(12);

  //Устанавливаем связь

  Serial.begin(9600);
  vw_setup(4000);
  vw_rx_start(); 

  Serial.println("Start");
  gprs.powerUpDown();
  
  while (!gprs.init()) 
   {
    delay(1000);
    Serial.println("Connecting");
   }
   
//Отправляем запрос температуры

 Serial.println("Connected");
 gprs.sendSMS(PHONE_NUMBER, HELLO_MESSAGE);
 Serial.println("Hello message sent");
 
 while(trig_temp == 0)
 {
  Serial.println("Waiting for trigger temperature");
    if (gprs.ifSMSNow()) 
   {
    gprs.readSMS(message, phone, datetime);
    sms_temp(message);
   } 
   delay(1000);
 }
 
 Serial.println("Trigger temperature assigned. Ask for mode name.");

 //Отправляем запрос режима
 
  gprs.sendSMS(PHONE_NUMBER, MODE_MESSAGE);
  
 while(mode == 0)
 {
   Serial.println("Waiting for mode");
   if (gprs.ifSMSNow()) 
   {
    gprs.readSMS(message, phone, datetime);
    sms_mode(message);   
   }
   delay(1000);
 }
  Serial.println("Mode assigned");

  gprs.sendSMS(PHONE_NUMBER, READY_MESSAGE);
}

void loop()
{
    //Ждем сообщения
    
    if (gprs.ifSMSNow()) 
   {
    gprs.readSMS(message, phone, datetime);
    Serial.println("Message");
    inc_sms(message);
   }
   //Получаем текущую температуру с термостата
   
   inc_temp();
   
   //Проверяем надобность включения реле
   
   relay();
}

//Включаем или выключаем реле

void relay()
{
  if(curr_temp < trig_temp && mode == 1)
  {
    digitalWrite(RELAY, HIGH);  
    stateRelay = true;
    delay(3000);
  }
   if(curr_temp >= trig_temp && mode == 1) 
  {
    digitalWrite(RELAY, LOW);
    stateRelay = false;
    delay(3000);
  }
  if(m_temp == 1 &&  mode == 2 && curr_temp < danger_temp)
  {
     digitalWrite(RELAY, HIGH);  
     stateRelay = true;
  }
  if(m_temp == 0 &&  mode == 2 || curr_temp >= danger_temp)
  {
     digitalWrite(RELAY, LOW);  
     stateRelay = false;
     if(curr_temp >= danger_temp)
     {
      Serial.println("DANGER!");
      gprs.sendSMS(PHONE_NUMBER, DANGER_MESSAGE);
      delay(60000);
     }
  }
}

//Проверяем входящее SMS

void inc_sms(char f_message[])
{
  if(strcmp(f_message, "State") == 0)
  {
    Serial.println("Calling for state function");
    state();
  }
  else if(strcmp(f_message, "HeaterOn") == 0)
  {
    m_temp = 1;
    gprs.sendSMS(PHONE_NUMBER, HEATERON);
  }
  else if(strcmp(f_message, "HeaterOff") == 0)
  {
    m_temp = 0;
    gprs.sendSMS(PHONE_NUMBER, HEATEROFF);
  }
  else if(strcmp(f_message, "Auto") == 0)
  {
    mode = 1;
    gprs.sendSMS(PHONE_NUMBER,AUTOMODE);
  }
  else if(strcmp(f_message, "Manual") == 0)
  {
    mode = 2;
    gprs.sendSMS(PHONE_NUMBER, MANUALMODE);
  }
  else if(strcmp(f_message, "20") == 0)
 {
  trig_temp = 20;
  gprs.sendSMS(PHONE_NUMBER, OKTEMP);
 }
 else if(strcmp(f_message, "25") == 0)
 {
  trig_temp = 25;
  gprs.sendSMS(PHONE_NUMBER, OKTEMP);
 }
 else if(strcmp(f_message, "28") == 0)
 {
  trig_temp = 28;
  gprs.sendSMS(PHONE_NUMBER, OKTEMP);
 }
  else 
  {
    Serial.println("Error");
    gprs.sendSMS(PHONE_NUMBER, ERROR_SMS);
    
  }
} 
 
//Устанавливаем режим

void sms_mode(char f_message[])
{
  if(strcmp(f_message, "Auto") == 0)
  {
    mode = 1;
  }
   else if(strcmp(f_message, "Manual") == 0)
  {
    mode = 2;
  }
  else
  {
    gprs.sendSMS(PHONE_NUMBER,INC_MODE);
  }
}
  
  /*
    Температура, которую нужно поддерживать.
    Я не буду делать так, чтобы можно было установить
    любую температуру срабатывания.
    Я выберу три - 20, 25 и 28.
    Вы можете выбирать режим на свое усмотрение.
  */
  void sms_temp(char f_message[])
{
 if(strcmp(f_message, "20") == 0)
 {
  trig_temp = 20;
 }
 else if(strcmp(f_message, "25") == 0)
 {
  trig_temp = 25;
 }
 else if(strcmp(f_message, "28") == 0)
 {
  trig_temp = 28;
 }
 else
 {
  gprs.sendSMS(PHONE_NUMBER,INC_TRIG);
 }
}

//Считываем температуру

void inc_temp()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN]; // Буфер для сообщения
  uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера
  char temp[3];
  
  if (vw_get_message(buf, &buflen)) // Если принято сообщение
  {
  Serial.println("Received:"); 
  digitalWrite(13, HIGH);
  for(int i = 0; i < buflen; i++)
  {
     temp[i] = buf[i];
  }
  curr_temp = atoi(temp);
  Serial.print("Temperature is ");
  Serial.print(temp);
  Serial.println(" C");
  digitalWrite(13, LOW);
 }
}

//Готовим и отправляем SMS со статусом

void state()
{
  if(stateRelay)
  {
    message_to_send = String(helloText + tempText + termValue + degree + heaterOn);
    message_to_send.toCharArray(char_message_to_send, 100);
    Serial.println("Sending");
    gprs.sendSMS(PHONE_NUMBER, char_message_to_send);
    Serial.println("Sent");
  }
  else if(!stateRelay)
  {
    message_to_send = String(helloText + tempText + termValue + degree + heaterOff);
    message_to_send.toCharArray(char_message_to_send, 100);
    Serial.println("Sending");
    gprs.sendSMS(PHONE_NUMBER, char_message_to_send);
    Serial.println("Sent");
  }
}

А оно как работает?

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

В это же время устройство ждет сообщений от хозяина. Если пришло сообщение о запросе статуса, то устройство отправляет нынешнее значение температуры и состояние реле, если пришло число, то устройство меняет температуру срабатывания, если пришло указание о смене режима – устройство меняет режим работы.

Вот небольшой кусок моего общения с обогревателем.

AT команды

GPRS Shield так же можно управлять с помощью AT команд. Вот небольшой скетч, который показывает, как можно отправить SMS.

void setup()
{

//Включаем GPRS Shield
  
gprs_On();

//Открываем Serial port для индикации...

Serial.begin(9600);

//...и Serila1 для общения с шилдом

Serial1.begin(9600);

while(!Serial)
{
}

    Serial.println("I'm ready");

    //Устанавливаем текстовый режим сообщений
    
    Serial1.print("AT+CMGF = 1\r");

    delay(3000);

    //Указываем номер, на который будем отправлять SMS
    //Не забудьте указать свой номер

    Serial1.println("AT + CMGS = \"+XXXXXXXXXXX\"");
    delay(300);
    
    // Пишем текст сообщения
    
    Serial1.println("AT Test");
    delay(300);
    
    // Отправляем Ctrl+Z, обозначая, что сообщение готово
    
    Serial1.println((char)26);
    Serial.println("SMS send!");

}

void loop() 
{
}

//Функция включения GPRS Shield

void gprs_On()
{
  // настраиваем пин №2 в режим выхода
  pinMode(2, OUTPUT);
  // проверяем состояние 3 пина
  if (digitalRead(3) != HIGH) {
    // если на нём «низкий уровень»
    // подаём на пин 2 «высокий уровень»
    digitalWrite(2, HIGH);
    // ждём 3 секунды
    delay(3000);
  }
  // подаём на пин 2 «низкий уровень»
  digitalWrite(2, LOW);
}

AT команды используются, если вам не хватает функционала готовых библиотек. С помощью AT команд, например, можно использовать часы реального времени, встроенные в GPRS Shield.

Если хочется общаться с GPRS Shield в режиме реального времени, то можно запустить пример из библиотеки под названием  GPRS_AT_Commands.

Чтобы узнать время у модуля, нужно отправить команду AT+CCLK?. Если вы включили Shield в первый раз или вынули из него батарейку, а потом включили, то ответом будет время, прошедшее после запуска GPRS Shileld.У меня ответом было это.

Для того чтобы установить время, нужно использовать команду AT+CCLK="YY/MM/DD,HH:MM:SS+ZZ"

Где YY – это год, MM – месяц, DD – день, HH – час, MM – минута, SS – секунда, ZZ – часовой пояс, причем, если сейчас сентябрь, то я должен вписывать 09, а не просто 9.Вот пример.

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

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

 

Итог

Теперь, на “А у нас в квартире газ” можно с гордостью ответить – “А у меня обогреватель доцент кафедры обогревательных наук!”

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

Ну а я с вами прощаюсь – до скорого!

Прикрепленные файлы:

Теги:

Опубликована: 0 1
Я собрал 0 2
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 5 Проголосовало: 2 чел.

Комментарии (5) | Я собрал (0) | Подписаться

0
Публикатор #
На форуме автоматически создана тема для обсуждения статьи.
Ответить
0
r9o-11 #
Надо же, сейчас как раз проверяю управление обогревом гаража, сделанном на таком же принципе, только всё заморочено на старом телефоне и без ардуины. Бывают же совпадения... Автору спасибо, и хоть в программировании не разбираюсь, но всё равно поставил по всем пунктам "пятёрочки".
Ответить
0
Аристократ #
Автор где достать эту плату Troyka Shield? Нигде не могу таких найти на алиэкспрессе, ебей, Герберст нет их. Или можно чем нибудь заменить?!
Ответить
0

[Автор]
Симилячник #
Не принципиально использовать Тройку. Ее плюс в том, что земля и питание выведеный на каждый трех-штырьевой контакт. Можно взять макетную плату и развести питание землю и управляющий пин на ней.
Кстати, первый ответ по запросу "Troyka shield" является ссылкой на сайт, где можно приобрести Тройку.
Аналогом на AliExpress будет являться Sensor Shield.
Ответить
0
аристократ #
А куда мне подключать провода GPRS Shield к Troyka shield? Скиньте схему если несложно
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется напряжение?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Raspberry Pi 2
Raspberry Pi 2
iMAX B6 - зарядное для Lion, LiPo, LiFe, Pb, NiCd и NiMH аккумуляторов Бокс для хранения компонентов
вверх