Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Herb Box Eco System

Componentes y suministros

Amazon Alexa Echo Dot
× 1
Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Arduino Proto Shield
× 1
Arduino 4 Relys Shield
× 1
Bomba de agua
× 2
Lámpara de cultivo de plantas
× 1
Adaptador de corriente de 220 V CC
× 1
Adaptador de corriente de 12 V CC
× 1
Enchufe de alimentación USB + cable
× 1
Manguera de aire
× 1
Cables de puente (genéricos)
× 1

Aplicaciones y servicios en línea

Arduino IDE
Kit de habilidades de Alexa de Amazon Alexa
Amazon Web Services AWS Lambda
servidor web php

Acerca de este proyecto

Dado que mis plantas siempre sufren de demasiada o menos agua y me gusta poner muchas hierbas en mis platos, decidí crear un sistema de riego personalizado. La caja de mis hierbas debe ser configurable y funcionar de forma automática o manual. Por lo tanto, existe una interfaz para un sitio web para permitir una configuración y mostrar la humedad en un gráfico agradable. El último paso fue la integración del control por voz para pedirle humedad a Amazon Alexa, encender / apagar una lámpara de cultivo de plantas e iniciar el riego, si la automatización está desactivada. Haga clic aquí para encontrar el resultado.

Empecé con la parte técnica del proyecto y compré un Arduino. Después de algunos tutoriales, me mantuve firme con el software y controlando el Arduino. Pedí un controlador wifi, algunos sensores de humedad, bombas, una lámpara de cultivo de plantas y hardware adicional necesario (protector de relés para separar los circuitos de la lámpara y las bombas del Arduino, algunos cables y madera de haya para el marco). El código Arduino del resultado se proporciona en este tutorial, junto con información sobre cómo usar los componentes en sus proyectos. No se proporciona el código del sitio web / api (a menos que la demanda sea muy alta;)).

Paso uno:sensor de humedad

El primer hito fue leer la humedad con mi Arduino. El sensor de humedad YL-69 fue fácil de conectar con Arduino. Debe conectar el pin VCC a un pin GPIO (en mi ejemplo, pin 06), tierra a tierra y el A0 a un pin analógico (en mi ejemplo, pin A1) del Arduino.

Tutorial:Sensor de humedad del suelo

  byte vccPin =6; byte dataPin =A1; void setup () {pinMode (vccPin, OUTPUT); digitalWrite (vccPin, BAJO); Serial.begin (9600); while (! Serial);} int readHumidity () {digitalWrite (vccPin, HIGH); retraso (500); // necesita probar cuánto tiempo pre-power antes de la medición int value =analogRead (dataPin); digitalWrite (vccPin, BAJO); return 1023 - value;} void loop () {Serial.print ("HumidityLevel (0-1023):"); Serial.println (readHumidity ()); retraso (10000);}  

Paso dos:relé para bombas y lámpara

El siguiente objetivo fue instalar un protector de relé (4 relés) para separar los circuitos de la lámpara, bombas y Arduino. El Arduino funciona con 5V, las bombas usan 12V y la lámpara de cultivo de plantas 230V. El escudo debe estar conectado a los pines de 5V y tierra en el Arduino. Además, cada relé necesita un pin GPIO de su elección para encender y apagar. Por último, puede usar un puente para VCC JC a VCC en el escudo, o usar una batería adicional (lo que sería mejor, pero todavía no tengo ninguna batería dentro de mi proyecto).

Es importante entender que mi escudo se enciende con "LOW" en el pin. Tan pronto como mi pin se define como SALIDA, cambia automáticamente a activo. En el código, siempre debe cambiar a INPUT y LOW, si desea que el relé esté apagado. Por defecto, los pines de Arduino son ENTRADA y BAJA.

Tutorial:Relay Shield

Información:¿Por qué relé SALIDA + BAJA =Activa?

  byte pump1 =11; byte pump2 =10; void setup () {Serial.begin (9600); mientras (! Serial); pinMode (bomba1, SALIDA); // variante baja / alta digitalWrite (bomba2, BAJA); // entrada / salida variante} void loop () {digitalWrite (pump1, HIGH); // bomba1 desactivado pinMode (bomba2, ENTRADA); // retardo desactivado de la bomba2 (1000); digitalWrite (bomba1, BAJA); // bomba1 activado pinMode (bomba2, SALIDA); // retardo activado de la bomba2 (1000);}  

Paso tres:WiFi con ESP-01

Conectar el espressif ESP8266 ESP-01 al Arduino para WiFi fue la parte más difícil. Me tomó horas hacer que el wifi se ejecutara en mi secuencia de comandos.

El ESP está conectado a:VCC =3.3V, GND =GND, CH_PD =3.3V, TX =Pin 02, RX =Pin 03. Para un uso productivo, debe usar al menos un convertidor de nivel de 5V a 3.3V para el pin 02 y el pin 03 también. En mi caso, funcionó bien.

Similar al Arduino, el ESP-01 es otro microcontrolador. Si desea que ambos controladores se comuniquen, debe utilizar la comunicación en serie. El Arduino UNO usa por defecto los pines 01 y 02 para RX y TX. Pero también se utilizan para la depuración de USB y, por lo tanto, se sugiere incluir SoftwareSerial.hy definir pines personalizados.

  #include  SoftwareSerial espSerial (3,2); // RX, TXvoid setup () {Serial.begin (9600); espSerial.begin (115200); // cambia a 9600 después de AT + UART_DEF =9600,8,1,0,0 while (! Serial);} void loop () {if (espSerial.available ()) {Serial.write (espSerial.read ()); } if (Serial.available ()) {espSerial.write (Serial.read ()); }}  

Al ejecutar el script anterior, puede ingresar comandos AT en el monitor en serie y ver los resultados. La comunicación en serie es propensa a fallas, por lo tanto, disminuí la velocidad en baudios de comunicación utilizada por el ESP de 115200 a 9600.

Tutorial:ESP8266 + Arduino | Tutorial:ESP8266 general (alemán)

  • Una clase auxiliar útil (pero usó demasiada memoria):Biblioteca:WiFiEsp
  • Herramienta de verificación de memoria:Biblioteca:MemoryFree

El script usa HTTP 1.0, porque con HTTP 1.1 los bytes son parte de la respuesta. Es importante tener cuidado con los saltos de línea para que el comando se envíe después de AT + CIPSEND. Si están equivocados, recibirá un error de envío de bytes.

  #include  SoftwareSerial espSerial (3,2); // RX, TXconst char * ssid =""; const char * pass =""; void setup () {Serial.begin (9600); espSerial.begin (9600); mientras (! Serial); mientras (! connectToWiFi ()); // solicita el sitio web e imprime el resultado if (httpRequest ("my.server.com", "/site/subsite/index.php")) {while (espSerial.available ()) {Serial.write (espSerial.read () ); }}} void loop () {// ejecutar una y otra vez if (espSerial.available ()) {Serial.write (espSerial.read ()); } if (Serial.available ()) {espSerial.write (Serial.read ()); }} bool connectToWiFi () {retraso (2000;) espSerial.setTimeout (3000); while (espSerial.available ()) Serial.write (espSerial.read ()); Serial.println (F ("[ESP] Conectando a WiFi")); espSerial.println (F ("AT + CIPSTATUS =2")); if (! espSerial.find ("OK")) {espSerial.setTimeout (10000); Serial.println (F ("[ESP] Reset Module")); espSerial.println (F ("AT + RST")); if (! espSerial.find ("listo")) {Serial.println (F ("[ESP] Falló el reinicio")); falso retorno; } Serial.println (F ("[ESP] Establecer CWMode")); espSerial.println (F ("AT + CWMODE =1")); if (! espSerial.find ("OK")) {Serial.println (F ("Falló el modo [ESP]")); falso retorno; } Serial.println (F ("[ESP] Conectarse al enrutador")); espSerial.print (F ("AT + CWJAP =\" ")); espSerial.print (ssid); espSerial.print (F (" \ ", \" ")); espSerial.print (pasar); espSerial.println ("\" "); if (! espSerial.find ("OK")) {Serial.println (F ("[ESP] Error en la conexión WiFi")); falso retorno; }} espSerial.setTimeout (3000); Serial.println (F ("[ESP] WiFi está conectado")); return true;} bool httpRequest (servidor de cadenas, sitio de cadenas) {String cmd =""; cmd + ="OBTENER" + sitio + "HTTP / 1.0 \ r \ n"; cmd + ="Host:" + servidor + "\ r \ n"; cmd + ="Conexión:cerrar"; int cmdLength =cmd.length () + 4; // Serial.println (cmd); espSerial.print (F ("AT + CIPSTART =\" TCP \ ", \" ")); espSerial.print (servidor); espSerial.println (F (" \ ", 80")); if (! espSerial.find ("OK")) {Serial.println (F ("[ESP] Error de conexión TCP")); falso retorno; } espSerial.print (F ("AT + CIPSEND =")); espSerial.println (cmdLength); if (! espSerial.find (findGT)) {Serial.println (F ("[ESP] Error de estado de envío")); falso retorno; } espSerial.print (F ("OBTENER")); espSerial.print (sitio); espSerial.print (F ("HTTP / 1.0 \ r \ n")); espSerial.print (F ("Host:")); espSerial.print (servidor); espSerial.print (F ("\ r \ n")); espSerial.print (F ("Conexión:cerrar \ r \ n")); espSerial.println (); if (! espSerial.find (":")) {Serial.println (F ("Bytes no enviados")); espSerial.print (F ("AT + CIPCLOSE")); falso retorno; } estado de caracteres [32] ={0}; espSerial.readBytesUntil ('\ r', estado, tamaño de (estado)); if (strcmp (status, "HTTP / 1.1 200 OK")! =0) {Serial.print (F ("[ESP] Respuesta inesperada:")); Serial.println (estado); falso retorno; } if (! espSerial.find ("\ r \ n \ r \ n")) {Serial.println (F ("[ESP] Respuesta inválida")); falso retorno; } // Omitir encabezados HTTP // if (! EspSerial.find (\ r \ n)) {Serial.println (F ("[ESP] Bytes no encontrados")); regreso; } // omitir bytes (para http 1.1) devolver verdadero; i}  

Paso cuatro:la caja de madera

El marco fue planeado para almacenar todos los dispositivos electrónicos y tres botes de hierbas del supermercado. Medí los tamaños de todos los componentes y estructuré las posiciones. Cuatro sensores de humedad, dos bombas, el protector Arduino +, un protector de relé 4x y un enchufe USB y algunos cables deben caber en la caja. Estaba hecho de madera de haya, para que fuera resistente y durara las gotas de agua sin esmaltes adicionales.

Los círculos se cortaron con una sierra caladora en una mesa de sierra caladora hecha por uno mismo. Los soportes para plantas se pegan dentro de los círculos con pegamento termofusible. Los lados de la caja están pegados con cola para madera (D3 para resistencia al agua). Además del electrónico, no utilicé tornillos ni clavos al lado de la fijación del panel inferior.

Puse todos los circuitos, cables y tubos de agua dentro de la caja, saqué los sensores y los tubos para el tanque de agua adicional. Antes de cerrar la caja, agregué platillos para evitar que el agua se ahogara dentro de la caja para proteger la electrónica.

Paso cinco:la API del sitio web

La API y el sitio web se basan en jQuery, Bootstrap, X-editable (para formularios ajax en línea) y Chart.js (para la tabla de humedad), codificados en php. En el sitio web puede definir la configuración del Arduino (p. Ej., Pines de sensor, intervalo de verificación de humedad, bombas por planta, pines VCC de bomba, pin VCC de luz) y encontrar la tabla de humedad + actual.

JSON proporciona la configuración para Arduino. Después de comenzar y en un intervalo frecuente, la caja de hierbas verifica si hay nuevos ajustes. Para analizar JSON con Arduino, utilicé la biblioteca ArduinoJson. Para el intervalo de sondeo utilicé StensTimer.

Biblioteca:ArduinoJson | Biblioteca:StensTimer

Paso seis:integración de Alexa

El sitio web proporciona una API para la comunicación de Alexa. Sirve como un centro para recibir la solicitud JSON de Alexa y la traduce a un JSON personalizado utilizado por Arduino (por ejemplo, lámpara encendida, irrigar la planta 1, ...). Arduino sondea en busca de nuevas acciones y las ejecuta.

Debido a que las solicitudes de voz son más que solo activadas / desactivadas, implementé una habilidad de Alexa y no una casa inteligente de Alexa. AWS Lampda reenvía la solicitud JSON a mi API, que analiza los intents.

  var https =require ('https'); export.handler =(evento, contexto, devolución de llamada) => {var postData =JSON.stringify (evento); var options ={host:'', ruta:'', puerto:443, método:'POST', encabezados:{'Content-Type':'application / json' , 'Content-Length':postData.length,}}; // configura la solicitud var postRequest =https.request (options, function (res) {res.setEncoding ('utf8'); res.on ('data', function (chunk) {console.log ('Response:' + fragmento); // console.log (fragmento); devolución de llamada (nulo, JSON.parse (fragmento));});}); // publicar los datos postRequest.write (postData); postRequest.end ();};  

Un extracto de las intenciones que usé para mi habilidad:

  • ReadHumidityIntent ¿Cómo están mis plantas?
  • ReadHumidityIntent ¿Cómo está mi {plantName}
  • IrrigatePlantIntent Irrigar mis plantas
  • IrrigatePlantIntent Irrigar mi {plantName} durante {durationSeconds} segundos
  • SwitchIntent Cambia la lámpara {switchState}
  • ReadIrrigateIntent Qué plantas necesitan agua
  • ReadLastIrrigationIntent ¿Cuándo fue el último riego de mi {plantName}

Por último, pero no menos importante, agregué soporte local para el uso en alemán e inglés.

El resultado

Como resultado, tengo una caja de madera para colocar macetas de hierbas del supermercado, llevar tubos de agua y sensores de humedad en el suelo y los tubos en un tanque de agua externo. Con la integración de Alexa, puedo decir las siguientes oraciones:

  • " Alexa, pregúntale a Herbert Box cómo están mis plantas "- Respuesta:" La planta 1 está bien, la planta 2 está seca, ... "
  • " Alexa, dile a la caja de hierbas que riegue mi albahaca durante 5 segundos "- Respuesta:" Regar albahaca durante 5 segundos "
  • " Alexa, pregúntale a la caja de hierbas qué plantas necesitan riego. "- Respuesta:" La planta 1 está seca, la planta 3 está seca, ... "
  • " Alexa, pregunta a la caja de hierbas cuándo fue el último riego de mi albahaca "- Respuesta:" El último riego de albahaca fue hace 36 horas "
  • " Alexa, dile a Herb Box que encienda la lámpara "- Respuesta:" Encendido de la lámpara de cultivo de plantas "

Pedirle a Alexa la humedad de mi planta y luego regarla (alemán):

Pidiéndole a Alexa que encienda la lámpara de cultivo de plantas:

GIF que muestran el resultado sin los videos:

Funciones planificadas

Las siguientes funciones aún no están implementadas, pero están previstas para el futuro:

  • Modo de ahorro de energía para el código fuente de Arduino
  • Agregue Nanos Arduino externos con comunicación inalámbrica (2,4 GHz) para medir la humedad de otras plantas en la casa (la caja es el concentrador para WiFi), usando solo baterías
  • Amplíe la API para varias instancias de la caja de hierbas, para amigos (¡y para quien sea, si está interesado!)
  • Agregue un botón para regar y encender la lámpara en la caja sin sitio web o Alexa
  • Imágenes de Alexa (tarjeta en respuesta a la habilidad)

Actualización 23.03.2018

He agregado dos nuevas intenciones. Uno de ellos es importante para la función planificada de Adruino Nanos externos que solo registran la humedad.

  • Qué plantas están secas
  • ¿Cuándo fue el último riego?

Código

  • EcoActionBuffer.h
  • EcoActionBuffer.cpp
  • Plant.cpp
  • Plant.h
  • WhiteWalnut.ino
  • WhiteWalnutApi.cpp
  • WhiteWalnutApi.h
EcoActionBuffer.h Arduino
 #ifndef ECOACTIONBUFFER_H # define ECOACTIONBUFFER_H # incluye "Arduino.h" #include "StensTimer.h" struct EcoActionBuffer:public IStensTimerListener {entrada largaNo; int action; int pin; Larga duración; void timerCallback (Temporizador * temporizador); void switchPin (pin int, valor bool); void readStack (); proceso nulo (); void toSerial (); void reset ();}; # endif 
EcoActionBuffer.cpp Arduino
 #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) ::{resetStack; WhiteWalnutApi ::receiveActionFromStack (* esto); if (entryNo! =0) {process (); // WhiteWalnutApi ::updateActionOnStack (* esto); // desactivado para el rendimiento}} void EcoActionBuffer ::process () {toSerial (); pinMode (pin, SALIDA); digitalWrite (pin, ALTO); switch (acción) {case ACTION_ECOACTION_HIGH:switchPin (pin, verdadero); descanso; case ACTION_ECOACTION_LOW:switchPin (pin, falso); descanso; } if (duración! =0) {StensTimer ::getInstance () -> setTimer (este, -pin, duración); }} void EcoActionBuffer ::timerCallback (Timer * timer) {switch (timer-> getAction ()) {case ACTION_ECOACTION_READ:readStack (); descanso; } if (temporizador-> getAction () <0) {switchPin (abs (temporizador-> getAction ()), falso); }} void EcoActionBuffer ::switchPin (pin int, valor bool) {switch (valor) {caso verdadero:digitalWrite (pin, LOW); descanso; caso falso:digitalWrite (pin, HIGH); descanso; } WhiteWalnutApi ::switchPin (pin, valor);} void EcoActionBuffer ::reset () {entryNo =0; acción =0; pin =0; duración =0;} void EcoActionBuffer ::toSerial () {Serial.print (entryNo); Serial.print (F ("- Acción:")); Serial.print (acción); Serial.print (F (", Pin:")); Serial.print (pin); Serial.print (F (", Duración:")); Serial.print (duración); Serial.println ();} 
Plant.cpp Arduino
 #include "Plant.h" #include "StensTimer.h" #include "WhiteWalnutApi.h" #define ACTION_PLANT_CHECKHUMIDITY 2 # define PIN_HUMIDITY_VCC 12void Plant ::checkHumidity () {if (TemperatureDataPin! =0) {Serial.print (código); Serial.print (F ("- Verificar humedad ...")); digitalWrite (PIN_HUMIDITY_VCC, HIGH); retraso (200); // TODO int humedad =1023 - analogRead (humedadDataPin); digitalWrite (PIN_HUMIDITY_VCC, BAJO); Serial.println (humedad); WhiteWalnutApi ::sendHumidity (* esto, humedad); if (intervalo de verificación de humedad ==0) intervalo de verificación de humedad =60000; StensTimer ::getInstance () -> setTimer (esto, ACTION_PLANT_CHECKHUMIDITY, humedadCheckInterval); } else StensTimer ::getInstance () -> setTimer (esto, ACTION_PLANT_CHECKHUMIDITY, 60000);} void Plant ::updateApi () {WhiteWalnutApi ::updatePlant (* esto); // WhiteWalnutApi ::sendHeartbeat (* esto); // desactivado para rendimiento pinMode (PIN_HUMIDITY_VCC, OUTPUT); toSerial ();} void Plant ::timerCallback (Timer * timer) {switch (timer-> getAction ()) {case ACTION_PLANT_CHECKHUMIDITY:checkHumidity (); descanso; }} void Plant ::toSerial () {Serial.print (código); Serial.print (F ("- DataPin:")); Serial.print (humedadDataPin); Serial.print (F (", Intervalo:")); Serial.print (humedadCheckInterval); Serial.println ();} 
Plant.h Arduino
 #ifndef PLANT_H # define PLANT_H # include "Arduino.h" #include "StensTimer.h" struct Plant:public IStensTimerListener {const char * code; int TemperatureDataPin; longidityCheckInterval; void checkHumidity (); void timerCallback (Temporizador * temporizador); void toSerial (); void updateApi ();}; # endif 
WhiteWalnut.ino Arduino
 #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_begin_READ); mientras (! Serial); stensTimer =StensTimer ::getInstance (); leftPlant.code ="IZQUIERDA"; centerPlant.code ="CENTRO"; rightPlant.code ="DERECHA"; externalPlant.code ="EXTERNAL"; while (! WhiteWalnutApi ::connectToWiFi ()) retraso (2000); WhiteWalnutApi ::switchPin (0, falso); 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 (); descanso; }} 
WhiteWalnutApi.cpp Arduino
necesita agregar su configuración de WiFi y 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 ="listo"; char * findGT =">"; char * findDP =":"; char * findHD ="\ r \ n \ r \ n"; char * findBT ="\ r \ n"; bool WhiteWalnutApi ::connectToWiFi () {espSerial.begin (9600); espSerial.setTimeout (3000); while (espSerial.available ()) Serial.write (espSerial.read ()); Serial.println (F ("[ESP] Conectando a WiFi")); espSerial.println (F ("AT + CIPSTATUS =2")); if (! espSerial.find (findOK)) {espSerial.setTimeout (10000); Serial.println (F ("[ESP] Reset Module")); espSerial.println (F ("AT + RST")); if (! espSerial.find (findRY)) {Serial.println (F ("[ESP] Restablecimiento fallido")); falso retorno; } Serial.println (F ("[ESP] Establecer CWMode")); espSerial.println (F ("AT + CWMODE =1")); if (! espSerial.find (findOK)) {Serial.println (F ("Falló el modo [ESP]")); falso retorno; } Serial.println (F ("[ESP] Conectarse al enrutador")); espSerial.print (F ("AT + CWJAP =\" ")); espSerial.print (ssid); espSerial.print (F (" \ ", \" ")); espSerial.print (pasar); espSerial.println ("\" "); if (! espSerial.find (findOK)) {Serial.println (F ("[ESP] Error en la conexión WiFi")); falso retorno; }} espSerial.setTimeout (3000); Serial.println (F ("[ESP] WiFi está conectado")); return true;} void WhiteWalnutApi ::updatePlant (Planta y planta) {String site =String (API_PLANT) + "? action =get &code =" + String (plant.code); while (! httpRequest (sitio)) connectToWiFi (); JsonObject &root =parseJson (); if (root.success ()) {plant.humidityDataPin =root ["dataPin"]. as  (); plant.humidityCheckInterval =atol (root ["intervalo"]. as  ()); }} void WhiteWalnutApi ::sendHumidity (Planta y planta, humedad int) {String site =String (API_PLANT) + "? action =humedad y código =" + String (código de planta) + "&humedad =" + String (humedad); while (! httpRequest (sitio)) connectToWiFi (); // TODO:ELIMINAR RETORNO} void WhiteWalnutApi ::sendHeartbeat (Planta y planta) {String site =String (API_PLANT) + "? Action =heartbeat &code =" + String (plant.code); while (! httpRequest (sitio)) 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 ["valor"]. as  ()); }} void WhiteWalnutApi ::updateActionOnStack (EcoActionBuffer &actionBuffer) {String site =String (API_ACTION) + "? action =procesado &entryNo =" + String (actionBuffer.entryNo); while (! httpRequest (sitio)) connectToWiFi ();} void WhiteWalnutApi ::switchPin (int pin, bool value) {String site =String (API_ACTION) + "? action =switch &pin =" + String (pin) + "&value ="+ Cadena (valor); while (! httpRequest (sitio)) connectToWiFi ();} bool WhiteWalnutApi ::httpRequest (String sitio) {// char * cmd; // sprintf (cmd, "OBTENER% s HTTP / 1.0 \ r \ nHost:% s \ r \ nConexión:cerrar", sitio, SERVIDOR_API); / * Cadena cmd =""; cmd + ="OBTENER" + sitio + "HTTP / 1.0 \ r \ n"; cmd + ="Host:" + String (API_SERVER) + "\ r \ n"; cmd + ="Conexión:cerrar"; int cmdLength =cmd.length () + 4; Serial.println (cmd); * / int cmdLength =44 + site.length () + strlen (API_SERVER); // Serial.print (F ("[MEMORIA]")); // Serial.print (freeMemory ()); // Serial.print (F ("-")); // Serial.println (sitio); // -> 785 para espSerial.print externo (F ("AT + CIPSTART =\" TCP \ ", \" ")); espSerial.print (API_SERVER); espSerial.println (F (" \ ", 80") ); if (! espSerial.find (findOK)) {Serial.println (F ("[ESP] Error de conexión TCP")); falso retorno; } espSerial.print (F ("AT + CIPSEND =")); espSerial.println (cmdLength); // espSerial.println (strlen (cmd)); if (! espSerial.find (findGT)) {Serial.println (F ("[ESP] Error de estado de envío")); falso retorno; } espSerial.print (F ("OBTENER")); espSerial.print (sitio); 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()); regreso; if (!espSerial.find(findDP)) { Serial.println(F("Bytes not sent")); espSerial.print(F("AT+CIPCLOSE")); falso retorno; } 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); falso retorno; } // Check HTTP status if (!espSerial.find(findHD)) { Serial.println(F("[ESP] Invalid response")); falso retorno; } // Skip HTTP headers // if (!espSerial.find(findBT)) { Serial.println(F("[ESP] Bytes not found")); regreso; } // 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

Esquemas

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.

Proceso de manufactura

  1. Controlador DMX operado por la web
  2. Arduino Spybot
  3. Sistema de alarma Arduino:SERENA
  4. Arduino + ESP Weather Box
  5. Sistema de ventilación del sótano / espacio de acceso
  6. Sistema de asistencia basado en Arduino y hoja de cálculo de Google
  7. BLUE_P:Escudo de programación inalámbrico Arduino
  8. Sistema de advertencia de detección de colisiones basado en Arduino
  9. TFT Shield para Arduino Nano - Iniciar
  10. Arduino Shield NCS314 Reloj de tubos NIXIE IN-14
  11. Controlador Arduino GrowBox