Управление теплицей или оранжереей из любой точки планеты

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

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

В проекте используется Arduino UNO и WiFi модуль ESP8266-01. Данные будут передаваться на облако посредством веб сервиса ThingSpeak.com, а устройства будут активироваться посредством андроид приложения, разработанного с помощью MIT AppInventor.

Управление теплицей или оранжереей из любой точки планеты (пример реализации)



IoT- концепция вычислительной сети физических предметов («вещей»), оснащённых встроенными технологиями для взаимодействия друг с другом или с внешней средой, рассматривающая организацию таких сетей как явление, способное перестроить экономические и общественные процессы, исключающее из части действий и операций необходимость участия человека.



Главным центром этого IoT проекта будет сервис ThingSpeak.com. Локальное устройство UNO/ESP-01 принимает данные с сенсоров и данные о состоянии исполнительных механизмов, отправляет их в интернет «записывая» через определенный канал статуса ThingSpeak.com (ThingSpeak.com Status Channel), так же это же локальное устройство принимает данные, «читая» их из другого канала данных- “канал исполнительных устройств” (ThingSpeak.com Actuator Channels).



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

Исполнительных устройства будет два – это водяной электрический насос и лампа. Их статус “ВКЛ/ВЫКЛ” так же будет отправляться на облако. Данные с сенсоров, например, могут отображать текущее состояние теплицы или оранжереи. Исполнительными устройствами пользователь будет управлять с помощью андроид приложения.



2 Список необходимых компонентов

Arduino UNO ( микроконтроллер)
ESP8266-01 (коммуникационный модуль)
DHT22 (датчик относительной влажности воздуха)
DS18B20 (1-Wire цифровой датчик температуры, используется для измерения температуры почвы)
YL-69 + LM393 (Датчик влажности почвы)
LDR (датчик освещенности)
2 x светодиоды (красный и зеленый)
1 x 2-х канальное релейный модуль DC 5V Relay
5V DC насос - $3.00
220V лампа
2 x 330 ohm резистор (используется со светодиодами)
2 x 10K ohm резистор (используется с DHT22 и LDR)
1 x 4K7 ohm резистор (используется с DS18B20)
Макетная плата
Перемычки
Вешний блок питания для реле 5V DC

3 Железная часть



Теперь надо подключить все сенсоры, как показано на схеме.



Идеальным решением было бы собирать и тестировать проект по частям.

В следующей последовательности:
1. Установить и протестировать все сенсоры
2. Установить и минимально сконфигурировать ESP-01
3. Изменить установку ESP-01 для финальной конфигурации и протестировать
4. Сконфигурировать ThingSpeak Status Channel
5. Установить ThingSpeak код на Arduino и проверить статус сенсоров на облаке
6. Разработать первую версию программы на андроид для проверки статусных сообщений от сенсоров
7. Установить исполнительные устройства
8. Сконфигурировать ThingSpeak Actuators channels
9. Установить и протестировать на Arduino код для исполнительных устройств
10. Сделать вторую версию программы на андроид для всего устройства в сборе.

4 Подключение сенсоров





В проекте используются некоторые библиотеки, которые входят в Arduino IDE . Необходимо проверить их наличие. Первоначальная конфигурация этих библиотек выглядит так:

// DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5 // DS18B20 on pin D5 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
int soilTemp = 0;
//DHT
#include "DHT.h"
#include <stdlib.h>
int pinoDHT = 11;
int tipoDHT = DHT22;
DHT dht(pinoDHT, tipoDHT); 
int airTemp = 0;
int airHum = 0;
// LDR (Light)
#define ldrPIN 1
int light = 0;
// Soil humidity
#define soilHumPIN 0
int soilHum = 0;



Теперь инициализируем наши сенсоры и будем выводить их на дисплей в терминале:

void setup()
{
 Serial.begin(9600); 
 DS18B20.begin();
 dht.begin();
}
void loop()
{
 readSensors();
 displaySensors();
 delay (10000);
}


И наконец, напишем две функции: одна считывает показания с сенсоров, а другая выводит их на экран:

/********* Read Sensors value *************/
void readSensors(void)
{
 airTemp = dht.readTemperature();
 airHum = dht.readHumidity();
 DS18B20.requestTemperatures(); 
 soilTemp = DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius
 
 soilHum = map(analogRead(soilHumPIN), 1023, 0, 0, 100); 
 
 light = map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% 
}
/********* Display Sensors value *************/
void displaySensors(void)
{
 Serial.print ("airTemp (oC): ");
 Serial.println (airTemp);
 Serial.print ("airHum (%): ");
 Serial.println (airHum);
 Serial.print ("soilTemp (oC): ");
 Serial.println (soilTemp);
 Serial.print ("soilHum (%): ");
 Serial.println (soilHum);
 Serial.print ("light (%): ");
 Serial.println (light);
 Serial.println ("");
}



На фото видно как выводятся данные на экран.



Исходный код можно скачать на GITHUB автора

4 ESP8266-01 базовая конфигурация



Самый быстрый способ «пообщаться» с модулем это АТ команды. В модуль уже встроен процессор АТ команд. По умолчанию модуль идет с заводскими настройками 115200 бод, надо выставить в настройках 9600 бод.

Во-первых, надо подключить модуль, как показано на фото



( Обратите внимание, что вывод Тх модуля ESP-01 подключен к выводу Тх UNO, так же как и выводы Rx подключены друг к другу. Позже это подключение будет изменено ).

Затем подключите UNO к компьютеру, откройте IDE и загрузите пример, который находится File> Examples> 01.Basics> BareMinimum. Это пустой код, для того, чтобы не было конфликтов между ESP-01 и UNO. Этот код залили в Ardunio до того, как подключить к нему ESP-01, для того чтобы быть точно уверенными, что Ardunio не будет использовать выводы Тх и Rx для чего-то еще.
Теперь надо открыть IDE Serial Monitor, выставить в настройках скорость передачи данных 115200 бод и отправить команду AT в IDE Serial Monitor. ESP-01 должен прислать ответ ОК

Теперь надо изменить скорость передачи данных в модуле ESP-01. Для этого в IDE дайте команду

AT + CIOBAUD = 9600



Возможно, случится так, что ESP-01 вернется к заводским настройкам, тогда надо будет использовать другую команду:

AT+ UART_DEF=<baudrate>,<databits>,<stopbits>,<parity>,<flow control>



На пример 9600 baud / 8 data bits / 1 stop bits and none parity and flow control

AT + UART_DEF = 9600,8,1,0,0



Теперь измените скорость передачи данных в настройках IDE на 9600 и отправьте команду АТ, должен придти ответ ОК.
Далее надо переключить модуль в режим STA для того, чтобы он мог подключиться к точке доступа вашей сети.

AT + CWMODE = 1



Чтобы модуль подключился к сети введите команду AT + CWJAP = "network_name", "network_name_1", где network_name – имя вашей сети, а network_name_1 – пароль к вашей сети (пароль и имя сети должны быть в кавычах)
Если вы видите ответ WIFI CONNECTED WIFI GOT IP, значит соединение установлено. Проверьте IP адрес командой

AT + CIFSR

.

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



• ESP-01 RX (Yellow) --> UNO Pin D7
• ESP-01 TX (Orange) --> UNO Pin D6
• ESP-01 Ch-Pd (Brown) --> Vcc (3.3V)
• ESP-01 Reset (Blue) --> UNO Pin D8
• ESP-01 Vcc (Red) --> 3.3V
• ESP-01 Gnd (Black) --> UNO GND

Обратите внимание, что библиотека Software Serial использует вывод UNO Pin D7 как TX и соединяется он с выводом ESP-01 RX, а UNO Pin D6 как RX, соединенный с ESP-01 TX.

Введите не большой код, для того, чтобы проверить правильность подключения и настройки модуля ESP-01

#include <SoftwareSerial.h> 
SoftwareSerial esp8266(6,7); //Rx ==> Pin 6; TX ==> Pin7 
#define speed8266 9600 
void setup() 
{
 esp8266.begin (speed8266); 
 Serial.begin(speed8266);
 Serial.println("ESP8266 Setup test - use AT coomands");
}
void loop() 
{
 while(esp8266.available())
 {
 Serial.write(esp8266.read());
 }
 while(Serial.available())
 {
 esp8266.write(Serial.read());
 }
}



Теперь несколько АТ команд. Смотрите за результатами в Serial Monitor.



* AT =====> ESP8266 returns OK
* AT+RST =====> ESP8266 restart and returns OK
* AT+GMR =====> ESP8266 returns AT Version; SDK version; id; OK
* AT+CWMODE? => ESP8266 returns mode type
* AT+CWLAP ===> ESP8266 returns close access points
* AT+CIFSR ===> ESP8266 returns designided IP

Код программы можно скачать по адресу

6 подключение сенсоров и ESP-01




После того, как все сенсоры подключены и проверены, а так же проверен модуль ESP-01, надо подготовить данные к отправке в интернет.

7 ThingSpeak





Одной из важнейших частей проекта является открытая платформа IoT, которая позволит собирать данные с сенсоров, обрабатывать и анализировать их. Для этого надо перейти по ссылке и создать свой аккаунт. Далее надо создать канал, где будут 2 исполнительных устройства, 5 сенсоров и одно резервное поле.
• Field 1: Actuator 1(устройство 1)
• Field 2: Actuator 2 (устройство 2)
• Field 3: Air Temperature in oC (температура воздуха в градусах цельсия)
• Filed 4: Air Relative Humidity in % (Относительная влажность воздуха в %)
• Field 5: Soil Temperature in oC (Температура почвы в гр. Цельсия)
• Field 6: Soil Humidity in % (влажность почвы в %)
• Field 7: Luminosity in % (освещенность в % )
• Field 8: Spare

Поле 8 оставлено для будущего расширения или для отладки. Данном проекте оно используется как счетчик ошибок связи между Arduino/ESP-01 и ThingSpeak.com.

Как только вы создали канал Status Channel, нужно обязательно записать ключи, как показано на фото.

8 Отправка статуса сенсоров в облако



На данный момент у нас есть настроенный облачный сервис и наши датчики собирают данные локально. Теперь надо взять эти данные и переслать их в облако на ThingSpeak.com.

Для того, чтобы писать данные в канал ThingSpeak, надо отправить строку GET. Это будет делаться в три этапа
Отправим команду «Start cmd»

AT+CIPSTART="TCP","184.106.153.149",80


Далее длина строки

AT+CIPSEND=116



И наконец, строка GET, которая будет писать наши данные в зарезервированных полях Status Channel.

GET /update?api_key=Ваш_сохраненный_ключ_здесь&field1=pump&fieldlamp=0&field3=airTemp&field4=airHum&field5=soilTemp&field6=soilHum&field7=light&field8=spare



Обратите внимание, что мы не должны писать данные в канал чаще 1 раза в 16 секунд.

Представленый код будет выполнять все это.

// Thingspeak 
String statusChWriteKey = "YOUR WRITE KEY HERE"; // Status Channel id: 385184
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(6, 7); // Rx, Tx
#define HARDWARE_RESET 8
// DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5 // DS18B20 on pin D5 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
int soilTemp = 0;
//DHT
#include "DHT.h"
#include <stdlib.h>
int pinoDHT = 11;
int tipoDHT = DHT22;
DHT dht(pinoDHT, tipoDHT); 
int airTemp = 0;
int airHum = 0;
// LDR (Light)
#define ldrPIN 1
int light = 0;
// Soil humidity
#define soilHumPIN 0
int soilHum = 0;
// Variables to be used with timers
long writeTimingSeconds = 17; // ==> Define Sample time in seconds to send data
long startWriteTiming = 0;
long elapsedWriteTime = 0;
// Variables to be used with Actuators
boolean pump = 0; 
boolean lamp = 0; 
int spare = 0;
boolean error;
void setup()
{
 Serial.begin(9600);
 
 pinMode(HARDWARE_RESET,OUTPUT);
 
 digitalWrite(HARDWARE_RESET, HIGH);
 
 DS18B20.begin();
 dht.begin();
 EspSerial.begin(9600); // Comunicacao com Modulo WiFi
 EspHardwareReset(); //Reset do Modulo WiFi
 startWriteTiming = millis(); // starting the "program clock"
}
void loop()
{
 start: //label 
 error=0;
 
 elapsedWriteTime = millis()-startWriteTiming; 
 
 if (elapsedWriteTime > (writeTimingSeconds*1000)) 
 {
 readSensors();
 writeThingSpeak();
 startWriteTiming = millis(); 
 }
 
 if (error==1) //Resend if transmission is not completed 
 { 
 Serial.println(" <<<< ERROR >>>>");
 delay (2000); 
 goto start; //go to label "start"
 }
}
/********* Read Sensors value *************/
void readSensors(void)
{
 airTemp = dht.readTemperature();
 airHum = dht.readHumidity();
 DS18B20.requestTemperatures(); 
 soilTemp = DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius
 
 light = map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% 
 soilHum = map(analogRead(soilHumPIN), 1023, 0, 0, 100); 
}
/********* Conexao com TCP com Thingspeak *******/
void writeThingSpeak(void)
{
 startThingSpeakCmd();
 // preparacao da string GET
 String getStr = "GET /update?api_key=";
 getStr += statusChWriteKey;
 getStr +="&field1=";
 getStr += String(pump);
 getStr +="&field2=";
 getStr += String(lamp);
 getStr +="&field3=";
 getStr += String(airTemp);
 getStr +="&field4=";
 getStr += String(airHum);
 getStr +="&field5=";
 getStr += String(soilTemp);
 getStr +="&field6=";
 getStr += String(soilHum);
 getStr +="&field7=";
 getStr += String(light);
 getStr +="&field8=";
 getStr += String(spare);
 getStr += "\r\n\r\n";
 sendThingSpeakGetCmd(getStr); 
}
/********* Reset ESP *************/
void EspHardwareReset(void)
{
 Serial.println("Reseting......."); 
 digitalWrite(HARDWARE_RESET, LOW); 
 delay(500);
 digitalWrite(HARDWARE_RESET, HIGH);
 delay(8000);//Tempo necessário para começar a ler 
 Serial.println("RESET"); 
}
/********* Start communication with ThingSpeak*************/
void startThingSpeakCmd(void)
{
 EspSerial.flush();//limpa o buffer antes de começar a gravar
 
 String cmd = "AT+CIPSTART=\"TCP\",\"";
 cmd += "184.106.153.149"; // Endereco IP de api.thingspeak.com
 cmd += "\",80";
 EspSerial.println(cmd);
 Serial.print("enviado ==> Start cmd: ");
 Serial.println(cmd);
 if(EspSerial.find("Error"))
 {
 Serial.println("AT+CIPSTART error");
 return;
 }
}
/********* send a GET cmd to ThingSpeak *************/
String sendThingSpeakGetCmd(String getStr)
{
 String cmd = "AT+CIPSEND=";
 cmd += String(getStr.length());
 EspSerial.println(cmd);
 Serial.print("enviado ==> lenght cmd: ");
 Serial.println(cmd);
 if(EspSerial.find((char *)">"))
 {
 EspSerial.print(getStr);
 Serial.print("enviado ==> getStr: ");
 Serial.println(getStr);
 delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando
 String messageBody = "";
 while (EspSerial.available()) 
 {
 String line = EspSerial.readStringUntil('\n');
 if (line.length() == 1) 
 { //actual content starts after empty line (that has length 1)
 messageBody = EspSerial.readStringUntil('\n');
 }
 }
 Serial.print("MessageBody received: ");
 Serial.println(messageBody);
 return messageBody;
 }
 else
 {
 EspSerial.println("AT+CIPCLOSE"); // alert user
 Serial.println("ESP8266 CIPSEND ERROR: RESENDING"); //Resend...
 spare = spare + 1;
 error=1;
 return "error";
 } 
}


Вы можете посмотреть ход выполнения в Serial Monitor.


Исходный код можно скачать по адресу

9 приложение для андроид- часть первая



Сначала надо создать пользовательский интерфейс. На картинке показаны основные видимые и невидимые элементы.



После этого надо создать блоки. Пункты меню соответствуют номерам скриншотов.

1 Переменные состояния, которые должны быть объявленные как глобальные

2 Каждые две секунды (зависит от Clock1) вызывается процедура "readArduino"



Процедура возвращает значение переменных которые должны будут отобразится на экране. При этом значение состояния (0 и 1) для исполнительных устройств преобразуются в «ВКЛ» и «ВЫКЛ» для лучшего восприятия.

Эти значения (Status) будут отображаться в соответствующих «Ярлыках»

3 Процедура «readArduino», по сути, будет читать канал состояния в ThingSpeak. Итак, надо определить URL-адрес, который будет отправлен в Thingspeak. Для этого должны быть объявлены 3 глобальных переменные и объединены для создания URL-адреса, который будет отправлен в ThingSpeak. GET следует отправить в веб-компонент под названием «ArduFarmBotStatusCh»

4 Текст, полученный из предыдущей команды, поступит в формате JSon. Этот текст необходимо обработать, чтобы каждое поле было прочитано и сохранено в соответствующей глобальной переменной.


5 Последнее, что нужно сделать, это вызвать процедуру «Тревога», которая будет анализировать состояние двух датчиков почвы. Если температура слишком низкая (в нашем случае 10oC), должно отображаться сообщение. То же самое для влажности, если она ниже 60%.

Обратите внимание на то, что мы определили еще один таймер (Clock2), запрограммированный на то, чтобы он запускался каждую секунду. Он нужен только для «переключения» цвета текста сообщения (от белого к красному). Сообщение будет «мигать».


Код приложения можно скачать по ссылке

10 Подключение исполнительных устройств




Команды включения и выключения насоса и лампы будут приниматься дистанционно. Выход Ardunio, будет активировать реле и светодиод, принимая эти команды. На картинке показано, как должны быть подключены исполнительные устройства. Обратите внимание, что вывод GND реле НЕ ПОДКЛЮЧЕН к выводу GND UNO. Так будет меньше помех по питанию при работе реле.

11 конфигурирование канала исполнительных устройств (Actuators Channels)




Все действия повторяют процедуру конфигурирования канала Status. Надо создать два канала для каждого из устройств. Для каждого канала надо записать Channel ID, Read и Write ключи. Мы будем писать только в первое поле каждого канала. Для примера:
Channel ID 375598 ==> LED Red (Pump)
◦ Field1 = 0 ==> Pump OFF
◦ Field1 = 1 ==> Pump ON
2. Channel ID 375599 ==> LED Green (Lamp)
◦ Field1 = 0 ==> Lamp OFF
◦ Field1 = 1 ==> Lamp ON

11 загрузка и тестирование кода исполнительных устройств в Ardunio.


Когда мы отправляли данные в облако, то мы «писали» эти данные в канал статуса (Status Channel) ThingSpeak., «передавая» (выгружая) эти данные. Теперь мы должны «прочитать» данные из канала исполнительных устройств (Actuator Channel), «принимая» (загружая) эти данные.

Для этого необходимо отправить строку GET и эта процедура состоит из 3 этапов.
"Start cmd"

AT+CIPSTART="TCP","184.106.153.149",80


Длина строки

AT+CIPSEND=36


И сама строка GET

GET /channels/375598/fields/1/last


Каналы будут «читаться» раз в 10 секунд

После отправки GET мы должны принять ответ от ThingSpeak. Ответ должен быть либо 0, либо 1, для каждого из каналов. Если будут какие-то другие значения, то их просто игнорируем.

Основное различие между этой частью и предыдущей только в функции readThingSpeak(String channelID)
Ниже приведен код который выполняет описаные действия.

// Thingspeak 
String canalID1 = "999999"; //Actuator1
String canalID2 = "999999"; //Actuator2
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(6, 7); // Rx, Tx
#define HARDWARE_RESET 8
// Variables to be used with timers
long readTimingSeconds = 10; // ==> Define Sample time in seconds to receive data
long startReadTiming = 0;
long elapsedReadTime = 0;
//Relays
#define ACTUATOR1 10 // RED LED ==> Pump
#define ACTUATOR2 12 // GREEN LED ==> Lamp
boolean pump = 0; 
boolean lamp = 0; 
int spare = 0;
boolean error;
void setup()
{
 Serial.begin(9600);
 
 pinMode(ACTUATOR1,OUTPUT);
 pinMode(ACTUATOR2,OUTPUT);
 pinMode(HARDWARE_RESET,OUTPUT);
 digitalWrite(ACTUATOR1, HIGH); //o módulo relé é ativo em LOW
 digitalWrite(ACTUATOR2, HIGH); //o módulo relé é ativo em LOW
 digitalWrite(HARDWARE_RESET, HIGH);
 EspSerial.begin(9600); // Comunicacao com Modulo WiFi
 EspHardwareReset(); //Reset do Modulo WiFi
 startReadTiming = millis(); // starting the "program clock"
}
void loop()
{
 start: //label 
 error=0;
 
 elapsedReadTime = millis()-startReadTiming; 
 if (elapsedReadTime > (readTimingSeconds*1000)) 
 {
 int command = readThingSpeak(canalID1); 
 if (command != 9) pump = command; 
 delay (5000);
 command = readThingSpeak(canalID2); 
 if (command != 9) lamp = command; 
 takeActions();
 startReadTiming = millis(); 
 }
 
 if (error==1) //Resend if transmission is not completed 
 { 
 Serial.println(" <<<< ERROR >>>>");
 delay (2000); 
 goto start; //go to label "start"
 }
}
/********* Take actions based on ThingSpeak Commands *************/
void takeActions(void)
{
 Serial.print("Pump: ");
 Serial.println(pump);
 Serial.print("Lamp: ");
 Serial.println(lamp);
 if (pump == 1) digitalWrite(ACTUATOR1, LOW);
 else digitalWrite(ACTUATOR1, HIGH);
 if (lamp == 1) digitalWrite(ACTUATOR2, LOW);
 else digitalWrite(ACTUATOR2, HIGH);
}
/********* Read Actuators command from ThingSpeak *************/
int readThingSpeak(String channelID)
{
 startThingSpeakCmd();
 int command;
 // preparacao da string GET
 String getStr = "GET /channels/";
 getStr += channelID;
 getStr +="/fields/1/last";
 getStr += "\r\n";
 String messageDown = sendThingSpeakGetCmd(getStr);
 if (messageDown[5] == 49)
 {
 command = messageDown[7]-48; 
 Serial.print("Command received: ");
 Serial.println(command);
 }
 else command = 9;
 return command;
}
/********* Reset ESP *************/
void EspHardwareReset(void)
{
 Serial.println("Reseting......."); 
 digitalWrite(HARDWARE_RESET, LOW); 
 delay(500);
 digitalWrite(HARDWARE_RESET, HIGH);
 delay(8000);//Tempo necessário para começar a ler 
 Serial.println("RESET"); 
}
/********* Start communication with ThingSpeak*************/
void startThingSpeakCmd(void)
{
 EspSerial.flush();//limpa o buffer antes de começar a gravar
 
 String cmd = "AT+CIPSTART=\"TCP\",\"";
 cmd += "184.106.153.149"; // Endereco IP de api.thingspeak.com
 cmd += "\",80";
 EspSerial.println(cmd);
 Serial.print("enviado ==> Start cmd: ");
 Serial.println(cmd);
 if(EspSerial.find("Error"))
 {
 Serial.println("AT+CIPSTART error");
 return;
 }
}
/********* send a GET cmd to ThingSpeak *************/
String sendThingSpeakGetCmd(String getStr)
{
 String cmd = "AT+CIPSEND=";
 cmd += String(getStr.length());
 EspSerial.println(cmd);
 Serial.print("enviado ==> lenght cmd: ");
 Serial.println(cmd);
 if(EspSerial.find((char *)">"))
 {
 EspSerial.print(getStr);
 Serial.print("enviado ==> getStr: ");
 Serial.println(getStr);
 delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando
 String messageBody = "";
 while (EspSerial.available()) 
 {
 String line = EspSerial.readStringUntil('\n');
 if (line.length() == 1) 
 { //actual content starts after empty line (that has length 1)
 messageBody = EspSerial.readStringUntil('\n');
 }
 }
 Serial.print("MessageBody received: ");
 Serial.println(messageBody);
 return messageBody;
 }
 else
 {
 EspSerial.println("AT+CIPCLOSE"); // alert user
 Serial.println("ESP8266 CIPSEND ERROR: RESENDING"); //Resend...
 spare = spare + 1;
 error=1;
 return "error";
 } 
}



Скачать его можно по ссылке

12 отправка команд на устройства


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

Включить насос (красный светодиод включен)

https://api.thingspeak.com/update?api_key=Сохраненный_ключ_канала_1&field1=1


Насос выключить (красный светодиод выключен)

https://api.thingspeak.com/update?api_key=Сохраненный_ключ_канала_1&field1=0


Лампу включить (зеленый светодод включен)

https://api.thingspeak.com/update?api_key=Сохраненный_ключ_канала_2&field1=1


Лампу выключить (зеленый светодиод выключен)

https://api.thingspeak.com/update?api_key=Сохраненный_ключ_канала_2&field1=0



14 Завершение программы андроид



В предыдущей части была простая программа, которая «читала» данные из канала и выводила их на экран. Теперь надо сделать, чтобы программа «писала» команды в Actuator Channal, так чтобы эти команды могли быть прочитаны контроллером и лампа с насосом соответственно отрабатывали.

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

Нажимая кнопки в приложении можно видеть результат в Serial Monitor.

Код можно скачать по ссылке

15 Финальная сборка


На данном этапе есть полностью завершенное андроид приложение, полностью собранная «железная» часть, но нет кода в контроллере, который бы постоянно читал данные и отправлял команды на облако. Надо просто объединить все фрагменты кода, написанного ранее.В конечно коде есть дополнительные опции проверки (на пример если ESP-01 зависнет). Для этого, периодически, перед каждой командой чтения или записи отправляется команда АТ. И если от модуля не пришел ответ ОК, то модуль принудительно программно перезагружается.

Полный код проекта можно скачать по ссылке

Жми «Нравится» и получай только лучшие посты в Facebook ↓

Управление теплицей или оранжереей из любой точки планеты