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

Herb Box 生态系统

组件和用品

亚马逊 Alexa Echo Dot
× 1
Arduino UNO
× 1
乐鑫 ESP8266 ESP-01
× 1
Arduino Proto Shield
× 1
Arduino 4 继电器屏蔽
× 1
Aqua Pump
× 2
植物生长灯
× 1
220V 直流电源适配器
× 1
12V 直流电源适配器
× 1
USB 电源插头 + 电缆
× 1
空气软管
× 1
跳线(通用)
× 1

应用和在线服务

Arduino IDE
亚马逊 Alexa Alexa 技能套件
亚马逊网络服务 AWS Lambda
php 网络服务器

关于这个项目

由于我的植物总是受到过多或过少的水的影响,而且我喜欢在菜肴中加入大量草药,因此我决定创建一个定制的灌溉系统。我的草药盒应该是可配置的,可以自动或手动工作。因此,存在一个网站界面以启用设置并在漂亮的图表中显示湿度。最后一步是集成语音控制,向亚马逊 Alexa 询问湿度,打开/关闭植物生长灯,并在禁用自动化时启动灌溉。点击这里查看结果。

我从项目的技术部分开始,买了一个 Arduino。经过一些教程,我对软件和控制 Arduino 有了坚定的信念。我订购了一个 wifi 控制器、一些湿度传感器、泵、一个植物生长灯和额外的必需硬件(relais shield 将灯和泵的电路与 Arduino 分开,一些电线和山毛榉木用于框架)。本教程提供了结果的 Arduino 代码,以及如何在项目中使用组件的一些信息。不提供网站/api代码(除非要求非常高;))。

第一步:湿度传感器

第一个里程碑是用我的 Arduino 读取湿度。湿度传感器 YL-69 很容易与 Arduino 连接。您需要将 VCC 引脚连接到 Arduino 的 GPIO 引脚(在我的示例引脚 06 中)、接地和 A0 到模拟引脚(在我的示例引脚 A1 中)。

教程:土壤湿度传感器

byte vccPin =6;byte dataPin =A1;void setup() { pinMode(vccPin, OUTPUT);数字写入(vccPin,低); Serial.begin(9600); while (!Serial);}int readHumidity() { digitalWrite(vccPin, HIGH);延迟(500); // 你需要在测量前测试你预通电的时间 int value =analogRead(dataPin);数字写入(vccPin,低); return 1023 - value;}void loop() { Serial.print("HumidityLevel (0-1023):"); Serial.println(readHumidity());延迟(10000);} 

第二步:泵和灯的继电器

下一个目标是安装一个继电器屏蔽(4 个继电器)来分隔灯、泵和 Arduino 的电路。 Arduino 以 5V 运行,泵使用 12V,植物生长灯使用 230V。屏蔽需要连接到 Arduino 上的 5V 和接地引脚。每个继电器还需要一个您选择的 GPIO 引脚来打开和关闭。最后,您可以在屏蔽上使用 VCC JC 到 VCC 的跳线,或者使用额外的电池(这会是最好的,但我的项目中还没有任何电池)。

重要的是要了解,我的屏蔽在引脚上以“低”开关“打开”。一旦我的引脚被定义为输出,它就会自动切换到活动状态。在代码中,如果您希望继电器关闭,您应该始终切换到 INPUT 和 LOW。默认情况下,Arduino 引脚为 INPUT 和低电平。

教程:中继盾

信息:为什么继电器 OUTPUT + LOW =Active?

byte pump1 =11;byte pump2 =10;void setup() { Serial.begin(9600);而(!串行); pinMode(泵1,输出); // 变量低/高 digitalWrite(pump2, LOW); // 变量输入/输出}void loop() { digitalWrite(pump1, HIGH); // pump1 停用 pinMode(pump2, INPUT); // pump2 停用延迟(1000);数字写入(泵 1,低); // pump1 激活 pinMode(pump2, OUTPUT); // pump2 激活延迟(1000);} 

第三步:使用 ESP-01 的 WiFi

将 espressif ESP8266 ESP-01 连接到 Arduino for WiFi 是最困难的部分。我花了几个小时才让 wifi 在我的脚本中运行。

ESP 连接到:VCC =3.3V,GND =GND,CH_PD =3.3V,TX =引脚 02,RX =引脚 03。为了生产使用,你应该至少使用一个从 5V 到 3.3V 的电平转换器作为引脚02 和引脚 03,也是。就我而言,它运行良好。

与 Arduino 类似,ESP-01 是另一个微控制器。如果您希望两个控制器进行通信,则必须使用串行通信。 Arduino UNO 默认使用引脚 01 和 02 作为 RX 和 TX。但它们也用于 USB 调试,因此建议包含 SoftwareSerial.h 并定义自定义引脚。

#include SoftwareSerial espSerial(3,2); // RX, TXvoid setup() { Serial.begin(9600); espSerial.begin(115200); // AT+UART_DEF=9600,8,1,0,0后切换到9600 while (!Serial);}void loop() { if (espSerial.available()) { Serial.write(espSerial.read()); } if (Serial.available()) { espSerial.write(Serial.read()); }} 

运行上面的脚本,您可以在串行监视器中输入 AT 命令并查看结果。串口通讯容易出现故障,因此我将ESP使用的通讯波特率从115200降低到9600。

教程:ESP8266 + Arduino |教程:ESP8266通用(德语)

  • 一个有用的辅助类(但使用了太多内存):库:WiFiEsp
  • 内存检查工具:库:MemoryFree

该脚本使用 HTTP 1.0,因为对于 HTTP 1.1,字节是响应的一部分。重要的是要注意 AT+CIPSEND 之后要发送的命令的换行符。如果它们是错误的,您将收到一个字节发送错误。

#include SoftwareSerial espSerial(3,2); // RX, TXconst char* ssid ="";const char* pass ="";void setup() { Serial.begin(9600); espSerial.begin(9600);而(!串行); while(!connectToWiFi()); // 请求网站并打印结果 if (httpRequest("my.server.com", "/site/subsite/index.php")) { while (espSerial.available()) { Serial.write(espSerial.read() ); } }}void loop() { // 反复运行 if (espSerial.available()) { Serial.write(espSerial.read()); } if (Serial.available()) { espSerial.write(Serial.read()); }}bool connectToWiFi() { delay(2000;) espSerial.setTimeout(3000);而 (espSerial.available()) Serial.write(espSerial.read()); Serial.println(F("[ESP] 连接到 WiFi")); espSerial.println(F("AT+CIPSTATUS=2")); if (!espSerial.find("OK")) { espSerial.setTimeout(10000); Serial.println(F("[ESP] 重置模块")); espSerial.println(F("AT+RST")); if (!espSerial.find("ready")) { Serial.println(F("[ESP] 重置失败"));返回假; Serial.println(F("[ESP] 设置 CWMode")); espSerial.println(F("AT+CWMODE=1")); if (!espSerial.find("OK")) { Serial.println(F("[ESP] 模式失败"));返回假; Serial.println(F("[ESP] 连接路由器")); espSerial.print(F("AT+CWJAP=\"")); espSerial.print(ssid); espSerial.print(F("\",\"")); espSerial.print(pass); espSerial.println ("\""); if (!espSerial.find("OK")) { Serial.println(F("[ESP] WiFi 连接失败"));返回假; espSerial.setTimeout(3000); Serial.println(F("[ESP] WiFi 已连接")); return true;}bool httpRequest(String server, String site) { String cmd =""; cmd +="GET " + 站点 + " HTTP/1.0\r\n"; cmd +="主机:" + 服务器 + "\r\n"; cmd +="连接:关闭"; int cmdLength =cmd.length() + 4; // Serial.println(cmd); espSerial.print(F("AT+CIPSTART=\"TCP\",\"")); espSerial.print(server); espSerial.println(F("\",80")); if (!espSerial.find("OK")) { Serial.println(F("[ESP] TCP 连接错误"));返回假; espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] 发送状态错误"));返回假; } espSerial.print(F("GET ")); espSerial.print(网站); espSerial.print(F(" HTTP/1.0\r\n")); espSerial.print(F("主机:")); espSerial.print(服务器); espSerial.print(F("\r\n")); espSerial.print(F("连接:关闭\r\n")); espSerial.println(); if (!espSerial.find(":")) { Serial.println(F("Bytes not sent")); espSerial.print(F("AT+CIPCLOSE"));返回假; } 字符状态[32] ={0}; espSerial.readBytesUntil('\r', status, sizeof(status)); if (strcmp(status, "HTTP/1.1 200 OK") !=0) { Serial.print(F("[ESP] 意外响应:")); Serial.println(状态);返回假; } if (!espSerial.find("\r\n\r\n")) { Serial.println(F("[ESP] 无效响应"));返回假; } // 跳过 HTTP 头 // if (!espSerial.find(\r\n)) { Serial.println(F("[ESP] Bytes not found"));返回; } // 跳过字节(对于 http 1.1)返回 true;i} 

第四步:木箱

该框架计划存放超市的所有电子产品和三个药草罐。我测量了所有组件的尺寸并构建了位置。四个湿度传感器、两个泵、Arduino + 扩展板、一个 4x 继电器扩展板和一个 USB 插头以及一些电线需要装入盒子中。它由山毛榉木制成,使其坚固耐用,无需额外上釉。

在自制曲线锯台上用曲线锯锯出圆圈。植物支架用热胶粘在圆圈内。盒子的侧面用木胶(D3防水)粘合。除了电子,我没有在下面板固定旁边使用任何螺丝或钉子。

我把所有的电路、电线和水管放在盒子里,拉出传感器和额外水箱的管子。关闭盒子之前,我加了碟子,防止水淹在盒子里,保护电子设备。

第五步:网站 API

API 和网站基于 jQuery、Bootstrap、X-editable(用于内联 ajax 表单)和 Chart.js(用于湿度图表),用 php 编码。在网站上,您可以定义 Arduino 的设置(例如传感器引脚、湿度检查间隔、每株泵、泵 VCC 引脚、光 VCC 引脚)并找到当前湿度 + 图表。

配置由 JSON 提供给 Arduino。开始并在频繁的间隔后,药草框检查新设置。为了用 Arduino 解析 JSON,我使用了库 ArduinoJson。对于轮询间隔,我使用了 StensTimer。

库:ArduinoJson |图书馆:StensTimer

第六步:Alexa 集成

该网站提供了用于 Alexa 通信的 API。它用作接收 Alexa 请求 JSON 并将其转换为 Arduino 使用的自定义 JSON(例如,开灯、灌溉植物 1 等)的集线器。 Arduino 轮询新动作并执行它们。

因为语音请求不仅仅是开/关,所以我实施了 Alexa Skill 而没有 Alexa Smart Home。 AWS Lampda 将请求 JSON 转发到我的 API,后者解析意图。

var https =require('https');exports.handler =(event, context, callback) => { var postData =JSON.stringify(event); var options ={ host:'', path:'', port:443, method:'POST', headers:{ 'Content-Type':'application/json' , 'Content-Length':postData.length, } }; // 设置请求 var postRequest =https.request(options, function(res) { res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('Response:' + chunk); // console.log(chunk); callback(null, JSON.parse(chunk)); }); }); // 发布数据 postRequest.write(postData); postRequest.end();}; 

我的技能使用的意图的摘录:

  • ReadHumidityIntent 我的植物怎么样
  • ReadHumidityIntent 我的{plantName}怎么样
  • IrrigatePlantIntent 灌溉我的植物
  • IrrigatePlantIntent 灌溉我的 {plantName} {durationSeconds} 秒
  • SwitchIntent 开关灯{switchState}
  • ReadIrrigateIntent 哪些植物需要水
  • ReadLastIrrigationIntent 最后一次灌溉我的 {plantName} 是什么时候

最后但并非最不重要的一点是,我添加了对德语和英语使用的语言环境支持。

结果

因此,我确实有一个木箱可以将超市药草盆放入其中,将水管和土壤中的水分传感器以及外部水箱中的管子放入。通过 Alexa 集成,我可以说以下句子:

  • "Alexa,问药盒我的植物怎么样 ” - 回应:“植物 1 很好,植物 2 干燥,......”
  • "Alexa,告诉药草盒给我的罗勒浇水 5 秒 ” - 回应:“灌溉罗勒 5 秒”
  • "Alexa,询问草药盒哪些植物需要灌溉 ” - 回应:“植物 1 是干的,植物 3 是干的,......”
  • "Alexa,问草药盒最后一次灌溉是什么时候 我的罗勒 ” - 回应:“上次灌溉罗勒是在 36 小时前”
  • "Alexa,告诉 Herb box 打开灯 “ - 响应:“打开植物生长灯”

向 Alexa 询问我的植物的湿度并随后对其进行灌溉(德语):

要求 Alexa 打开植物生长灯:

没有视频的 GIF 显示结果:

计划功能

以下功能尚未实现但计划在未来实现:

  • Arduino 源代码的省电模式
  • 添加具有无线通信 (2,4 GHz) 的外部 Arduino Nanos,用于测量屋内其他植物的水分(盒子是 WiFi 的集线器) - 仅使用电池
  • 为多个药草盒实例扩展 API,为朋友(以及任何人,如果您感兴趣?!)
  • 在没有网站或Alexa的盒子上添加一个按钮来灌溉和开关灯
  • Alexa 图像(技能响应中的卡片)

23.03.2018 更新

我添加了两个新意图。其中之一对于仅记录湿度的外部 Adruino Nanos 的计划功能很重要。

  • 哪些植物是干的
  • 最后一次灌溉是什么时候

代码

  • EcoActionBuffer.h
  • EcoActionBuffer.cpp
  • Plant.cpp
  • Plant.h
  • WhiteWalnut.ino
  • WhiteWalnutApi.cpp
  • WhiteWalnutApi.h
EcoActionBuffer.hArduino
#ifndef ECOACTIONBUFFER_H#define ECOACTIONBUFFER_H#include "Arduino.h"#include "StensTimer.h"struct EcoActionBuffer :public IStensTimerListener { long entryNo;行动;内部引脚;持续时间长; void timerCallback(Timer* timer); void switchPin(int pin, bool value);无效的读取堆栈();无效过程(); void toSerial(); void reset();};#endif
EcoActionBuffer.cppArduino
#include "EcoActionBuffer.h"#include "StensTimer.h"#include "WhiteWalnutApi.h"#define ACTION_ECOACTION_READ 1#define ACTION_ECOACTION_HIGH 2#define ACTION_ECOACTION_LOW 3void EcoActionBuffer::readStack() { reset(); WhiteWalnutApi::receiveActionFromStack(*this); if (entryNo !=0) { process(); // WhiteWalnutApi::updateActionOnStack(*this); // 为性能而停用 }}void EcoActionBuffer::process() { toSerial(); pinMode(pin, 输出);数字写入(引脚,高); switch (action) { case ACTION_ECOACTION_HIGH:switchPin(pin, true);休息; case ACTION_ECOACTION_LOW:switchPin(pin, false);休息; } if (duration !=0) { StensTimer::getInstance()->setTimer(this, -pin, duration); }}void EcoActionBuffer::timerCallback(Timer* timer) { switch (timer->getAction()) { case ACTION_ECOACTION_READ:readStack();休息; } if (timer->getAction() <0) { switchPin(abs(timer->getAction()), false); }}void EcoActionBuffer::switchPin(int pin, bool value) { switch (value) { case true:digitalWrite(pin, LOW);休息;情况为假:digitalWrite(pin, HIGH);休息; } WhiteWalnutApi::switchPin(pin, value);}void EcoActionBuffer::reset() { entryNo =0;动作 =0;引脚 =0;持续时间 =0;}void EcoActionBuffer::toSerial() { Serial.print(entryNo); Serial.print(F(" - 动作:")); Serial.print(action); Serial.print(F(", Pin:")); Serial.print(pin); Serial.print(F(", Duration:")); Serial.print(持续时间); Serial.println();}
Plant.cppArduino
#include "Plant.h"#include "StensTimer.h"#include "WhiteWalnutApi.h"#define ACTION_PLANT_CHECKHUMIDITY 2#define PIN_HUMIDITY_VCC 12void Plant::checkHumidity() { if (hydrityDataPin !=0) { Serial.print (代码); Serial.print(F(" - 检查湿度..."));数字写入(PIN_HUMIDITY_VCC,高);延迟(200); // TODO int 湿度 =1023 - 模拟读取(湿度数据引脚);数字写入(PIN_HUMIDITY_VCC,低); Serial.println(湿度); WhiteWalnutApi::sendHumidity(*this, 湿度);如果(湿度检查间隔==0)湿度检查间隔=60000; StensTimer::getInstance()->setTimer(this, ACTION_PLANT_CHECKHUMIDITY,hydrationCheckInterval); } else StensTimer::getInstance()->setTimer(this, ACTION_PLANT_CHECKHUMIDITY, 60000);}void Plant::updateApi() { WhiteWalnutApi::updatePlant(*this); // WhiteWalnutApi::sendHeartbeat(*this); // 禁用性能 pinMode(PIN_HUMIDITY_VCC, OUTPUT); toSerial();}void Plant::timerCallback(Timer* timer) { switch (timer->getAction()) { case ACTION_PLANT_CHECKHUMIDITY:checkHumidity();休息; }}void Plant::toSerial() { Serial.print(code); Serial.print(F(" - DataPin:")); Serial.print(湿度数据Pin); Serial.print(F(", 间隔:"));串行打印(湿度检查间隔); Serial.println();}
Plant.hArduino
#ifndef PLANT_H#define PLANT_H#include "Arduino.h"#include "StensTimer.h"struct Plant :public IStensTimerListener { const char* code; int 湿度数据引脚;长湿度检查间隔;无效检查湿度(); void timerCallback(Timer* timer); void toSerial(); void updateApi();};#endif
WhiteWalnut.inoArduino
#include "EcoActionBuffer.h"#include "Plant.h"#include "StensTimer.h"#include "WhiteWalnutApi.h"struct TimerHelper :public IStensTimerListener { public:void updateApi(); void timerCallback(Timer* timer);};StensTimer* stensTimer;TimerHelper apiTimer;Plant leftPlant;Plant centerPlant;Plant rightPlant;Plant externalPlant;EcoActionBuffer actionBuffer;#define ACTION_PLANT_UPDATE 1#define ACTION_ECOACTION_READ 1void setup() { Serial.begin);而(!串行); stensTimer =StensTimer::getInstance(); leftPlant.code ="左"; centerPlant.code ="中心"; rightPlant.code ="正确"; externalPlant.code ="外部"; while(!WhiteWalnutApi::connectToWiFi()) delay(2000); WhiteWalnutApi::switchPin(0, false); apiTimer.updateApi(); leftPlant.checkHumidity(); centerPlant.checkHumidity(); rightPlant.checkHumidity(); externalPlant.checkHumidity(); actionBuffer.readStack(); StensTimer::getInstance()->setInterval(&apiTimer, ACTION_PLANT_UPDATE, 60000); StensTimer::getInstance()->setInterval(&actionBuffer, ACTION_ECOACTION_READ, 1000);}void loop() { stensTimer->run();}void TimerHelper::updateApi() { leftPlant.updateApi(); centerPlant.updateApi(); rightPlant.updateApi(); externalPlant.updateApi();}void TimerHelper::timerCallback(Timer* timer){ switch (timer->getAction()) { case ACTION_PLANT_UPDATE:updateApi();休息; }}
WhiteWalnutApi.cppArduino
你需要添加你的 WiFi 和 API 设置
#include "Arduino.h"#include "ArduinoJson.h"#include "EcoActionBuffer.h"#include "MemoryFree.h"#include "Plant.h"#include " SoftwareSerial.h"#include "WhiteWalnutApi.h"SoftwareSerial espSerial(3, 2);const char* ssid ="";const char* pass ="";const char* API_SERVER ="";const char* API_PLANT ="";const char* API_ACTION ="";char* findOK ="OK";char* findRY ="ready";char* findGT =">";char* findDP =":";char* findHD ="\r\n\r\n";char* findBT ="\r\n"; bool WhiteWalnutApi::connectToWiFi() { espSerial.begin(9600); espSerial.setTimeout(3000);而 (espSerial.available()) Serial.write(espSerial.read()); Serial.println(F("[ESP] 连接到 WiFi")); espSerial.println(F("AT+CIPSTATUS=2"));如果 (!espSerial.find(findOK)) { espSerial.setTimeout(10000); Serial.println(F("[ESP] 重置模块")); espSerial.println(F("AT+RST")); if (!espSerial.find(findRY)) { Serial.println(F("[ESP] 重置失败"));返回假; Serial.println(F("[ESP] 设置 CWMode")); espSerial.println(F("AT+CWMODE=1")); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] 模式失败"));返回假; Serial.println(F("[ESP] 连接路由器")); espSerial.print(F("AT+CWJAP=\"")); espSerial.print(ssid); espSerial.print(F("\",\"")); espSerial.print(pass); espSerial.println ("\""); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] WiFi 连接失败"));返回假; espSerial.setTimeout(3000); Serial.println(F("[ESP] WiFi 已连接")); return true;}void WhiteWalnutApi::updatePlant(Plant&plant) { String site =String(API_PLANT) + "?action=get&code=" + String(plant.code);而 (!httpRequest(site)) connectToWiFi(); JsonObject&root =parseJson(); if (root.success()) { plant.hydrityDataPin =root["dataPin"].as();植物湿度检查间隔 =atol(root["interval"].as()); }}void WhiteWalnutApi::sendHumidity(Plant&plant, int 湿度) { String site =String(API_PLANT) + "?action=hydrity&code=" + String(plant.code) + "&humidity=" + String(humity);而 (!httpRequest(site)) connectToWiFi(); // TODO:REMOVE RETURN}void WhiteWalnutApi::sendHeartbeat(Plant&plant) { String site =String(API_PLANT) + "?action=heartbeat&code=" + String(plant.code); while (!httpRequest(site)) connectToWiFi();}void WhiteWalnutApi::receiveActionFromStack(EcoActionBuffer&actionBuffer) { while (!httpRequest(String(API_ACTION))) connectToWiFi(); JsonObject&root =parseJson(); if (root.success()) { actionBuffer.entryNo =atol(root["entryNo"].as()); actionBuffer.action =root["actionEnum"].as(); actionBuffer.pin =root["pin"].as(); actionBuffer.duration =atol(root["value"].as()); }}void WhiteWalnutApi::updateActionOnStack(EcoActionBuffer&actionBuffer) { String site =String(API_ACTION) + "?action=processed&entryNo=" + String(actionBuffer.entryNo); while (!httpRequest(site)) connectToWiFi();}void WhiteWalnutApi::switchPin(int pin, bool value) { String site =String(API_ACTION) + "?action=switch&pin=" + String(pin) + "&value=" + 字符串(值); while (!httpRequest(site)) connectToWiFi();}bool WhiteWalnutApi::httpRequest(String site) { // char* cmd; // sprintf(cmd, "GET %s HTTP/1.0\r\nHost:%s\r\nConnection:close", site, API_SERVER); /* 字符串 cmd =""; cmd +="GET " + 站点 + " HTTP/1.0\r\n"; cmd +="主机:" + String(API_SERVER) + "\r\n"; cmd +="连接:关闭"; int cmdLength =cmd.length() + 4; Serial.println(cmd); */ int cmdLength =44 + site.length() + strlen(API_SERVER); // Serial.print(F("[MEMORY] ")); // Serial.print(freeMemory()); // Serial.print(F(" - ")); // Serial.println(站点); // -> 785 用于外部 espSerial.print(F("AT+CIPSTART=\"TCP\",\"")); espSerial.print(API_SERVER); espSerial.println(F("\",80") ); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] TCP 连接错误"));返回假; espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); // espSerial.println(strlen(cmd)); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] 发送状态错误"));返回假; } espSerial.print(F("GET ")); espSerial.print(网站); espSerial.print(F(" HTTP/1.0\r\n")); espSerial.print(F("Host:")); espSerial.print(API_SERVER); espSerial.print(F("\r\n")); espSerial.print(F("Connection:close\r\n")); espSerial.println(); // while (espSerial.available()) Serial.println(espSerial.readString());返回; if (!espSerial.find(findDP)) { Serial.println(F("Bytes not sent")); espSerial.print(F("AT+CIPCLOSE"));返回假; } char status[32] ={0}; espSerial.readBytesUntil('\r', status, sizeof(status)); if (strcmp(status, "HTTP/1.1 200 OK") !=0) { Serial.print(F("[ESP] Unexpected response:")); Serial.println(status);返回假; } // Check HTTP status if (!espSerial.find(findHD)) { Serial.println(F("[ESP] Invalid response"));返回假; } // Skip HTTP headers // if (!espSerial.find(findBT)) { Serial.println(F("[ESP] Bytes not found"));返回; } // skip bytes (for http 1.1) return true;}JsonObject&WhiteWalnutApi::parseJson() { const size_t capacity =JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60; DynamicJsonBuffer jsonBuffer(capacity); JsonObject&root =jsonBuffer.parseObject(espSerial); if (!root.success()) Serial.println(F("Parsing failed!")); return root;}
WhiteWalnutApi.hArduino
#ifndef WHITEWALNUTAPI_H#define WHITEWALNUTAPI_H#include "Arduino.h"#include "ArduinoJson.h"#include "EcoActionBuffer.h"#include "Plant.h"class WhiteWalnutApi { public:static bool connectToWiFi(); static void updatePlant(Plant&plant); static void sendHumidity(Plant&plant, int humidity); static void sendHeartbeat(Plant&plant); static void receiveActionFromStack(EcoActionBuffer&actionBuffer); static void updateActionOnStack(EcoActionBuffer&actionBuffer); static void switchPin(int pin, bool value); private:static bool httpRequest(String site); static JsonObject&parseJson();};#endif

示意图

Chart about the communication and interfaces All implemented intents you can ask Alexa, including the response.
(multilingual) If you are interested in the entrance step of your alexa json parsing.

制造工艺

  1. Web 操作的 DMX 控制器
  2. Arduino Spybot
  3. Arduino 报警系统:SERENA
  4. Arduino + ESP 气象箱
  5. 地下室/爬行空间通风系统
  6. 基于Arduino和谷歌电子表格的考勤系统
  7. BLUE_P:无线 Arduino 编程扩展板
  8. 基于Arduino的碰撞检测预警系统
  9. Arduino Nano 的 TFT 扩展板 - 开始
  10. Arduino Shield NCS314 NIXIE Tubes Clock IN-14
  11. Arduino GrowBox 控制器
  12. 基于 Arduino 的安全系统