Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

IoT Made Easy с UNO, ESP-01, ThingSpeak и MIT App Inventor

Компоненты и расходные материалы

Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Датчик температуры DHT22
× 1
Цифровой датчик температуры DS18B20 1-Wire для использования на почве
× 1
LDR - светозависимый резистор
× 1
2-канальный релейный модуль постоянного тока 5 В
× 1

Приложения и онлайн-сервисы

IDE Arduino
ThingSpeak API
MIT App Inventor

Об этом проекте

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

Подавляющая часть моей работы в сфере Интернета вещей была связана с использованием NodeMCU, а в последнее время - ESP32. Но, думаю, важно не забывать о моих первых шагах, пару лет назад, когда я начал изучать Интернет вещей, используя Arduino UNO и старый добрый ESP8266-01.

Итак, я решаю здесь вернуться в то время (теперь с немного большим опытом) и снова исследовать эти замечательные устройства, подключая их к облаку с помощью веб-службы ThingSpeak.com. Мы также рассмотрим возможность удаленного управления с помощью приложения для Android, разработанного с помощью MIT AppInventor.

«Центром нашего IoT-проекта» станет ThingSpeak.com. Локальный блок (UNO / ESP-01) будет собирать данные с датчиков и состояния привода, отправлять их в Интернет, "написав" на конкретном ThingSpeak.com Статусный канал . Местное подразделение также получит данные из Интернета, "считывая" их из определенных каналов активатора ThingSpeak .

Приложение для Android также будет для чтения эти данные из канала статуса ThingSpeak.com и отображать их для пользователя. Таким же образом пользователь, основываясь на этой информации о статусе, может отправлять команды исполнительным механизмам, запись их на каналах актуатора ThingSpeak (см. приведенную выше блок-схему, чтобы лучше понять поток данных).

Итак, что мы будем делать? Блок-схема, показанная на следующем шаге, даст нам обзор окончательного проекта:

Шаг 1. Введение

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

Данные, которые будут собирать датчики будет:

  • Температура воздуха и относительная влажность
  • Температура и влажность почвы
  • Яркость

В проекте будет 2 исполнительных механизма . :

  • Электрический насос
  • Электрическая лампа

Статус этих исполнительных механизмов («ВКЛ / ВЫКЛ») также должен быть отправлен в облако.

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

  • Включите насос, если влажность почвы слишком низкая.
  • Включите лампу, если температура почвы слишком низкая.

Чтобы удаленно управлять нашими приводами, мы будем использовать приложение для Android.

Шаг 2:BoM - Спецификация

Некоторые из наиболее важных компонентов, перечисленных здесь, имеют ссылку и ориентировочную цену в долларах США. Эти ссылки предназначены только для информации.

  • Arduino UNO (микроконтроллер) - 10 долларов США.
  • ESP8266-01 (коммуникационный модуль) - 3,50 доллара США.
  • DHT22 (датчик воздуха и относительной влажности) - 9 долларов США.
  • DS18B20 (цифровой датчик температуры 1-Wire для использования на почве) - 6 долларов США.
  • YL-69 + LM393 (датчик влажности почвы) - 2 доллара США.
  • LDR (датчик яркости) - 0,20 доллара США.
  • 2 светодиода (красный и зеленый)
  • 1 x 2-канальный релейный модуль постоянного тока 5 В с триггером низкого уровня оптопары - 7 долларов США.
  • Насос 5 В постоянного тока - 3 доллара США.
  • Лампа 220 В
  • резистор 2 x 330 Ом (для использования со светодиодами)
  • резистор 2 x 10 кОм (для использования с DHT22 и LDR)
  • 1 резистор 4K7 Ом (для использования с DS18B20.
  • Протоборд
  • Джемперы
  • Внешний источник питания 5 В постоянного тока для реле

Шаг 3. Оборудование

Соберем Project HW. Идеальный вариант - установить и протестировать наш проект по частям. В качестве предложения мы можем выполнить следующие действия:

  • Установите и протестируйте все датчики локально.
  • Установите и настройте ESP-01 (BareMinimum)
  • Измените установку ESP-01 на ее окончательную конфигурацию и протестируйте ее.
  • Настроить канал статуса ThingsPeak
  • Установите код ThingsPeak в свой Arduino и проверьте статус датчиков в облаке.
  • Разработайте первую версию Android-приложения для отображения статуса и сообщений.
  • Установите исполнительные механизмы (светодиоды и реле)
  • Настроить каналы ThingSpeak Actuators.
  • Установите и протестируйте код Arduino с исполнительными механизмами.
  • Разработайте окончательную версию приложения для Android.

Шаг 4:Подключение датчиков

У нас должны быть установлены некоторые библиотеки в нашей среде IDE, чтобы правильно считывать датчики. Убедитесь, что у вас установлены все библиотеки. Их первоначальная конфигурация должна быть:

  // DS18B20 # include  #include  #define ONE_WIRE_BUS 5 // DS18B20 на выводе D5 OneWire oneWire (ONE_WIRE_BUS); DallasTemperature DS18B20 (&oneWire); int грунтТемп =0 // DHT # include "DHT.h" #include  int pinoDHT =11; int tipoDHT =DHT22; DHT dht (pinoDHT, tipoDHT); int airTemp =0; int airHum =0; // LDR (Light) #define ldrPIN 1int light =0; // Влажность почвы # определить почвенныйHumPIN 0int грунтHum =0;  

В разделе «Настройка и цикл» напишем:

  void setup () {Serial.begin (9600); DS18B20.begin (); dht.begin ();} недействительный цикл () {readSensors (); displaySensors (); задержка (10000);}  

И, наконец, давайте напишем две конкретные функции, одну для чтения наших датчиков, а другую для отображения их значений на последовательном мониторе:

  / ********* Чтение значений датчиков ************* / void readSensors (void) {airTemp =dht.readTemperature (); airHum =dht.readHumidity (); DS18B20.requestTemperatures (); почваTemp =DS18B20.getTempCByIndex (0); // Датчик 0 будет фиксировать температуру почвы в градусах Цельсия SoilHum =map (analogRead (SoilHumPIN), 1023, 0, 0, 100); свет =карта (analogRead (ldrPIN), 1023, 0, 0, 100); // LDRDark:0 ==> light 100%} / ********* Значение датчиков дисплея ************* / void displaySensors (void) {Serial.print (" airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("Температура почвы (oC):"); Serial.println (температура почвы); Serial.print ("почваХум (%):"); Serial.println (почваХум); Serial.print ("свет (%):"); Serial.println (светлый); Serial.println ("");}  

На приведенном ниже изображении последовательного монитора показаны значения датчиков.

Код можно скачать с моего GITHUB:Sens ors_Test.ino

Шаг 5:Начальная настройка ESP8266-01

ESP-01 будет использоваться в качестве последовательного моста, что означает, что мы будем программировать его с помощью «AT-команд». Прежде всего убедитесь, что ваш ESP-01 использует правильную скорость передачи данных. В нашем случае 9600 бод. Обычно ESP-01 поставляется с заводской запрограммированной скоростью 115 200 бод, и мы должны изменить ее на 9600 бод.

Сначала вы должны подключить ESP-01, как показано выше.

Затем подключите Arduino к компьютеру, откройте IDE и загрузите пример, который находится в File> Examples> 01.Basics> BareMinimum. Это пустой код, чтобы гарантировать отсутствие конфликта связи между Arduino и ESP.

Мы передали этот код в Arduino перед подключением его к ESP-01S, чтобы гарантировать, что Arduino не будет использовать последовательную связь (TX и RX). Это важно для того, чтобы ESP могла правильно общаться.

Откройте ваш IDE Serial Monitor и измените скорость на 115 200 бод. Начните посылать команду «AT» на ваш IDE Serial Monitor. ESP-01 должен вернуть "ОК"

Далее изменим скорость. Для этого вы можете использовать команду:

  AT + CIOBAUD =9600  

Обратите внимание, что ESP-01 может вернуться к заводскому программированию (я не знаю, связано ли это с версией FW). По крайней мере, в моем случае мне пришлось использовать другую команду, чтобы окончательно изменить BaudRate:

  AT + UART_DEF =, , , ,   

Например:9600 бод / 8 бит данных / 1 стоповый бит и без контроля четности и потока:

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

В поле выбора в нижней части монитора последовательного порта измените скорость на «9600 бод». Протестируйте связь:в верхней части окна введите AT и увидите ответ ОК. Теперь вы должны настроить модуль в режиме станции . действовать как Клиент вашей сети Wi-Fi. Используйте команду:

  AT + CWMODE =1  

Теперь мы должны подключить модуль к вашей сети Wi-Fi.

Для этого используйте приведенные ниже команды, заменив «network_name» на имя вашей сети Wi-Fi и «network_name» на свой пароль. Сохраняйте кавычки.

  AT + CWJAP ="имя_сети", "имя_сети"  

Если вы видите ответ ниже, ваше соединение установлено правильно:

  ПОДКЛЮЧЕННЫЙ WIFI WIFI GOT IP  

Чтобы узнать IP, выполните команду:

  AT + CIFSR  

И обратите внимание на IP-адрес, который появится в вашем последовательном мониторе. Возможно, он вам понадобится в будущем.

Шаг 6. Тестирование ESP-01

После того, как мы настроили ESP-01, мы должны установить его на последний контур. Для этого мы должны ИЗМЕНИТЬ проводку, сделанную ранее, и подключить ESP-01 к нашему UNO, как показано ниже:

  • ESP-01 RX (желтый) к контакту UNO D7
  • ESP-01 TX (оранжевый) к контакту UNO D6
  • ESP-01 Ch-Pd (коричневый) на Vcc (3,3 В)
  • Сброс ESP-01 (синий) на вывод UNO D8
  • ESP-01 Vcc (красный) до 3,3 В
  • ESP-01 Gnd (черный) на UNO GND

Давайте проведем простой тест, чтобы проверить, исправлен ли наш ESP-01, установлен и протестирован. Введите приведенный ниже код:

  #include  SoftwareSerial esp8266 (6,7); // Rx ==> Контакт 6; TX ==> Pin7 #define speed8266 9600 void setup () {esp8266.begin (speed8266); Serial.begin (speed8266); Serial.println («Тест установки ESP8266 - используйте команды AT»);} void loop () {while (esp8266.available ()) {Serial.write (esp8266.read ()); } пока (Serial.available ()) {esp8266.write (Serial.read ()); }}  

Теперь попробуйте несколько AT-команд и посмотрите результат на своем последовательном мониторе:

  * AT =====> ESP8266 возвращает OK * AT + RST =====> ESP8266 перезапуск и возвращает OK * AT + GMR =====> ESP8266 возвращает версию AT; Версия SDK; я бы; ОК * AT + CWMODE? => ESP8266 возвращает тип режима * AT + CWLAP ===> ESP8266 возвращает закрытые точки доступа * AT + CIFSR ===> ESP8266 возвращает спроектированный IP  

Код можно скачать с моего GITHUB:ESP_AT_Config.ino

Если вы хотите подключаться к сети Wi-Fi каждый раз, когда происходит сброс (или ваш Arduino выключается / включается) и вводит свои учетные данные, добавьте вызов в connectWiFi () в конце функции setup ():

  setup () {... connectWiFi (); }  

connectWiFi () функция должна быть в конце вашего основного кода .ino:

  void connectWiFi (void) {sendData ("AT + RST \ r \ n", 2000, 0); // сбросить sendData ("AT + CWJAP =\" ВАШЕ ИМЯ ПОЛЬЗОВАТЕЛЯ \ ", \" ВАШ ПАРОЛЬ \ "\ r \ n", 2000, 0); // Подключаем сетевую задержку (3000); sendData ("AT + CWMODE =1 \ r \ n", 1000, 0); sendData ("AT + CIFSR \ r \ n", 1000, 0); // Показать IP-адрес Serial.println ("8266 Connected");}  

Обратите внимание, что указанная выше функция вызывает другой sendData (data) функция, которая также должна находиться в вашем коде:

  String sendData (строковая команда, время ожидания const int, логическая отладка) {String response =""; EspSerial.print (команда); long int time =миллис (); while ((time + timeout)> millis ()) {while (EspSerial.available ()) {// У esp есть данные, поэтому отобразите их вывод в окне последовательного порта char c =EspSerial.read (); // читаем следующий символ. ответ + =c; }} если (отладка) {Serial.print (ответ); } вернуть ответ;}  

Шаг 7:Подключение датчиков и ESP-01

После того, как мы установили и протестировали все датчики, а также наш ESP-01 заработал должным образом, давайте посмотрим все вместе и подготовимся к отправке данных в Интернет.

Шаг 8:ThingSpeak

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

Затем создайте новый канал, в котором у нас будут 2 исполнительных механизма, 5 датчиков и состояние запасного поля:

  • Поле 1:Привод 1
  • Поле 2:Привод 2
  • Поле 3:Температура воздуха в ° C
  • Файл 4:Относительная влажность воздуха в%
  • Поле 5:Температура почвы в oC
  • Поле 6:Влажность почвы в%
  • Поле 7:Яркость в%
  • Поле 8:Запасной

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

После того, как вы создадите свой канал (в данном случае это будет наш статусный канал), важно запомнить свои ключи, как показано ниже.

Шаг 9. Отправка статуса в облако

На данный момент у нас есть облачный сервис, а наши датчики собирают данные локально. Давайте возьмем эти значения и отправим их на ThingSpeak.com. Мы будем ЗАПИСАТЬ на канал ThingSpeak, и для этого нам нужно будет отправить строку GET. Сделаем в 3 части:

Мы отправим "Start cmd":

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

Следуя «длине» команды:

  AT + CIPSEND =116  

И сама строка GET, которая будет писать в соответствующие поля в канале состояния:

  GET / update? api_key =YOUR_WRITE_KEY_HERE &field1 =pump &fieldlamp =0 &field3 =airTemp &field4 =airHum &field5 =грунтTemp &field6 =грунтHum &field7 =light &field8 =запасной 

Приведенный ниже код сделает всю работу за нас, а приведенный выше PrintScreen показывает результат на последовательном мониторе:

  // Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // Идентификатор канала состояния:385184 # include  SoftwareSerial EspSerial (6, 7); // Rx, Tx # define HARDWARE_RESET 8 // DS18B20 # include  #include  #define ONE_WIRE_BUS 5 // DS18B20 на контакте D5 OneWire oneWire (ONE_WIRE_BUS); =0; // DHT # включает "DHT.h" #include  int pinoDHT =11; int tipoDHT =DHT22; DHT dht (pinoDHT, tipoDHT); int airTemp =0; int airHum =0; // LDR (Light) #define ldrPIN 1int light =0; // Влажность почвы # определить почву // ==> Определить время выборки в секундах для отправки данных вместе startWriteTiming =0; long elapsedWriteTime =0; // Переменные, которые будут использоваться с Actuatorsboolean pump =0; логическая лампа =0; int Spare =0; логическая ошибка; void setup () {Serial.begin (9600); pinMode (HARDWARE_RESET, ВЫХОД); digitalWrite (HARDWARE_RESET, HIGH); DS18B20.begin (); dht.begin (); EspSerial.begin (9600); // Comunicacao com Modulo WiFi EspHardwareReset (); // Сброс do Modulo WiFi startWriteTiming =millis (); // запускаем "часы программы"} void loop () {start:// label error =0; elapsedWriteTime =millis () - startWriteTiming; если (elapsedWriteTime> (writeTimingSeconds * 1000)) {readSensors (); writeThingSpeak (); startWriteTiming =millis (); } if (error ==1) // Отправить повторно, если передача не завершена {Serial.println ("<<<>>>"); задержка (2000); перейти к началу; // переход к метке "start"}} / ********* Чтение значения датчиков ************* / void readSensors (void) {airTemp =dht.readTemperature (); airHum =dht.readHumidity (); DS18B20.requestTemperatures (); почваTemp =DS18B20.getTempCByIndex (0); // Датчик 0 будет фиксировать температуру почвы в градусах Цельсия light =map (analogRead (ldrPIN), 1023, 0, 0, 100); // LDRDark:0 ==> светлый 100% грунтHum =map (analogRead (gradientHumPIN), 1023, 0, 0, 100); } / ********* Conexao com TCP com Thingspeak ******* / void writeThingSpeak (void) {startThingSpeakCmd (); // подготовка строки GET String getStr ="GET / update? api_key ="; getStr + =statusChWriteKey; getStr + ="&field1 ="; getStr + =String (насос); getStr + ="&field2 ="; getStr + =String (лампа); getStr + ="&field3 ="; getStr + =String (airTemp); getStr + ="&field4 ="; getStr + =Строка (airHum); getStr + ="&field5 ="; getStr + =String (грунтТемп); getStr + ="&field6 ="; getStr + =Строка (почваХум); getStr + ="&field7 ="; getStr + =String (светлый); getStr + ="&field8 ="; getStr + =String (запасной); getStr + ="\ г \ п \ г \ п"; sendThingSpeakGetCmd (getStr); } / ********* Сброс ESP ************* / void EspHardwareReset (void) {Serial.println ("Сброс ......."); digitalWrite (HARDWARE_RESET, LOW); задержка (500); digitalWrite (HARDWARE_RESET, HIGH); delay (8000); // Необходимое время для перехода к Serial.println ("RESET"); } / ********* Начать общение с ThingSpeak ************* / void startThingSpeakCmd (void) {EspSerial.flush (); // удалить буфер, оставшийся после сообщения 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 ("Ошибка")) {Serial.println ("Ошибка AT + CIPSTART"); возвращение; }} / ********* отправить команду GET в ThingSpeak ************* / String sendThingSpeakGetCmd (String getStr) {String cmd ="AT + CIPSEND ="; cmd + =String (getStr.length ()); EspSerial.println (cmd); Serial.print ("enviado ==> lenght cmd:"); Serial.println (cmd); если (EspSerial.find ((char *) ">")) {EspSerial.print (getStr); Serial.print ("enviado ==> getStr:"); Serial.println (getStr); delay (500); // темп обработки GET, такая задержка сейчас занята, но не назначена команда String messageBody =""; while (EspSerial.available ()) {Строка строки =EspSerial.readStringUntil ('\ n'); if (line.length () ==1) {// фактическое содержимое начинается после пустой строки (имеющей длину 1) messageBody =EspSerial.readStringUntil ('\ n'); }} Serial.print ("MessageBody получено:"); Serial.println (messageBody); return messageBody; } else {EspSerial.println ("AT + CIPCLOSE"); // предупреждаем пользователя Serial.println ("ESP8266 CIPSEND ERROR:RESENDING"); // Повторная отправка ... Spare =SpA + 1; ошибка =1; вернуть «ошибку»; }}  

Код можно скачать с моего GITHUB:SendingStatusTS_EXT.ino

Шаг 10. Приложение для Android. Первая часть - мониторинг состояния

Давайте создадим нашу первую часть приложения для Android.

Сначала мы разрабатываем пользовательский интерфейс. На приведенном выше экране печати показаны основные видимые и невидимые элементы. После этого мы должны спроектировать блоки (цифры ниже соответствуют цифрам выше):

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

  • Возвращением такой процедуры будет значение каждой переменной состояния, которая должна отображаться на экране.
  • Обратите внимание, что для лучшего понимания мы «конвертируем» значения «0» и «1» из состояния исполнительных механизмов в «ВЫКЛ.» и «ВКЛ.».
  • Эти значения («Статус») будут отображаться на соответствующих «ярлыках».
  • Переменные состояния должны быть объявлены как глобальные.
  • Процедура readArduino фактически будет читать канал состояния на ThingSpeak. Итак, мы должны определить URL-адрес, который будет отправлен в Thingspeak. Для этого должны быть объявлены и объединены 3 глобальные переменные, чтобы создать URL-адрес для отправки в TS. GET должен быть отправлен веб-компоненту с именем «ArduFarmBotStatusCh»
  • Текст, полученный из предыдущей команды, будет доставлен в формате JSon. Этот текст необходимо обработать так, чтобы каждое поле было прочитано и сохранено в соответствующей глобальной переменной.
  • Последнее, что нужно сделать, это вызвать процедуру «Тревога», которая проанализирует состояние двух датчиков почвы. Если температура слишком низкая (в нашем случае 10oC), должно появиться сообщение. То же самое для влажности, если она ниже 60%. Обратите внимание, что мы определили еще один таймер (Clock2), запрограммированный на срабатывание каждую 1 секунду. Это только для «переключения» цвета текста сообщения (с белого на красный). Это заставит сообщение "мигать".

На последней фотографии выше показано окончательное работающее приложение.

Код приложения можно загрузить с моего GITHUB:ArduFarmBot_Status_App_EXT.aia

Шаг 11:Установка исполнительных механизмов (светодиодов и реле)

Давайте завершим наш HW.

Для этого мы должны установить наши Актуаторы. Как вы помните, мы будем удаленно получать команды на включение и выключение насоса и лампы. Выход Arduino активирует реле (и светодиод) для выполнения этих действий.

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

На приведенном выше рисунке показано, как должны быть подключены приводы. Обратите внимание, что Realy GND НЕ ПОДКЛЮЧЕН к GND Arduino. Это поможет не вносить шум при срабатывании реле.

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

Шаг 12:Настройка каналов исполнительных механизмов ThingSpeak

Так же, как мы сделали для статуса, мы создадим 2 новых канала, по одному для каждого привода. На каждом из них запишите ID канала, ключи чтения и записи. Мы будем писать только в Поле 1 каждого из этих каналов. Так, например, в моем случае:

ID канала 375598 ==> Красный светодиод (насос)

  • Поле1 =0 ==> Насос выключен
  • Field1 =1 ==> Насос включен

ID канала 375599 ==> Зеленый светодиод (лампа)

  • Поле1 =0 ==> Лампа выключена
  • Field1 =1 ==> Лампа горит

Шаг 13:Установка и тестирование кода Arduino с исполнительными механизмами

Когда мы отправляли данные в Интернет, мы просто ЗАПИСЫВАЕМ на канал ThingSpeak (статус канала) для «передачи» (загрузки) данных. Теперь мы должны ПРОЧИТАТЬ из канала ThingSpeak (канал исполнительного механизма), чтобы «получать» (загружать) данные.

Мы будем читать из канала ThingSpeak, и для этого нам нужно будет отправить строку GET. Сделаем в 3 части:

Мы отправим "Start cmd":

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

Следуя «длине» команды:

  AT + CIPSEND =36  

И сама строка GET, которая будет считываться из поля 1 на каждом из каналов исполнительного механизма:

  GET / channels / 375598 / fields / 1 / last  

Мы будем читать каналы ThingSpeak с интервалом в 10 секунд. После того, как мы отправим приведенную выше команду GET, которая вызывает «ПОСЛЕДНЕЕ ЗНАЧЕНИЕ, СОХРАНЕННОЕ НА ПОЛЕ 1, мы получим ответ от ThingSpeak, который должен быть« 1 »или« 0 »в определенной позиции ответа. Если что-то отличается от этого прибыл, мы должны игнорировать его.

Основное отличие этой части кода от предыдущей (для отправки данных о состоянии) заключается в функции:

  readThingSpeak (String channelID)  

Приведенный ниже код сделает всю работу за нас, а приведенный выше PrintScreen показывает результат на последовательном мониторе:

  // Строка языка слов canalID1 ="375598"; // Actuator1String canalID2 ="375599"; // Actuator2 # include  SoftwareSerial EspSerial (6, 7); // Rx, Tx # define HARDWARE_RESET 8 // Переменные, которые будут использоваться с timerslong readTimingSeconds =10; // ==> Определить время выборки в секундах для получения данных startReadTiming =0; long elapsedReadTime =0; // Реле # определить ACTUATOR1 10 // КРАСНЫЙ СВЕТОДИОД ==> Насос # определить ACTUATOR2 12 // ЗЕЛЕНЫЙ СВЕТОДИОД ==> Насос Lampboolean =0; логическая лампа =0; int Spare =0; логическая ошибка; void setup () {Serial.begin (9600); pinMode (ПРИВОД1, ВЫХОД); pinMode (ПРИВОД2, ВЫХОД); pinMode (HARDWARE_RESET, ВЫХОД); digitalWrite (ACTUATOR1, ВЫСОКИЙ); // или релейный модуль с низким значением digitalWrite (ACTUATOR2, HIGH); // модуль должен иметь низкий уровень digitalWrite (HARDWARE_RESET, HIGH); EspSerial.begin (9600); // Comunicacao com Modulo WiFi EspHardwareReset (); // Сброс do Modulo WiFi startReadTiming =millis (); // запускаем "часы программы"} void loop () {start:// label error =0; elapsedReadTime =millis () - startReadTiming; если (elapsedReadTime> (readTimingSeconds * 1000)) {int command =readThingSpeak (canalID1); если (команда! =9) насос =команда; задержка (5000); команда =readThingSpeak (canalID2); если (команда! =9) лампа =команда; принять меры(); startReadTiming =millis (); } if (error ==1) // Отправить повторно, если передача не завершена {Serial.println ("<<<>>>"); задержка (2000); перейти к началу; // переход к метке "start"}} / ********* Выполнение действий на основе команд ThingSpeak ************* / void takeActions (void) {Serial.print ( "Насос:"); Serial.println (насос); Serial.print ("Лампа:"); Serial.println (лампа); if (pump ==1) digitalWrite (ACTUATOR1, LOW); иначе digitalWrite (ACTUATOR1, HIGH); if (lamp ==1) digitalWrite (ACTUATOR2, LOW); else digitalWrite (ACTUATOR2, HIGH);} / ********* Чтение команды исполнительных механизмов из ThingSpeak ************* / int readThingSpeak (String channelID) {startThingSpeakCmd (); int command; // подготовка строки GET String getStr ="GET / channels /"; getStr + =channelID; getStr + ="/ fields / 1 / last"; getStr + ="\ г \ п"; Строка messageDown =sendThingSpeakGetCmd (getStr); если (messageDown [5] ==49) {command =messageDown [7] -48; Serial.print ("Команда получена:"); Serial.println (команда); } else command =9; return command;} / ********* Reset ESP ************* / void EspHardwareReset (void) {Serial.println ("Сброс ......." ); digitalWrite (HARDWARE_RESET, LOW); задержка (500); digitalWrite (HARDWARE_RESET, HIGH); delay (8000); // Необходимое время для перехода к Serial.println ("RESET"); } / ********* Начать общение с ThingSpeak ************* / void startThingSpeakCmd (void) {EspSerial.flush (); // удалить буфер, оставшийся после сообщения 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 ("Ошибка")) {Serial.println ("Ошибка AT + CIPSTART"); возвращение; }} / ********* отправить команду GET в ThingSpeak ************* / String sendThingSpeakGetCmd (String getStr) {String cmd ="AT + CIPSEND ="; cmd + =String (getStr.length ()); EspSerial.println (cmd); Serial.print ("enviado ==> lenght cmd:"); Serial.println (cmd); если (EspSerial.find ((char *) ">")) {EspSerial.print (getStr); Serial.print ("enviado ==> getStr:"); Serial.println (getStr); delay (500); // темп обработки GET, такая задержка сейчас занята, но не назначена команда String messageBody =""; while (EspSerial.available ()) {Строка строки =EspSerial.readStringUntil ('\ n'); if (line.length () ==1) {// фактическое содержимое начинается после пустой строки (имеющей длину 1) messageBody =EspSerial.readStringUntil ('\ n'); }} Serial.print ("MessageBody получено:"); Serial.println (messageBody); return messageBody; } else {EspSerial.println ("AT + CIPCLOSE"); // предупреждаем пользователя Serial.println ("ESP8266 CIPSEND ERROR:RESENDING"); // Повторная отправка ... Spare =SpA + 1; ошибка =1; вернуть «ошибку»; }}  

Код можно скачать с моего GITHUB:ReadingCommandTS_EXT.ino

Шаг 14:Отправка команд исполнительным механизмам

На этом этапе у нас есть каналы исполнительных механизмов, настроенные на ThingSpeak, и, изменяя значение поля 1 на каждом канале, мы должны видеть соответствующие изменения исполнительных механизмов. On our final project we will do this task, using the Android App, but for testing proposes we can also do it using a normal browser. Let's do it.

The commands are:

Turn ON Pump (RED LED):

https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=1 

Turn OFF Pump (RED LED):

https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=0 

Turn ON Lamp (GREEN LED):

https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=1 

Turn OFF Lamp (GREEN LED):

https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=0 

Above you can see a print screen of a command to TurnOn the Pump sent from a browser and how it will appear at Serial Monitor. Obviously, the LED Red and relay will be also be turned on.

Step 15:Completing the Android APP

Let's complete the APP. Previously we have developed a simple App that gets the status from ThingSpeak (READ from Staus Channel). Now we must WRITE on Actuator channels, so those commands could be read by Arduino and act on Pump and Lamp accordingly.

For a user to pass the commands to the App, we will use "buttons". A pair of buttons (ON and OFF) for each one of the Actuators.

When a button is pressed, the color of its text changes.

  • If ON ==> Blue
  • if OFF ==> Red

Above you can see the set of blocks for each one of the pairs of buttons.

Test the App, sending commands to turn ON and OFF the actuators. Check on Serial Monitor, the messages exchanged between ESP-01 and ThingSpeak.

The complete App code can be downloaded from my GITHUB:ArduFarmBot_V1_EXT.aia

Step 16:Putting All Together

Идеально! At this point, you have a full Android APP, a complete HW but you still do not have a code that will continuously read and write on ThingSpeak. Let's combine all that we have developed previously.

On the final code, you will find additional portions to verify for example if the ESP-01 is not freezing. We will do it, sending an AT command to it before any read or write. As we saw at the very beginning of this tutorial, sending an AT command should return from ESP-01 an OK. If this does not happen, we will proceed with an HW reset, commanded by SW (as we do once during setup phase).

The complete code for our project can be downloaded from my GITHUB:ArduFarmBot_Light_EXT.ino

Step 17:Conclusion

There is a lot to be explored in IoT arena with those great little devices, the Arduino Uno, and the ESP8266-01. We will return soon with new tutorials! Keep following MJRoBot tutorials!

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

Please visit my GitHub for updated files:ArduFarmBot_Light

Чтобы узнать больше о проектах, посетите мой блог:MJRoBot.org

Салудо с юга мира!

Увидимся на моем следующем уроке!

Спасибо,

Марсело

Код

  • Фрагмент кода №1
  • Фрагмент кода №2
  • Фрагмент кода №3
  • Фрагмент кода №11
  • Фрагмент кода № 12
  • Фрагмент кода №16
  • Code snippet #20
Фрагмент кода №1 Обычный текст
// DS18B20#include #include #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 int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;
Фрагмент кода 2 Обычный текст
void setup(){ Serial.begin(9600); DS18B20.begin(); dht.begin();}void loop(){ readSensors(); displaySensors(); delay (10000);}
Фрагмент кода № 3 Обычный текст
/********* 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 ("");}
Фрагмент кода № 11 Обычный текст
#include  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()); }} 
Фрагмент кода № 12 Обычный текст
* AT =====> ESP8266 returns OK* AT+RST =====> ESP8266 restart and returns OK* AT+GMR =====> ESP8266 returns AT Version; SDK version; я бы; OK* AT+CWMODE? => ESP8266 returns mode type* AT+CWLAP ===> ESP8266 returs close access points* AT+CIFSR ===> ESP8266 returs designided IP
Фрагмент кода №16 Обычный текст
// Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // Status Channel id:385184#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// DS18B20#include #include #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 int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;// Variables to be used with timerslong writeTimingSeconds =17; // ==> Define Sample time in seconds to send datalong startWriteTiming =0;long elapsedWriteTime =0;// Variables to be used with Actuatorsboolean 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(" <<<>>>"); 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(); // подготовка строки 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 + ="\ г \ п \ г \ п"; sendThingSpeakGetCmd(getStr); }/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); задержка (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"); возвращение; }}/********* 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 получено:"); Serial.println (messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; вернуть «ошибку»; }} 
Code snippet #20Plain text
// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables to be used with timerslong readTimingSeconds =10; // ==> Define Sample time in seconds to receive datalong startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean 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(" <<<>>>"); 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 ("Команда получена:"); Serial.println(command); } else command =9; return command;}/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); задержка (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"); возвращение; }}/********* 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 получено:"); Serial.println (messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; вернуть «ошибку»; }} 
Github
https://github.com/Mjrovai/ArduFarmBot_Light

Схема

Electrical diagram
https://github.com/Mjrovai/ArduFarmBot_Light/blob/master/ArduFarmBot_Light/ArduFarmBot%20Light.fzz

Производственный процесс

  1. Упрощение параллельных вычислений на платах Raspberry Pi 4B + IoT
  2. Монитор сердечного ритма с использованием Интернета вещей
  3. WebServerBlink с использованием Arduino Uno WiFi
  4. Простой калькулятор UNO
  5. Постоянство видения
  6. Ворота бесконтактного мониторинга температуры
  7. Arduino - отправка температуры в Интернет через последовательный
  8. Метеостанция ThingSpeak Arduino
  9. Насколько легко использовать термистор ?!
  10. Бассейн Azure IoT