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

ArduFarmBot - Часть 2:Удаленная станция и реализация Интернета вещей

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

Arduino Nano R3
× 1
Espressif ESP8266 ESP-01
× 1
Датчик температуры DHT22
× 1
ky18
× 1
ареометр
× 1
Реле (универсальное)
× 2
ЖК-дисплей 4X20
× 1
Кнопочный переключатель SparkFun, 12 мм
× 3
LED (общий)
× 3

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

ThingSpeak API

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

Это руководство является продолжением ArduFarmBot:Управление домашней фермой с помидорами с помощью Arduino и IoT

В первой части мы создаем локальную станцию ​​управления, собирающую информацию с плантации томатов, такую ​​как температура, относительная влажность воздуха, освещенность и влажность почвы. На основе этих данных ArduFarmBot автоматически определил, какое количество (и когда) плантация должна получать тепло и воду. Местная станция, разработанная по Части 1, также позволяла ручное вмешательство оператора для управления водяным насосом и электрической лампой. В этой части 2 мы реализуем подход IoT, где это «ручное вмешательство» также будет возможно удаленно через Интернет. Блок-схема показывает, как мы это будем делать.

Обратите внимание, что захваченные данные будут отправлены в «службу облачного хранилища» (в нашем случае Thinkspeak.com). Также специальный веб-сайт, «Страница дистанционного управления», будет отслеживать и отображать эти данные практически в реальном времени. На этой веб-странице также можно будет дистанционно активировать помпу и лампу.

Шаг 1. Спецификация

  • Arduino Nano - (7,50 доллара США)
  • Датчик температуры и влажности DHT22 или DHT11 - (3,66 доллара США)
  • Датчик освещенности - модуль фоторезистора AD-018. или любой эквивалент - (0,71 доллара США)
  • Датчик влажности почвы 2X - (1,99 доллара США) (необязательно, можно сделать своими руками)
  • ЖК-дисплей I2C 20X4 (13,99 доллара США)
  • Светодиоды (1 шт.) (0,20 доллара США)
  • Модуль последовательного беспроводного приемопередатчика Wi-Fi Esp8266 Esp-01 - (5,96 доллара США)
  • Активный зуммер - Ky-12 или аналогичный (0,60 доллара США)
  • Релейный модуль 2 x 5 В (11,60 долл. США)
  • Соединительные провода (S1.00)
  • Резистор 10 кОм - (0,03 доллара США)
  • Резистор 2,2 кОм - (0,03 доллара США)
  • Резистор 1,0 кОм - (0,03 доллара США)
  • Резистор 220 Ом - (0,03 доллара США)
  • Arduino Nano Shield («Funduino») - (7,28 доллара США).
  • Мембранная клавиатура (4 клавиши) - (6,65 долл. США)
  • Пластиковая коробка

Шаг 2. Установка оборудования

Начиная с локальной станции, разработанной в Части 1, единственное необходимое дополнительное аппаратное обеспечение - это ESP8266. На приведенной выше блок-схеме показаны все PIN-соединения Arduino и основных компонентов. Единственная забота, которая вам необходима, связана с уровнем напряжения. ESP8266 работает с напряжением 3,3 В, поэтому контакт Rx не следует подключать напрямую к контакту Nano Tx (D3). Следует использовать уровень напряжения. В нашем случае мы построим делитель напряжения, который будет использоваться в качестве преобразователя уровня напряжения. На схемах выше более подробно показано, как подключить ESP8266. Если вы хотите узнать больше о ESP8266, см. Мои руководства:

  • ESP8266, часть 3 - Удаленное включение светодиодов Arduino
  • ESP8266, часть 1 - последовательный модуль WIFI для Arduino
  • ESP8266, часть 2 - веб-сервер Arduino

Обратите внимание, что мы используем ESP8266, подключенный к Nano Pin 2 (Tx) и Pin 3 (Rx), используя библиотеку SoftSerial. Если вы хотите «освободить» эти цифровые выводы, вы можете поочередно использовать выводы 0 и 1 Nano Serial. Помните только, что вы должны отключить их при загрузке кода в Nano.

ПРИМЕЧАНИЕ:Если вы хотите подключить ЗУММЕР, вы должны сделать это на контакте D17 (так же, как и на контакте A3). Хорошо иметь звук, когда у вас есть ошибка связи. Я использовал его на этапе тестирования, оставив его в финальном проекте (hw, но код для этого подготовлен). Получите это или нет - решать вам.

Вы можете использовать приведенный ниже код для тестирования и / или настройки ESP8266:

FC9DBPKIT682FY7.ino

Шаг 3. Подключение ESP8266

Чтобы подключить ArduFarmBot к Интернету, мы будем использовать ESP8266, простой, дешевый и легкий в программировании модуль для проектов IoT. После того, как модуль установлен, первое, что нужно сделать, это применить «Reset» на его выводе CH-PD.

  / ****************************************** ********* Функция сброса для приема сообщения ************************************ **************** / void reset8266 (void) {pinMode (CH_PD, OUTPUT); digitalWrite (CH_PD, LOW); задержка (300); digitalWrite (CH_PD, HIGH); Serial.print («8266 сбросить ОК»); lcd.clear (); lcd.println ("8266 сбросить ОК");}  

После сброса давайте подключим его к вашей локальной сети, используя свои учетные данные (в коде измените:ИМЯ ПОЛЬЗОВАТЕЛЯ и ПАРОЛЬ) и запустите модуль как «STA:режим станции» (CWMODE =1):

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

Чтобы отправить данные на ESP8266, функция sendData () был использован:

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

Вышеупомянутые функции будут вызываться на «этапе настройки» нашего Кодекса. Если все было сделано правильно, вы должны увидеть в Serial Monitor сообщения, аналогичные приведенным выше.

Шаг 4. Данные облачного хранилища:ThinkSpeak.com

Все данные, собранные ArduFarmBot, будут загружены в облако с помощью бесплатного сервиса ThinkSpeak.com.

В функции «Loop ()» (после сбора данных с помощью readSensors () ), мы вызовем специальную функцию для загрузки захваченных данных: updateDataThingSpeak ();

  / ****************************************** ********* Передача данных на thingspeak.com *********************************** ***************** / void updateDataThingSpeak (void) {startThingSpeakCmd (); cmd =msg; cmd + ="&field1 ="; // поле 1 для температуры DHT cmd + =tempDHT; cmd + ="&field2 ="; // поле 2 для влажности DHT cmd + =humDHT; cmd + ="&field3 ="; // поле 3 для светимости LDR cmd + =lumen; cmd + ="&field4 ="; // поле 4 для данных о влажности почвы cmd + =грунтMoist; cmd + ="&field5 ="; // поле 5 для статуса НАСОСА cmd + =pumpStatus; cmd + ="&field6 ="; // поле 6 для статуса ЛАМПЫ cmd + =lampStatus; cmd + ="\ г \ п"; sendThingSpeakCmd ();}  

Чтобы отправить эти данные, первое, что нужно сделать, - это начать общение с ThingSpeak. Мы сделаем это с помощью функции: startThingSpeakCmd ();

  / ****************************************** ********* Начать общение с ThingSpeak.com *********************************** ***************** / void startThingSpeakCmd (void) {cmd ="AT + CIPSTART =\" TCP \ ", \" "; cmd + =IP; cmd + =" \ ", 80"; esp8266.println (cmd); задержка (2000); if (esp8266.find ("Ошибка")) {Serial.println ("ОШИБКА НАЧАЛА ESP8266"); возвращение; } Serial.println («Thinkspeak Comm запущен»); cmd ="";}  

Когда канал открыт с ThingSpeak и строка "cmd" собрана с данными, пора загрузить все это в соответствующий канал на ThingSpeak с помощью функции: sendThingSpeakCmd ();

  / ****************************************** ******** * Обновить канал ThingSpeak.com ************************************ **************** / String sendThingSpeakCmd (void) {esp8266.print ("AT + CIPSEND ="); esp8266.println (cmd.length ()); если (esp8266.find (">")) {esp8266.print (cmd); Serial.println (""); Serial.println (""); Serial.println (cmd); задержка (500); Строка messageBody =""; while (esp8266.available ()) {Строка строки =esp8266.readStringUntil ('\ n'); if (line.length () ==1) {// фактическое содержимое начинается после пустой строки (имеющей длину 1) messageBody =esp8266.readStringUntil ('\ n'); Serial.print ("Сообщение получено:"); Serial.println (messageBody); }} return messageBody; } else {esp8266.println ("AT + CIPCLOSE"); Serial.println («ОШИБКА ESP8266 CIPSEND:ПОВТОРНАЯ ОТПРАВКА»); // Отправить повторно ... error =1; вернуть «ошибку»; }}  

Вышеупомянутые функции были основаны на отличном и подробном руководстве, разработанном Михалисом Василакисом. Дополнительные сведения см. В его руководстве:Arduino IOT:температура и влажность (с ESP8266 WiFi).

На фотографии показан канал ArduFarmBot на ThingSpeak.com.

Шаг 5. Управление исполнительными механизмами через Интернет

В данный момент мы выгружаем все собранные данные и храним их в облаке. Это очень хорошо и полезно для удаленного мониторинга, но что произойдет, если на основе этих данных мы также захотим включить насос или лампу независимо от локальной автоматической программы? Для этого нам также потребуется «загрузить» данные из облака и дать контроллеру команду действовать в соответствии с этими командами.

Мы создадим специальные поля на нашем канале ThinkSpeak для управления исполнительными механизмами:

Поле 7:

  • Data =1 ==> НАСОС должен быть включен.
  • Data =0 ==> НАСОС должен быть ВЫКЛЮЧЕН.

Поле 8:

  • Data =1 ==> ЛАМПА должна быть ВКЛЮЧЕНА.
  • Data =0 ==> ЛАМПА должна быть ВЫКЛЮЧЕНА.

Хорошо, но как настроить эти поля непосредственно в ThingSpeak? Мы можем сделать это, например, написать «подключаемый модуль» непосредственно в ThinksPeak, или мы можем использовать для этого внешний веб-сайт (это будет нашим выбором). В любом случае, в обоих случаях вам следует использовать такую ​​команду, как:

  api.thingspeak.com/update?key=YOUR_WRITE_KEY&field7=1  

С помощью приведенной выше команды, например (и используя ключ записи вашего канала), вы напишите «1» в поле 7, что означает, что НАСОС должен быть включен. Вы можете легко протестировать это, написав указанную выше командную строку в вашем браузере, соответствующее поле на вашем канале будет изменено. В качестве возврата браузер покажет белую страницу с одним номером в верхнем левом углу, соответствующим последовательному вводу данных в вашем канале.

50% работы выполнено, теперь вы должны прочитать эту «команду» (данные на поле) на локальной станции ArduFarmBot.

Команда для этого показана ниже. Он получит последние данные, которые были записаны в конкретное поле (в нашем случае это будет «команда».

  api.thingspeak.com/channels/CHANNEL_ID/fields/7/last  

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

Вернемся к «земле», напишем функцию, которая будет читать это «последнее поле»:

  / ****************************************** ********* Чтение данных из поля 7 сайта thingspeak.com ********************************* ******************* / int readLastDataField7 () {startThingSpeakCmd (); // "ПОЛУЧИТЬ / каналы / CHANNEL_ID / fields / 7 / last"; cmd =msgReadLastDataField7; cmd + ="\ г \ п"; Строка messageDown =sendThingSpeakCmd (); Serial.print ("Команда получена:"); Serial.println (messageDown [7]); int command =messageDown [7] -48; команда возврата;}  

Вышеупомянутая функция вернет данные из поля 7 («1» или «0»). Аналогичную функцию следует написать для поля 8.

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

  / ****************************************** ********* Получение команд от thingSpeak.com *********************************** ***************** / void receiveCommands () {field7Data =readLastDataField7 (); если (field7Data ==1) {digitalWrite (PUMP_PIN, HIGH); pumpStatus =1; showDataLCD (); } если (field7Data ==0) {digitalWrite (PUMP_PIN, LOW); pumpStatus =0; showDataLCD (); } задержка (500); field8Data =readLastDataField8 (); если (field8Data ==1) {digitalWrite (LAMP_PIN, HIGH); lampStatus =1; showDataLCD (); } если (field8Data ==0) {digitalWrite (LAMP_PIN, LOW); lampStatus =0; showDataLCD (); } задержка (500); }  

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

Еще одно важное соображение - это «координация» между локальным и удаленным управлением. Мы должны изменить функцию readLocalCmd () чтобы также обновить поля Thinkspeak Field 7 и 8 соответственно с помощью состояния насоса и лампы (в соответствующем «заявлении IF». Полный код см. в конце этого руководства):

  field7Data =pumpStatus; field8Data =lampStatus;  

Теперь «filed7Data» и «field8Data» синхронизируются с командами веб-страницы, а также с локальными командными действиями при нажатии кнопки. Итак, давайте обновим aplyCmd () функция, которая отвечает за включение / выключение исполнительных механизмов:

  / ****************************************** ********* Получение команд и воздействие на исполнительные механизмы *********************************** ***************** / void aplyCmd () {если (field7Data ==1) digitalWrite (PUMP_PIN, HIGH); если (field7Data ==0) digitalWrite (PUMP_PIN, LOW); если (field8Data ==1) digitalWrite (LAMP_PIN, HIGH); if (field8Data ==0) digitalWrite (LAMP_PIN, LOW);}  

Когда вы запустите свои тесты, вы поймете, что любая команда, которую вы выполняете вручную локально или через Интернет, будет преодолена автоматическими действиями, определяемыми функцией autoControlPlantation () ; На этом этапе вы должны подумать, кто будет «боссом», за которым будет последнее слово! В нашем случае здесь мы определим следующее:

  • Каждый цикл цикла, то есть почти «всегда», мы будем смотреть, нажата ли кнопка.
  • Каждую минуту мы должны проводить «объединение» в ThingSpeak и проверять, получили ли мы оттуда заказ.
  • Примерно каждые 10 минут мы будем считывать показания датчиков, обновлять данные на ThingSpeak и, что более важно, предпринимать автоматические действия. Эти действия будут выполнены независимо от того, что было выбрано вручную, и будет ли оно сохранено.

Вы можете изменить его, как хотите. Это хорошая вещь в использовании программируемого процессора для управления вещами!

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

  long sampleTimingSeconds =75; // ==> ******** Определение времени выборки в секундах для чтения датчиков ********* int reverseElapsedTimeSeconds =0; long startTiming =0; long elapsedTime =0; long poolingRemoteCmdSeconds =20; // ==> ******** Определить время объединения в секундах для новых команд ThingSpeak ********* long startRemoteCmdTiming =0; long elapsedRemoteCmdTime =0;  

Итак, loop () теперь функция должна быть переписана, как показано ниже:

  void loop () {elapsedRemoteCmdTime =millis () - startRemoteCmdTiming; // Запускаем таймер для объединения удаленных команд elapsedTime =millis () - startTiming; // Запускаем таймер для измерений reverseElapsedTimeSeconds =round (sampleTimingSeconds - elapsedTime / 1000); readLocalCmd (); // Считываем статус локальной кнопки showDataLCD (); если (elapsedRemoteCmdTime> (poolingRemoteCmdSeconds * 1000)) {receiveCommands (); updateDataThingSpeak (); startRemoteCmdTiming =millis (); } если (прошедшее время> (sampleTimingSeconds * 1000)) {readSensors (); autoControlPlantation (); updateDataThingSpeak (); startTiming =millis (); }}  

Шаг 6. Создание выделенной веб-страницы

На данный момент наш ArduFarmBot работает и им можно управлять через Интернет. Вы можете отслеживать данные на сайте Thinkspeak, а также отправлять команды с помощью браузера, но, конечно, это «веб-решение» нельзя считать «элегантным»! Лучший способ реализовать полное решение IoT - разработать полную веб-страницу, на которой будут отображаться все данные, а также кнопки для активации исполнительных механизмов.

Я выбираю Byethost, бесплатный хостинг, который очень легко и просто обрабатывать ваши страницы. Я также воспользовался возможностью применить в этом проекте то, что я узнал по фантастической онлайн-специализации на Coursera / Мичиганском университете:научиться разрабатывать и создавать веб-сайты (создавать адаптивное и доступное веб-портфолио с использованием HTML5, CSS3 и JavaScript. ).

Я не буду вдаваться в подробности, как разработать такую ​​страницу, поскольку это не является основной целью данного руководства, но я включу сюда исходные коды HTML, CSS и JavaScript. И как только кто-то заинтересуется, как я получил результаты, мы можем обсудить это отдельно, используя доску комментариев в конце проекта.

Важно подчеркнуть, что эта страница не работает напрямую с локальной станцией управления ArduFarmBot. На самом деле он взаимодействует с каналом ThinkSpeak, как показано ниже:

  • Считывание данных датчиков в полях 1, 2, 3, 4
  • Чтение статуса привода в полях 5 и 6
  • Запись данных в поля 7 и 8
  • Чтение местных данных о погоде из сервисов Yahoo.

Пункт 4 выше не очень важен для проекта, но всегда доступны дополнительные данные на тот случай, если вы захотите предпринять некоторые удаленные действия, независимо от того, что происходит локально с плантацией ваших помидоров. Другое соображение заключается в том, что вы можете, например, сохранить эти данные на другом канале ThingSpeak и загрузить их на свой Arduino, показывая данные о погоде на локальном ЖК-дисплее (я разработал это в другом классном проекте, который отлично работал! Я оставляю его здесь как предложение для вы).

FQOK9ENIT653YX5.zip

Шаг 7:Вернитесь к мозгу. Матричный подход "датчик-исполнительный элемент":

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

На матрице были определены для каждого датчика его состояние и каким должен быть выход исполнительных механизмов. Результат можно увидеть в таблице Excel, приведенной ниже. В файле Excel есть две таблицы. Таблица с фильтром и версией, в которой вы можете выбрать несколько состояний датчика и посмотреть, как исполнительные механизмы будут работать благодаря этому выбору.

Как только матрица определена, мы должны перевести ее в наш код. Был создан массив из 18 строк и 10 столбцов для «копирования» условий матрицы датчика-исполнительного механизма:

  // + --- ПОЧВА ---- + - СВЕТ - + --- ТЕМП. --- + --- ДЕЙСТВИЕ ---- + // SL SM SH LL LH TL TM TH Насос Lampboolean SDf [18] [10] ={{1, 0, 0, 0, 1, 0, 0, 1, 1, 0}, {1, 0, 0, 0, 1, 0, 1, 0, 1 , 0}, {1, 0, 0, 0, 1, 1, 0, 0, 1, 1}, {1, 0, 0, 1, 0, 0, 0, 1, 1, 0}, {1 , 0, 0, 1, 0, 0, 1, 0, 1, 0}, {1, 0, 0, 1, 0, 1, 0, 0, 0, 1}, {0, 1, 0, 0 , 1, 0, 0, 1, 0, 0}, {0, 1, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 1, 0, 0, 1, 1, 0 , 0, 0, 1}, {0, 1, 0, 1, 0, 0, 0, 1, 0, 0}, {0, 1, 0, 1, 0, 0, 1, 0, 0, 1 }, {0, 1, 0, 1, 0, 1, 0, 0, 0, 1}, {0, 0, 1, 0, 1, 0, 0, 1, 0, 0}, {0, 0 , 1, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 1, 0, 1, 1, 0, 0, 0, 1}, {0, 0, 1, 1, 0 , 0, 0, 1, 0, 0}, {0, 0, 1, 1, 0, 0, 1, 0, 0, 1}, {0, 0, 1, 1, 0, 1, 0, 0 , 0, 1},};  

Для работы с Матрицей создаем функцию defSensorStatus () . Эта функция проверяет для каждой строки, истинны ли условия первых 8 столбцов. Если да, то выполняются условия последних двух столбцов.

Например:

  if (1 и 0, и 0, и 0, и 1, и 0, и 0, и 1) {pumpStatus =1; lampStatus =0} иначе, если (1 и 0, и 0, и 0, и 1, и 0, и 1, и 0) {pumpStatus =1; lampStatus =0}  

и так далее.

Внутри указанной выше функции создается еще один массив со статусом каждого показания датчика:

  логический snsSts [8] ={0, 0, 0, 0, 0, 0, 0, 0}; // SL, SM, SH, LL, LH, TL, TM, TH  

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

F2HWXBYITA8WIN1.xlsx

Шаг 8. Оптимизация кода

В процессе разработки ArduFarmBot мы понимаем, что необходимо внести некоторые изменения в исходную спецификацию:

Медийная реклама:

По умолчанию ЖК-дисплей должен быть ВЫКЛЮЧЕН, и каждый раз, когда требуются показания датчиков, мы можем вручную включить его. Это условие было реализовано в коде, и кнопка «Считывание датчиков» должна использоваться как в режиме «переключения» для включения / выключения ЖК-дисплея в любое время. Включите или выключите дисплей, чтобы обновлять показания датчиков для отображения, но не используется ArduFarmBot в своих обычных функциях.

Первоначальная настройка:

Когда ArduFarmBot включен (или сброшен), на ЖК-дисплее отобразится «Начальная настройка». Для запуска программы необходимо нажать кнопку «Датчики». Показана исходная информация (см. Фото выше):

  • ХОЛОДНАЯ температура (например, 12 ° C)
  • Влажность СУХОЙ почвы (например, 30%)
  • Влажность ВЛАЖНОЙ почвы (например, 60%)
  • ТЕМНЫЙ свет (т. е. 40%)
  • P_ON Время накачки включено (т. е. 10 с)
  • SCAN Время считывания датчиков (т. е. 600 с)
  • SW_Vertion (например, 4.1)

Запись журнала:

Для целей аудита мы создали ЖУРНАЛ с показаниями и действиями нашего ArduFarmBot. В каждом цикле чтения функция: storeDataLogEEPROM () выполняется.

  / ****************************************** ********* Хранение данных журнала в EEPROM Arduino ********************************** ****************** / void storeDataLogEEPROM (void) {for (int i =0; i <8; i ++) {logData =logData + (snsSts [i]) <<1; } EEPROM.write (memoAddr, logData); memoAddr ++; logData =0; logData =logData + pumpStatus; logData =logData <<1; logData =logData + lampStatus; EEPROM.write (memoAddr, logData); EEPROM.write (0, memoAddr + 1); logData =0; если ((memoAddr + 1) ==1023) memoAddr =1; else memoAddr ++;}  

Как отмечалось на последнем шаге, в EEPROM Arduino будет храниться содержимое, бит массива snsSts [] плюс состояние насоса и лампы. Выше вы можете увидеть ЖУРНАЛ последовательного монитора.

Весь код ArduFarmBot был разделен на разные файлы для облегчения понимания. Обратите внимание, что во второй части было добавлено 2 новых файла:

  • communication.ino (Специальные функции ThingSpeak и ESP8266)
  • stationCredentials.h (Идентификатор канала ThingSpeak и специальные ключи для записи на канале)

И последнее, но не менее важное:как только код закончился с разумным размером, мы решили хранить постоянные данные во флэш-памяти (программной) вместо SRAM. Для этого мы используем ключевое слово PROGMEM, которое является модификатором переменной. Например, вместо использования:

  #define DHTPIN 5  

Мы использовали:

  const PROGMEM byte DHTPIN =5;  

Ключевое слово PROGMEN сообщает компилятору «поместить эту информацию во флэш-память», а не в SRAM, куда она обычно помещается. Вы также должны включить библиотеку avr / pgmspace.h в главный файл вашего кода.

Еще одна хорошая процедура для уменьшения использования SRAM - это закомментировать (или удалить) все строки Serial.Print (), которые вы использовали для отладки во время разработки. Вы поймете, что код, используемый, например, для отображения журнала в последовательном мониторе, будет прокомментирован в файлах ниже.

Ниже вы можете найти полный код ArduFarmBot Arduino. Не забудьте заменить фиктивные данные на credentials.h своим идентификатором канала и ключом записи. Также на сайте communication.ino используйте свое настоящее имя пользователя и пароль для подключения ESP 8266 к Интернету.

FTUT5VIIT67U8ME.ino FWMIPSSIT67U8MG.ino FJPGZNKIT67U8MK.ino FQH3X9VIT67U8NA.ino F15MY4YIT67U8NB.ino FVU64X1IT67U8NC.h FZ057E3IT67U8P5.h

Шаг 9. Домашняя ферма MJRovai

На фотографиях ниже показаны последовательные фотографии ArduFarmBot, контролирующего мою первую плантацию томатов.

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

Шаг 10:Заключение

Вот и все, ребята! ... А пока!

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

Вскоре мы, вероятно, опубликуем третью и последнюю часть нашего проекта, которая, я надеюсь, будет очень хорошим рецептом пасты с органическим томатным соусом.

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

ArduFarmBot, the Book!

"ArduFarmBot, the book" is also at Amazon.com! You can get it, by clicking hereThe book uses the electronic controller ArduFarmBot as a basis for teaching how to work in both HW and SW, with:

  • LCD and OLED type displays;
  • LEDs and buttons;
  • Activation of pumps and lamps via relays and
  • Sensors such as:DHT22 (temperature and relative air humidity), DS18B20 (soil temperature), YL69 (soil moisture) and LDR (luminosity).

All key stages of the project are documented in detail through explanatory texts, block diagrams, high-resolution color photos, electrical diagrams using Fritzing application, complete codes stored in GitHub and YouTube videos.

Two versions of the electronic controller ArduFarmBot are developed in detail in the book. From capture of data coming from a garden, such as air and soil temperature, relative humidity, soil moisture and luminosity, the ArduFarmBot helps to control when a crop should receive heat and water. Control will happen automatically, locally and remotely via internet. The book is divided into 3 parts. In the first part, the Arduino Nano is the starting point for development of a local version of ArduFarmBot , that can be controlled both, manually and automatically.

In the second part, the book dives into automation design, introducing remote operation through the creation of a webpage. The ESP8266-01 is used for Wi-Fi connection, sending data to an important web service in the field of IoT, the ThingSpeak.com .

In the third part, a second version of ArduFarmBot is developed, introducing the NodeMCU ESP8266-12E , a powerful and versatile IoT device, which replaces both the Arduino Nano and the ESP8266-01 , used in the earlier parts of the book.

In this last part of the book, a new service platform of the IoT universe, the Blynk , is also explored.

Download the book, give it a review and please use the message board here to give us any comment, suggestion or critic!

For more projects, please visit my blog:MJRoBot.org

Saludos from the south of the world!

See you at my next project!

Thank you

Марсело

Код

  • Фрагмент кода №1
  • Фрагмент кода №2
  • Фрагмент кода №3
  • Фрагмент кода 4
  • Фрагмент кода 5
  • Code snippet #6
  • Code snippet #9
  • Code snippet #10
  • Фрагмент кода №11
  • Code snippet #12
  • Code snippet #13
  • Code snippet #14
  • Code snippet #15
Фрагмент кода №1 Обычный текст
/**************************************************** Reset funtion to accept communication****************************************************/void reset8266(void){ pinMode(CH_PD, OUTPUT); digitalWrite(CH_PD, LOW); задержка (300); digitalWrite(CH_PD, HIGH); Serial.print("8266 reset OK"); lcd.clear (); lcd.println("8266 reset OK ");}
Фрагмент кода 2 Обычный текст
/**************************************************** Connect WiFi****************************************************/void connectWiFi(void){ sendData("AT+RST\r\n", 2000, DEBUG); // reset sendData("AT+CWJAP=\"USERNAME\",\"PASSWORD\"\r\n", 2000, DEBUG); //Connect network delay(3000); sendData("AT+CWMODE=1\r\n", 1000, DEBUG); sendData("AT+CIFSR\r\n", 1000, DEBUG); // Show IP Adress lcd.clear(); lcd.print("8266 Connected"); Serial.println("8266 Connected");}
Фрагмент кода № 3 Обычный текст
/**************************************************** Send AT commands to module****************************************************/String sendData(String command, const int timeout, boolean debug){ String response =""; esp8266.print(command); long int time =millis(); while ( (time + timeout)> millis()) { while (esp8266.available()) { // The esp has data so display its output to the serial window char c =esp8266.read(); // read the next character. response +=c; } } if (debug) { Serial.print(response); } return response;}
Фрагмент кода №4 Обычный текст
/**************************************************** Transmit data to thingspeak.com****************************************************/void updateDataThingSpeak(void){ startThingSpeakCmd (); cmd =msg; cmd +="&field1="; //field 1 for DHT temperature cmd +=tempDHT; cmd +="&field2="; //field 2 for DHT humidity cmd +=humDHT; cmd +="&field3="; //field 3 for LDR luminosity cmd +=lumen; cmd +="&field4="; //field 4 for Soil Moisture data cmd +=soilMoist; cmd +="&field5="; //field 5 for PUMP Status cmd +=pumpStatus; cmd +="&field6="; //field 6 for LAMP Status cmd +=lampStatus; cmd +="\r\n"; sendThingSpeakCmd();}
Фрагмент кода № 5 Обычный текст
/**************************************************** Start communication with ThingSpeak.com****************************************************/void startThingSpeakCmd(void){ cmd ="AT+CIPSTART=\"TCP\",\""; cmd +=IP; cmd +="\",80"; esp8266.println(cmd); задержка (2000); if(esp8266.find("Error")) { Serial.println("ESP8266 START ERROR"); возвращение; } Serial.println("Thinkspeak Comm Started"); cmd ="";}
Code snippet #6Plain text
/*************************************************** * Update channel ThingSpeak.com****************************************************/String sendThingSpeakCmd(void){ esp8266.print("AT+CIPSEND="); esp8266.println(cmd.length()); if(esp8266.find(">")){ esp8266.print(cmd); Serial.println (""); Serial.println (""); Serial.println(cmd); задержка (500); String messageBody =""; while (esp8266.available()) { String line =esp8266.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =esp8266.readStringUntil('\n'); Serial.print("Message received:"); Serial.println(messageBody); } } return messageBody; } else{ esp8266.println("AT+CIPCLOSE"); Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... error=1; return "error"; }} 
Code snippet #9Plain text
/**************************************************** Read data from field7 of thingspeak.com****************************************************/int readLastDataField7(){ startThingSpeakCmd (); // "GET /channels/CHANNEL_ID/fields/7/last"; cmd =msgReadLastDataField7; cmd +="\r\n"; String messageDown =sendThingSpeakCmd(); Serial.print("Command received:"); Serial.println(messageDown[7]); int command =messageDown[7]-48; return command;}
Code snippet #10Plain text
/**************************************************** Receive Commands from thingSpeak.com****************************************************/void receiveCommands(){ field7Data =readLastDataField7(); if (field7Data ==1) { digitalWrite(PUMP_PIN, HIGH); pumpStatus =1; showDataLCD(); } if (field7Data ==0) { digitalWrite(PUMP_PIN, LOW); pumpStatus =0; showDataLCD(); } delay (500); field8Data =readLastDataField8(); if (field8Data ==1) { digitalWrite(LAMP_PIN, HIGH); lampStatus =1; showDataLCD(); } if (field8Data ==0) { digitalWrite(LAMP_PIN, LOW); lampStatus =0; showDataLCD(); } delay (500); } 
Фрагмент кода № 11 Обычный текст
/**************************************************** Receive Commands and act on actuators****************************************************/void aplyCmd(){ if (field7Data ==1) digitalWrite(PUMP_PIN, HIGH); if (field7Data ==0) digitalWrite(PUMP_PIN, LOW); if (field8Data ==1) digitalWrite(LAMP_PIN, HIGH); if (field8Data ==0) digitalWrite(LAMP_PIN, LOW);}
Code snippet #12Plain text
long sampleTimingSeconds =75; // ==> ******** Define Sample time in seconds to read sensores *********int reverseElapsedTimeSeconds =0;long startTiming =0;long elapsedTime =0;long poolingRemoteCmdSeconds =20; // ==> ******** Define Pooling time in seconds for new ThingSpeak commands *********long startRemoteCmdTiming =0; long elapsedRemoteCmdTime =0;
Code snippet #13Plain text
void loop() { elapsedRemoteCmdTime =millis()-startRemoteCmdTiming; // Start timer for pooling remote commands elapsedTime =millis()-startTiming; // Start timer for measurements reverseElapsedTimeSeconds =round (sampleTimingSeconds - elapsedTime/1000); readLocalCmd(); //Read local button status showDataLCD(); if (elapsedRemoteCmdTime> (poolingRemoteCmdSeconds*1000)) { receiveCommands(); updateDataThingSpeak(); startRemoteCmdTiming =millis(); } if (elapsedTime> (sampleTimingSeconds*1000)) { readSensors(); autoControlPlantation(); updateDataThingSpeak(); startTiming =millis(); }} 
Code snippet #14Plain text
 // +---SOIL----+-LIGHT-+---TEMP---+---ACTUAT----+ // SL SM SH LL LH TL TM TH Pump Lampboolean SDf [18] [10] ={{ 1, 0, 0, 0, 1, 0, 0, 1, 1, 0 }, { 1, 0, 0, 0, 1, 0, 1, 0, 1, 0 }, { 1, 0, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 0, 0, 1, 0, 0, 0, 1, 1, 0 }, { 1, 0, 0, 1, 0, 0, 1, 0, 1, 0 }, { 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, { 0, 1, 0, 0, 1, 0, 1, 0, 0, 0 }, { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, { 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }, { 0, 1, 0, 1, 0, 0, 1, 0, 0, 1 }, { 0, 1, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, { 0, 0, 1, 0, 1, 0, 1, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1 }, { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, { 0, 0, 1, 1, 0, 1, 0, 0, 0, 1 }, };
Code snippet #15Plain text
/**************************************************** Storage of Log data at Arduino EEPROM****************************************************/void storeDataLogEEPROM(void){ for (int i =0; i<8; i++) { logData =logData + (snsSts[i])<<1; } EEPROM.write (memoAddr, logData); memoAddr++; logData =0; logData =logData + pumpStatus; logData =logData <<1; logData =logData + lampStatus; EEPROM.write (memoAddr, logData); EEPROM.write (0, memoAddr+1); logData =0; if ((memoAddr+1) ==1023) memoAddr=1; else memoAddr++;} 
ArduFarmBot GitHub
https://github.com/Mjrovai/ArduFarmBot

Схема

ardufarmbot_qpNcBDX6Jr.fzz

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

  1. Тенденции реализации IoT
  2. 6-Shooter:станция для смешивания напитков Arduino
  3. Многотемпературный датчик
  4. MotionSense
  5. Пожарная безопасность 3D-принтера
  6. Датчик Интернета вещей с Arduino, Yaler и IFTTT
  7. Отталкивающая электромагнитная левитация Arduino
  8. Бот для захвата удаленного управления
  9. Регистратор данных с погодными шарами на базе Arduino
  10. CoroFence - Тепловой детектор🖖