亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

ArduFarmBot - 第 2 部分:远程站和物联网实施

组件和用品

Arduino Nano R3
× 1
乐鑫 ESP8266 ESP-01
× 1
DHT22 温度传感器
× 1
ky18
× 1
比重计
× 1
中继(通用)
× 2
lcd 4X20
× 1
SparkFun 按钮开关 12mm
× 3
LED(通用)
× 3

应用和在线服务

ThingSpeak API

关于这个项目

本教程是 ArduFarmBot:使用 Arduino 和物联网控制番茄家庭农场的延续

在第一部分中,我们创建了一个本地控制站,从番茄种植园捕获信息,如温度、相对空气湿度、光度和土壤湿度。根据这些数据,ArduFarmBot 会自动决定种植园应该接受的热量和水量(以及何时)。在第 1 部分开发的本地站还允许操作员手动干预以控制水泵和电灯。在第 2 部分中,我们将实施物联网方法,如果这种“手动干预”也可以通过互联网远程进行。框图显示了我们将如何做到这一点。

请注意,捕获的数据将发送到“云存储服务”(在我们的示例中为 Thinkspeak.com)。同样是一个专门的网站,“远程控制页面”将几乎实时监控和显示这些数据。该网页还允许远程激活泵和灯。

第 1 步:物料清单

  • Arduino Nano -(7.50 美元)
  • 温度和湿度传感器 DHT22 或 DHT11 -(3.66 美元)
  • 亮度传感器 - AD-018 光敏电阻模块。或任何等价物 -(0.71 美元)
  • 2X 土壤湿度传感器 -(1.99 美元)(可选,可以 DIY)
  • LCD I2C 20X4(13.99 美元)
  • LED (1X)(0.20 美元)
  • Esp8266 串行 Wifi 无线收发器模块 Esp-01 -(5.96 美元)
  • 有源蜂鸣器 - Ky-12 或同等产品(0.60 美元)
  • 2 X 5v 继电器模块(11.60 美元)
  • 跳线(S1.00)
  • 10KOhms 电阻器 - ($0.03)
  • 2.2K 欧姆电阻 - ($0.03)
  • 1.0K 欧姆电阻 - ($0.03)
  • 220 欧姆电阻 - ($0.03)
  • Arduino Nano Shield(“Funduino”)-(7.28 美元)
  • 薄膜键盘(4 个键)-(6.65 美元)
  • 塑料盒

第 2 步:完成硬件

从第 1 部分开发的本地站开始,唯一需要的额外硬件是 ESP8266。上面的框图显示了所有 Arduino 和主要组件的 PIN 连接。您唯一需要注意的是与电压电平有关。 ESP8266 工作电压为 3.3V,因此不应将 Rx Pin 直接连接到 Nano Tx Pin (D3)。应使用电压电平。在我们的例子中,我们将构建一个用作电压电平转换器的分压器。上图更详细地展示了如何连接 ESP8266。如果您想了解更多关于 ESP8266 的信息,请看我的教程:

  • ESP8266 第 3 部分 - 远程触发 Arduino LED
  • ESP8266 第 1 部分 - 适用于 Arduino 的串行 WIFI 模块
  • ESP8266 第 2 部分 - Arduino 网络服务器

请注意,我们使用连接到 Nano Pin 2 (Tx) 和 Pin 3 (Rx) 的 ESP8266,使用库 SoftSerial。如果你想“释放”那些数字引脚,你可以交替使用 Nano Serial 引脚 0 和 1。只记得上传代码到 Nano 时必须断开它们。

注意:如果你想连接蜂鸣器,你应该在引脚 D17(与引脚 A3 相同)上进行。当您遇到通信错误时有声音是很好的。我在测试阶段使用它,在最终项目中使用它(硬件,但代码已为此准备)。这取决于你拥有与否。

您可以使用以下代码来测试和/或设置您的 ESP8266:

FC9DBPKIT682FY7.ino

第 3 步:ESP8266 连接

为了将 ArduFarmBot 连接到互联网,我们将使用 ESP8266,这是一种用于物联网项目的简单、廉价且易于编程的模块。安装模块后,首先要做的是在其 CH-PD 引脚上应用“复位”。

/*********************************************** ********* 重置功能以接受通讯**************************************** ****************/void reset8266(void){ pinMode(CH_PD, OUTPUT);数字写入(CH_PD,低);延迟(300);数字写入(CH_PD,高); Serial.print("8266 复位OK");液晶显示器(); lcd.println("8266 reset OK");}  

重置后,让我们使用您的凭据将其连接到您的本地网络(在代码中,更改:用户名和密码)并将模块启动为“STA:站模式”(CWMODE =1):

/*********************************************** ********* 连接 WiFi******************************************** *************/void connectWiFi(void){ sendData("AT+RST\r\n", 2000, DEBUG); // 重置 sendData("AT+CWJAP=\"USERNAME\",\"PASSWORD\"\r\n", 2000, DEBUG); //连接网络延迟(3000); sendData("AT+CWMODE=1\r\n", 1000, DEBUG); sendData("AT+CIFSR\r\n", 1000, DEBUG); // 显示 IP 地址 lcd.clear(); lcd.print("8266 已连接"); Serial.println("8266 已连接");} 

要将数据发送到 ESP8266,函数 sendData() 被使用过:

/*********************************************** ********* 向模块发送 AT 命令**************************************** ****************/String sendData(String command, const int timeout, boolean debug){ String response =""; esp8266.print(命令); long int time =毫秒(); while ( (time + timeout)> millis()) { while (esp8266.available()) { // esp 有数据,因此将其输出显示到串行窗口 char c =esp8266.read(); // 读取下一个字符。响应 +=c; } } 如果(调试){ Serial.print(响应); }返回响应;} 

上述函数将在我们代码的“设置阶段”期间调用。如果一切正常,您应该在串行监视器上看到与上述类似的消息。

第 4 步:云存储数据:ThinkSpeak.com

ArduFarmBot 捕获的所有数据都将使用“ThinkSpeak.com”的免费服务上传到云端。

在“Loop()”函数中(在我们使用 readSensors() 捕获数据之后 ),我们将调用一个特定的函数来上传捕获的数据:updateDataThingSpeak();

/*********************************************** ********* 将数据传输到thingspeak.com*************************************** *****************/void updateDataThingSpeak(void){ startThingSpeakCmd(); cmd =味精; cmd +="&field1="; //字段1为DHT温度cmd +=tempDHT; cmd +="&field2="; //字段2为DHT湿度cmd +=humDHT; cmd +="&field3="; //字段 3 为 LDR 亮度 cmd +=lumen; cmd +="&field4="; // 土壤水分数据的字段 4 cmd +=oilMoist; cmd +="&field5="; // 泵状态 cmd +=pumpStatus 的字段 5; cmd +="&field6="; //字段 6 用于 LAMP 状态 cmd +=lampStatus; cmd +="\r\n"; sendThingSpeakCmd();}  

为了发送这些数据,首先要做的是开始与 ThingSpeak 的通信。我们将使用以下函数执行此操作:startThingSpeakCmd ();

/*********************************************** ********* 开始与 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 开始"); cmd ="";} 

一旦使用 ThingSpeak 打开通道并且“cmd”字符串与数据组合在一起,就可以使用以下函数将所有数据上传到 ThingSpeak 的对应通道:sendThingSpeakCmd();

/*********************************************** ******** * 更新频道 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) { //实际内容从空行(长度为1)之后开始 messageBody =esp8266.readStringUntil('\n'); Serial.print("收到消息:"); Serial.println(messageBody);返回 messageBody; } else{ esp8266.println("AT+CIPCLOSE"); Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //重新发送... error=1;返回“错误”; }} 

上述功能基于 Michalis Vasilakis 开发的精彩而详细的教程。详情请看他的教程:Arduino IOT:温度和湿度(带ESP8266 WiFi)。

图为 ThingSpeak.com 上的 ArduFarmBot 频道。

第 5 步:从网络命令执行器

此时我们正在上传所有收集的数据并将它们存储在云端。这对于远程监控非常好和有用,但是如果基于这些数据我们还想打开泵或灯,独立于本地自动程序,会发生什么?为此,我们还需要从云端“下载”数据并命令控制器根据这些命令采取行动。

我们将在我们的 ThinkSpeak 频道上创建特定字段来命令执行器:

字段 7:

  • Data =1 ==> PUMP 应该打开
  • Data =0 ==> PUMP 应该关闭

字段 8:

  • Data =1 ==> LAMP 应该打开
  • Data =0 ==> LAMP 应该关闭

好的,但是如何直接在 ThingSpeak 中设置这些字段?我们可以这样做,例如直接在 ThinksPeak 上编写“插件”,或者我们可以使用外部网站来完成(这将是我们的选择)。无论如何,在这两种情况下,您都应该使用如下命令:

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

例如,使用上述命令(并使用您的通道写入密钥),您将在第 7 栏写入“1”,这意味着应该打开 PUMP。您可以轻松测试它,在您的浏览器中编写上述命令行,您频道的通讯录字段将被更改。作为回报,浏览器会在左上角显示一个白色的页面,上面有一个数字,对应于您频道中的序列数据条目。

50%的工作已经完成,现在你必须在当地的ArduFarmBot站阅读这个“命令”(现场数据)。

执行此操作的命令如下所示。它将获得在特定字段写入的最后一个数据(在我们的例子中将是一个“命令”。

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

与我们之前所做的一样,您可以使用 Web 浏览器测试命令行。在这种情况下,浏览器将向您显示该特定字段的数据。请参阅上面的照片。

回到“地球”,我们写一个函数来读取这个“最后一个字段”:

/*********************************************** ********* 从 thingspeak.com 的 field7 读取数据************************************ *******************/int readLastDataField7(){ startThingSpeakCmd(); // "GET /channels/CHANNEL_ID/fields/7/last"; cmd =msgReadLastDataField7; cmd +="\r\n"; String messageDown =sendThingSpeakCmd(); Serial.print("收到命令:"); Serial.println(messageDown[7]); int 命令 =messageDown[7]-48;返回命令;} 

上述函数将返回字段 7 上的数据(“1”或“0”)。应该为字段 8 编写类似的函数。

一旦我们获得了两个字段的内容,我们就应该将它们用在一个函数上,该函数将像我们使用“手动命令功能”一样命令执行器:

/*********************************************** ********* 从thingSpeak.com 接收命令*************************************** *****************/void receiveCommands(){ field7Data =readLastDataField7(); if (field7Data ==1) { digitalWrite(PUMP_PIN, HIGH);泵状态 =1; showDataLCD(); } if (field7Data ==0) { digitalWrite(PUMP_PIN, LOW);泵状态 =0; showDataLCD(); } 延迟(500); field8Data =readLastDataField8(); if (field8Data ==1) { digitalWrite(LAMP_PIN, HIGH);灯状态 =1; showDataLCD(); } if (field8Data ==0) { digitalWrite(LAMP_PIN, LOW);灯状态 =0; showDataLCD(); } 延迟(500); } 

因此,从现在开始,您可以使用浏览器中的命令行远程打开/关闭泵和灯。上图显示了接收到的命令将如何出现在您的串行监视器上。

另一个重要的考虑是本地和远程命令之间的“协调”。我们必须改变 readLocalCmd() 函数 还分别使用泵和灯状态更新 Thinkspeak Field 7 和 8(在其对应的“IF 语句”中。请参阅本教程末尾的完整代码):

field7Data =pumpStatus;field8Data =lampStatus; 

现在,当您按下按钮时,“filed7Data”和“field8Data”与网页命令以及本地命令操作同步。所以,让我们更新 aplyCmd() 功能,即负责打开/关闭执行器的功能:

/*********************************************** ********* 接收命令并作用于执行器*************************************** *****************/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);} 

当您开始测试时,您会意识到您在本地或通过网络手动执行的任何命令都将被函数 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(); if (elapsedRemoteCmdTime> (poolingRemoteCmdSeconds*1000)) { receiveCommands(); updateDataThingSpeak(); startRemoteCmdTiming =毫秒(); } if (elapsedTime> (sampleTimingSeconds*1000)) { readSensors();自动控制种植园(); updateDataThingSpeak(); startTiming =毫秒(); }} 

第 6 步:实现专用网页

此时我们的 ArduFarmBot 可以运行并且可以通过网络进行控制。您可以在 Thinkspeak 网站上监控数据,也可以使用浏览器发送命令,但是这种“网络解决方案”当然不能算是“优雅”的解决方案!实施完整物联网解决方案的最佳方法是开发一个完整的网页,该网页将显示所有数据,并具有用于激活执行器的按钮。

我选择 Byethost,一个免费的虚拟主机,非常容易和简单地处理您的页面。我还利用这个机会申请了这个项目,我在 Coursera/密歇根大学的一个很棒的在线专业中学到的东西:学习设计和创建网站(使用 HTML5、CSS3 和 JavaScript 构建响应式和可访问的网络组合).

我不会详细介绍如何开发这样的页面,因为这不是本教程的中心目的,但我将在此处包含 HTML、CSS 和 JavaScript 源代码。一旦有人对我如何得到结果感兴趣,我们可以在项目结束时使用评论板进行讨论。

重要的是要强调此页面不能直接与 ArduFarmBot 本地控制站一起使用。它真正在做的是与 ThinkSpeak 频道互动,如下所示:

  • 读取字段 1、2、3、4 上的传感器数据
  • 读取字段 5 和 6 上的执行器状态
  • 在字段 7 和 8 上写入数据
  • 从雅虎服务读取本地天气数据

上面的第 4 项对于该项目来说并不是真正重要的,但是如果您想采取一些与番茄种植园本地正在发生的事情无关的远程操作,则总是有额外的数据可用。其他考虑是,例如,您可以将这些数据存储在另一个 ThingSpeak 频道上并将其下载到您的 Arduino,在本地 LCD 显示屏上显示天气数据(我在另一个很酷的项目上开发了这个,效果很好!我把它留在这里作为建议你)。

FQOK9ENIT653YX5.zip

第七步:回到大脑。传感器-执行器矩阵方法:

在这个项目的第一部分,我们已经定义了一些关于执行器应该如何根据传感器读数起作用的初步考虑。我们只做了简单的选择,但如果我们有更复杂的情况会发生什么?几种不同的条件?我们将开发的是“传感器 - 执行器矩阵方法”。

在矩阵上为每个传感器定义了它的条件以及执行器的输出应该如何。结果可以在下面包含的 Excel 电子表格中看到。在 Excel 文件中有两个电子表格。在带有过滤器和版本的表格中,您可以选择多个传感器条件,并查看执行器在此选择后将如何工作。

一旦定义了矩阵,我们必须将其转换为我们的代码。创建了一个 18 行 10 列的数组来“复制”传感器-执行器矩阵的条件:

 // +---SOIL----+-LIGHT-+---TEMP---+---ACTUAT----+ // 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 列的条件是否为 TRUE。如果是,则执行最后两列的条件。

例如:

if (1 and 0 and 0 and 0 and 1 and 0 and 0 and 1) { pumpStatus =1; lampStatus =0}else if (1 and 0 and 0 and 0 and 1 and 0 and 1 and 0) { pumpStatus =1;灯状态 =0} 

等等。

在上述函数中,创建了另一个数组,其中包含每个传感器读数的状态:

boolean snsSts[8]={0, 0, 0, 0, 0, 0, 0, 0}; // SL、SM、SH、LL、LH、TL、TM、TH 

此变量数组也将用于 LOG 寄存器。

F2HWXBYITA8WIN1.xlsx

第 8 步:代码优化

在开发 ArduFarmBot 的过程中,我们意识到应该对原始规范进行一些更改:

显示:

默认情况下,LCD 显示屏应关闭,任何时候需要传感器读数,我们都可以手动将其“打开”。此条件已在代码上实现,并且应在“切换”模式下使用“传感器读取”按钮随时打开/关闭 LCD。打开或关闭显示器将更新传感器读数以进行显示,但 ArduFarmBot 不会在其常规功能上使用。

初始设置:

当 ArduFarmBot 开启(或重置)时,LCD 将显示“初始设置”。要开始运行程序,必须按下“传感器”按钮。显示的初始信息(见上图)为:

  • 低温(即 12oC)
  • 干燥土壤湿度(即 30%)
  • 湿土壤湿度(即 60%)
  • 暗光(即 40%)
  • P_ON 开启泵送时间(即 10 秒)
  • SCAN 读取传感器的时间(即 600 秒)
  • SW_Vertion(即 4.1)

日志记录:

出于审计目的,我们创建了一个包含 ArduFarmBot 读数和驱动的日志。在每个读取周期,函数:storeDataLogEEPROM() 被执行。

/*********************************************** ********* 在 Arduino EEPROM 中存储日志数据************************************ ******************/void storeDataLogEEPROM(void){ for (int i =0; i<8; i++) { logData =logData + (snsSts[i])<<1; } EEPROM.write(memoAddr, logData);备忘录地址++;日志数据 =0; logData =logData + pumpStatus;日志数据 =日志数据 <<1; logData =logData + 灯状态; EEPROM.write (memoAddr, logData); EEPROM.write (0, memoAddr+1);日志数据 =0;如果 ((memoAddr+1) ==1023) memoAddr=1; else memoAddr++;}  

正如在最后一步中所评论的,将存储在 Arduino EEPROM 中的是内容,有点数组 snsSts[] 加上泵和灯状态。在上面你可以看到串行监视器上的日志。

为了更容易理解,所有的 ArduFarmBot 代码都被分成了不同的文件。请注意,在第二部分添加了 2 个新文件:

  • communication.ino (ThingSpeak 和 ESP8266 特定功能)
  • stationCredentials.h (ThingSpeak 频道 ID 和用于在频道上写入的特定键)

最后但并非最不重要的是,一旦代码以合理的大小结束,我们决定将常量数据存储在闪存(程序)存储器而不是 SRAM 中。为此,我们使用作为变量修饰符的 PROGMEM 关键字。例如,而不是使用:

#define DHTPIN 5 

我们使用了:

const PROGMEM byte DHTPIN =5; 

关键字 PROGMEN 告诉编译器“将此信息放入闪存中”,而不是放入 SRAM,它通常会放在那里。您还必须在代码的主文件中包含库 avr/pgmspace.h。

另一个减少 SRAM 使用的好方法是注释(或删除)您在开发过程中用于调试的所有 Serial.Print() 行。您将意识到用于例如在串行监视器上显示日志的代码将在波纹管文件中进行注释。

您可以在下面找到完整的 ArduFarmBot Arduino 代码。不要忘记使用您的频道 ID 和写入密钥更改凭据.h 上的虚拟数据。同样在communication.ino,使用您的真实用户名和密码在互联网上连接ESP 8266。

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

第 9 步:MJRovai 家庭农场

下面的照片显示了 ArduFarmBot 控制我的第一个番茄种植园的连续照片。

The below photo sequence, shows my 2nd plantation evolution from seed plantation until the time to select the best plants (around 45 days) and the transplantations of best 6 plants.

Step 10:Conclusion

That's all folks! ...For now!

As always, I hope this project can help others find their way in the exciting world of electronics, IoT and Robotics!

Soon we probably will publish the third and last part of our project that I hope will be a very good recipe of a organic tomato sauce pasta.

By the way, on the above photo you can see the first sighs of life on Mauricio's plantation! And before you go, please give a look and the new ArduFarmBot, the book!, where I pack all project on a more friendly format:

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 视频。

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

Marcelo

代码

  • 代码片段 #1
  • 代码片段#2
  • Code snippet #3
  • Code snippet #4
  • Code snippet #5
  • Code snippet #6
  • Code snippet #9
  • Code snippet #10
  • Code snippet #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); delay(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");}
Code snippet #3Plain text
/**************************************************** 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;}
Code snippet #4Plain text
/**************************************************** 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();}
Code snippet #5Plain text
/**************************************************** Start communication with ThingSpeak.com****************************************************/void startThingSpeakCmd(void){ cmd ="AT+CIPSTART=\"TCP\",\""; cmd +=IP; cmd +="\",80"; esp8266.println(cmd); delay(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); }
Code snippet #11Plain text
/**************************************************** 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. 物联网实施趋势
  2. 6-Shooter:Arduino 饮料混合站
  3. 多温度传感器
  4. MotionSense
  5. 3D 打印机消防安全
  6. 带有 Arduino、Yaler 和 IFTTT 的物联网仪表
  7. Arduino 排斥电磁悬浮
  8. 遥控夹爪机器人
  9. Arduino Powered Weather Balloon Datalogger
  10. $10 便携式 Arduino 气象站 (AWS)
  11. 微控制器实验室
  12. CoroFence - 热探测器🖖