Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Herb Box Eco-systeem

Componenten en benodigdheden

Amazon Alexa Echo Dot
× 1
Arduino UNO
× 1
Espressief ESP8266 ESP-01
× 1
Arduino Proto Shield
× 1
Arduino 4 relaisschild
× 1
Aquapomp
× 2
Plantgroeilamp
× 1
220V DC-lichtnetadapter
× 1
12V DC-lichtnetadapter
× 1
USB-stekker + kabel
× 1
Luchtslang
× 1
Jumperdraden (algemeen)
× 1

Apps en online services

Arduino IDE
Amazon Alexa Alexa Skills Kit
Amazon Web Services AWS Lambda
php-webserver

Over dit project

Omdat mijn planten altijd last hebben van te veel of te weinig water en ik graag veel kruiden in mijn gerechten doe, heb ik besloten om een ​​irrigatiesysteem op maat te maken. De box voor mijn kruiden moet configureerbaar zijn en automatisch of handmatig werken. Daarom bestaat er een interface naar een website om een ​​setup mogelijk te maken en de luchtvochtigheid in een mooie grafiek weer te geven. De laatste stap was de integratie van spraakbesturing om Amazon Alexa om vochtigheid te vragen, een plantengroeilamp aan/uit te zetten en de irrigatie te starten als de automatisering is gedeactiveerd. Klik hier voor het resultaat.

Ik begon met het technische deel van het project en kocht een Arduino. Na wat tutorials was ik stevig met de software en het besturen van de Arduino. Ik bestelde een wifi-controller, enkele vochtsensoren, pompen, een plantengroeilamp en extra benodigde hardware (relais-schild om de circuits voor de lamp en pompen van de Arduino te scheiden, wat draden en beukenhout voor het frame). De Arduino-code van het resultaat wordt in deze tutorial gegeven, naast wat informatie over het gebruik van de componenten in uw projecten. De website/api-code wordt niet verstrekt (tenzij de vraag erg hoog is;) ).

Stap één:vochtsensor

De eerste mijlpaal was het aflezen van de luchtvochtigheid met mijn Arduino. De vochtsensor YL-69 was eenvoudig te koppelen met de Arduino. Je moet de VCC-pin verbinden met een GPIO-pin (in mijn voorbeeld pin 06), aarde naar aarde en de A0 naar een analoge pin (in mijn voorbeeld pin A1) van de Arduino.

Tutorial:Bodemvochtigheidssensor

byte vccPin =6;byte dataPin =A1;void setup() { pinMode(vccPin, OUTPUT); digitalWrite(vccPin, LAAG); Serieel.begin(9600); while (!Serial);}int readHumidity() {digitalWrite(vccPin, HIGH); vertraging (500); // je moet testen hoe lang je pre-power voor de meting int value =analogRead(dataPin); digitalWrite(vccPin, LAAG); return 1023 - value;}void loop() { Serial.print("Vochtigheidsniveau (0-1023):"); Serial.println(readVochtigheid()); vertraging (10000);} 

Stap twee:relais voor pompen en lamp

Het volgende doel was om een ​​relaisscherm (4 relais) te installeren voor het scheiden van de circuits van de lamp, pompen en Arduino. De Arduino werkt op 5V, de pompen op 12V en de plantengroeilamp op 230V. Het schild moet worden aangesloten op de 5V- en Ground-pinnen op de Arduino. Elk relais heeft verder een GPIO-pin naar keuze nodig om in en uit te schakelen. Ten slotte kun je een jumper gebruiken voor VCC JC naar VCC op het schild, of een extra batterij gebruiken (wat het beste zou zijn, maar ik heb nog geen batterij in mijn project).

Het is belangrijk om te begrijpen, dat mijn schild "Aan" schakelt met "LAAG" op de pin. Zodra mijn pin is gedefinieerd als OUTPUT, wordt deze automatisch overgeschakeld naar actief. In de code moet je altijd overschakelen naar INPUT en LOW, als je wilt dat het relais uit is. Standaard zijn de Arduino-pinnen INPUT en LOW.

Zelfstudie:relaisscherm

Informatie:Waarom relais OUTPUT + LOW =Actief?

byte pump1 =11;byte pump2 =10;void setup() { Serial.begin(9600); terwijl (!Serial); pinMode (pomp1, UITGANG); // variant laag/hoog digitalWrite(pump2, LOW); // variant input/output}void loop() {digitalWrite(pump1, HIGH); // pump1 gedeactiveerd pinMode (pomp2, INPUT); // pump2 gedeactiveerde vertraging (1000); digitalWrite(pomp1, LAAG); // pump1 geactiveerde pinMode (pomp2, OUTPUT); // pump2 geactiveerde vertraging (1000);} 

Stap drie:WiFi met ESP-01

Het verbinden van de espressif ESP8266 ESP-01 met de Arduino voor WiFi was het moeilijkste deel. Het kostte me uren om de wifi in mijn script aan de praat te krijgen.

De ESP is aangesloten op:VCC =3.3V, GND =GND, CH_PD =3.3V, TX =Pin 02, RX =Pin 03. Voor productief gebruik dient u voor de pin minimaal een level converter van 5V naar 3.3V te gebruiken 02 en pin 03 ook. In mijn geval werkte het prima.

Net als de Arduino is de ESP-01 een andere microcontroller. Als u wilt dat beide controllers communiceren, moet u seriële communicatie gebruiken. De Arduino UNO gebruikt standaard de pinnen 01 en 02 voor RX en TX. Maar ze worden ook gebruikt voor USB-foutopsporing en daarom wordt aangeraden om SoftwareSerial.h op te nemen en aangepaste pinnen te definiëren.

#include SoftwareSerial espSerial(3,2); // RX, TXvoid setup () {Serial.begin (9600); espSerial.begin(115200); // schakel over naar 9600 na 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()); }} 

Als u het bovenstaande script uitvoert, kunt u AT-commando's invoeren in de seriële monitor en de resultaten bekijken. Seriële communicatie is gevoelig voor storingen, daarom heb ik de communicatie-baudrate die door de ESP wordt gebruikt verlaagd van 115200 naar 9600.

Zelfstudie:ESP8266 + Arduino | Tutorial:Algemeen ESP8266 (duits)

  • Een nuttige hulpklasse (maar gebruikte te veel geheugen):Bibliotheek:WiFiEsp
  • Geheugencontroletool:Bibliotheek:Geheugenvrij

Het script maakt gebruik van HTTP 1.0, omdat bij HTTP 1.1 de bytes deel uitmaken van het antwoord. Het is belangrijk om te letten op de regeleinden voor het commando dat na AT+CIPSEND moet worden verzonden. Als ze fout zijn, ontvang je een byte-verzendfout.

#include SoftwareSerial espSerial(3,2); // RX, TXconst char* ssid ="";const char* pass ="";void setup() {Serial.begin(9600); espSerial.begin(9600); while(!Serial); while(!connectToWiFi()); // vraag website aan en print resultaat indien (httpRequest("my.server.com", "/site/subsite/index.php")) { while (espSerial.available()) { Serial.write(espSerial.read() ); } }}void loop() { // herhaal en herhaal if (espSerial.available()) { Serial.write(espSerial.read()); } if (Serial.available()) { espSerial.write(Serial.read()); }}bool connectToWiFi() { delay(2000;) espSerial.setTimeout(3000); while (espSerial.available()) Serial.write(espSerial.read()); Serial.println(F("[ESP] Verbinding maken met 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("ready")) { Serial.println(F("[ESP] Reset mislukt")); onwaar retourneren; } Serial.println(F("[ESP] CWMode instellen")); espSerial.println(F("AT+CWMODE=1")); if (!espSerial.find("OK")) { Serial.println(F("[ESP]-modus is mislukt")); onwaar retourneren; } Serial.println(F("[ESP] verbinding maken met router")); 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-verbinding mislukt")); onwaar retourneren; } } espSerial.setTimeout(3000); Serial.println(F ("[ESP] WiFi is verbonden")); return true;}bool httpRequest(String-server, String-site) { String cmd =""; cmd +="GET " + site + " HTTP/1.0\r\n"; cmd +="Host:" + server + "\r\n"; cmd +="Verbinding:sluiten"; int cmdLength =cmd.length() + 4; // Serieel.println(cmd); espSerial.print(F("AT+CIPSTART=\"TCP\",\"")); espSerial.print(server); espSerial.println(F("\",80")); if (!espSerial.find("OK")) { Serial.println(F("[ESP] TCP-verbindingsfout")); onwaar retourneren; } espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] Send State Error")); onwaar retourneren; } espSerial.print(F("GET")); espSerial.print(site); espSerial.print(F(" HTTP/1.0\r\n")); espSerial.print(F("Host:")); espSerial.print(server); espSerial.print(F("\r\n")); espSerial.print(F("Verbinding:sluiten\r\n")); espSerial.println(); if (!espSerial.find(":")) { Serial.println(F("Bytes niet verzonden")); espSerial.print(F("AT+CIPCLOSE")); onwaar retourneren; } tekenstatus[32] ={0}; espSerial.readBytesUntil('\r', status, sizeof(status)); if (strcmp(status, "HTTP/1.1 200 OK") !=0) { Serial.print(F("[ESP] Onverwachte reactie:")); Serieel.println(status); onwaar retourneren; } if (!espSerial.find("\r\n\r\n")) { Serial.println(F("[ESP] Ongeldige reactie")); onwaar retourneren; } // HTTP-headers overslaan // if (!espSerial.find(\r\n)) { Serial.println(F("[ESP] Bytes niet gevonden")); opbrengst; } // skip bytes (voor http 1.1) return true;i} 

Stap vier:de houten kist

Het frame was bedoeld om alle elektronica in op te bergen en drie kruidenpotten uit de supermarkt. Ik heb de afmetingen van alle componenten gemeten en de posities gestructureerd. Vier vochtsensoren, twee pompen, het Arduino + schild, een 4x relaisschild en een USB-stekker en er moeten wat draden in de doos passen. Het is gemaakt van beukenhout, om het sterk te maken en waterdruppels te laten zonder extra glazuur.

De cirkels zijn uitgezaagd met decoupeerzaag op een zelfgemaakte decoupeerzaagtafel. De plantensteunen worden met hete lijm in de cirkels gelijmd. De zijkanten van de doos zijn verlijmd met houtlijm (D3 voor waterbestendigheid). Naast de elektronische heb ik geen schroeven of spijkers gebruikt naast de bevestiging van het onderste paneel.

Ik stopte alle circuits, draden en waterslangen in de doos, trok de sensoren eruit en de slangen voor de extra watertank. Voordat ik de doos sloot, voegde ik schoteltjes toe om te voorkomen dat er water in de doos zou verdrinken om de elektronica te beschermen.

Stap vijf:de website-API

De API en website zijn gebaseerd op jQuery, Bootstrap, X-editable (voor inline ajax-formulieren) en Chart.js (voor de vochtigheidsgrafiek), gecodeerd in php. Op de website kun je de instellingen voor de Arduino definiëren (bijv. sensorpinnen, vochtigheidscontrole-interval, pompen per plant, pomp VCC-pinnen, lichte VCC-pin) en de huidige vochtigheid + grafiek vinden.

De configuratie wordt verzorgd door JSON voor de Arduino. Na het starten en met regelmatige tussenpozen controleert de kruidenbox op nieuwe instellingen. Voor het ontleden van de JSON met de Arduino heb ik de bibliotheek ArduinoJson gebruikt. Voor het polling-interval heb ik StensTimer gebruikt.

Bibliotheek:ArduinoJson | Bibliotheek:StensTimer

Stap zes:Alexa-integratie

De website biedt een API voor Alexa-communicatie. Het dient als een hub om het verzoek JSON van Alexa te ontvangen en vertaalt het naar een aangepaste JSON die door de Arduino wordt gebruikt (bijvoorbeeld lamp aan, irrigatie-installatie 1, ...). De Arduino zoekt naar nieuwe acties en voert deze uit.

Omdat de spraakverzoeken meer zijn dan alleen aan/uit, heb ik een Alexa Skill geïmplementeerd en geen Alexa Smart Home. De AWS Lampda stuurt het verzoek JSON door naar mijn API, die de intenties parseert.

var https =required('https');exports.handler =(event, context, callback) => { var postData =JSON.stringify(event); var options ={ host:'', pad:'', poort:443, methode:'POST', headers:{ 'Content-Type':'application/json' , 'Content-Length':postData.length, } }; // stel het verzoek in 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)); }); }); // post de gegevens postRequest.write (postData); postRequest.end();}; 

Een uittreksel van de bedoelingen die ik heb gebruikt door mijn vaardigheid:

  • ReadHumidityIntent Hoe gaat het met mijn planten
  • ReadHumidityIntent Hoe gaat het met mijn {plantName}
  • IrrigatePlantIntent Irrigeer mijn planten
  • IrrigatePlantIntent Irrigeer mijn {plantName} gedurende {durationSeconds} seconden
  • SwitchIntent Schakel de lamp {switchState}
  • ReadIrrigateIntent Welke planten water nodig hebben
  • ReadLastIrrigationIntent Wanneer was de laatste irrigatie van mijn {plantName}

Last but not least heb ik locale-ondersteuning toegevoegd voor Duits en Engels gebruik.

Het resultaat

Als resultaat heb ik een houten kist om kruidenpotten van de supermarkt in te doen, waterbuizen en vochtsensoren in de grond te nemen en de buizen in een externe watertank. Met Alexa-integratie kan ik de volgende zinnen zeggen:

  • "Alexa, vraag kruidendoos hoe mijn planten zijn " - Reactie:"Plant 1 is prima, Plant 2 is droog, ..."
  • "Alexa, vertel de kruidendoos om mijn basilicum 5 seconden te irrigeren " - Reactie:"Basilicum 5 seconden irrigeren"
  • "Alexa, vraag kruidendoos welke planten irrigatie nodig hebben " - Reactie:"Plant 1 is droog, Plant 3 is droog, ..."
  • "Alexa, vraag kruidendoos wanneer was de laatste irrigatie van mijn basilicum " - Reactie:"Laatste irrigatie van basilicum was 36 uur geleden"
  • "Alexa, vertel de kruidendoos om de lamp aan te zetten " - Reactie:"Plantengroeilamp aangezet"

Alexa vragen naar de vochtigheid van mijn plant en daarna irrigeren (duits):

Alexa vragen om de plantengroeilamp aan te zetten:

GIF's die het resultaat tonen zonder de video's:

Geplande functies

De volgende functies zijn nog niet geïmplementeerd, maar staan ​​gepland voor de toekomst:

  • Energiebesparende modus voor de Arduino-broncode
  • Voeg externe Arduino Nano's toe met draadloze communicatie (2,4 GHz) voor vochtmeting van andere planten in huis (de box is de hub voor wifi) - alleen met batterijen
  • API uitbreiden voor meerdere instanties van de kruidendoos, voor vrienden (en wie dan ook, als je geïnteresseerd bent?!)
  • Voeg een knop toe om te irrigeren en schakel de lamp op de doos zonder website of Alexa
  • Alexa-afbeeldingen (kaart in vaardigheidsreactie)

Update 23.03.2018

Ik heb twee nieuwe intenties toegevoegd. Een daarvan is belangrijk voor de geplande functie van externe Adruino Nano's die alleen de vochtigheid loggen.

  • Welke planten zijn droog
  • Wanneer was de laatste irrigatie

Code

  • 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; int actie; int-pin; lange duur; ongeldige timerCallback (Timer * timer); void switchPin (int pin, bool-waarde); ongeldig readStack(); ongeldig proces(); ongeldig 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); // gedeactiveerd voor prestaties }}void EcoActionBuffer::process() { toSerial(); pinMode (pin, UITGANG); digitalWrite (pin, HOOG); switch (actie) { case ACTION_ECOACTION_HIGH:switchPin (pin, true); pauze; geval ACTION_ECOACTION_LOW:switchPin (pin, false); pauze; } if (duur !=0) { StensTimer::getInstance()->setTimer(this, -pin, duration); }}void EcoActionBuffer::timerCallback(Timer* timer) { switch (timer->getAction()) { case ACTION_ECOACTION_READ:readStack(); pauze; } if (timer->getAction() <0) { switchPin(abs(timer->getAction()), false); }}void EcoActionBuffer::switchPin(int pin, bool value) { switch (value) { case true:digitalWrite(pin, LOW); pauze; case false:digitalWrite(pin, HIGH); pauze; } WhiteWalnutApi::switchPin(pin, waarde);}void EcoActionBuffer::reset() { entryNo =0; actie =0; pin =0; duur =0;}void EcoActionBuffer::toSerial() { Serial.print(entryNo); Serial.print(F(" - Actie:")); Serial.print(actie); Serial.print(F(", Pin:")); Serial.print(pin); Serial.print(F(", Duur:")); Serieafdruk(duur); Serieel.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 (humidityDataPin !=0) { Serial.print (code); Serial.print(F(" - Controleer vochtigheid...")); digitalWrite (PIN_HUMIDITY_VCC, HOOG); vertraging (200); // TODO int vochtigheid =1023 - analogRead (humidityDataPin); digitalWrite (PIN_HUMIDITY_VCC, LAAG); Serial.println(vochtigheid); WhiteWalnutApi::sendHumidity(*this, vochtigheid); if (humidityCheckInterval ==0) vochtigheidCheckInterval =60000; StensTimer::getInstance()->setTimer(this, ACTION_PLANT_CHECKHUMIDITY, vochtigheidCheckInterval); } else StensTimer::getInstance()->setTimer(this, ACTION_PLANT_CHECKHUMIDITY, 60000);}void Plant::updateApi() { WhiteWalnutApi::updatePlant(*this); // WhiteWalnutApi::sendHeartbeat(*this); // gedeactiveerd voor prestaties pinMode (PIN_HUMIDITY_VCC, OUTPUT); toSerial();}void Plant::timerCallback(Timer* timer) { switch (timer->getAction()) { case ACTION_PLANT_CHECKHUMIDITY:checkHumidity(); pauze; }}void Plant::toSerial() { Serial.print(code); Serial.print(F(" - DataPin:")); Serial.print (vochtigheidDataPin); Serial.print(F(", Interval:")); Serial.print(humidityCheckInterval); Serieel.println();}
Plant.hArduino
#ifndef PLANT_H#define PLANT_H#include "Arduino.h"#include "StensTimer.h"struct Installatie:public IStensTimerListener { const char* code; int vochtigheidDataPin; lange vochtigheidCheckInterval; void checkVochtigheid(); ongeldige timerCallback (Timer * timer); ongeldig 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.begin_96 {Serial setup(READ 1 Serial); terwijl (!Serial); stensTimer =StensTimer::getInstance(); leftPlant.code ="LINKS"; centerPlant.code ="CENTER"; rightPlant.code ="RECHTS"; externalPlant.code ="EXTERN"; while(!WhiteWalnutApi::connectToWiFi()) vertraging (2000); WhiteWalnutApi::switchPin(0, false); apiTimer.updateApi(); leftPlant.checkVochtigheid(); centerPlant.checkVochtigheid(); rightPlant.checkVochtigheid(); externalPlant.checkVochtigheid(); 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(); pauze; }}
WhiteWalnutApi.cppArduino
u moet uw wifi- en API-instellingen toevoegen
#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); while (espSerial.available()) Serial.write(espSerial.read()); Serial.println(F("[ESP] Verbinding maken met 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] Reset mislukt")); onwaar retourneren; } Serial.println(F("[ESP] CWMode instellen")); espSerial.println(F("AT+CWMODE=1")); if (!espSerial.find(findOK)) { Serial.println(F("[ESP]-modus mislukt")); onwaar retourneren; } Serial.println(F("[ESP] verbinding maken met router")); 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-verbinding mislukt")); onwaar retourneren; } } espSerial.setTimeout(3000); Serial.println(F ("[ESP] WiFi is verbonden")); return true;}void WhiteWalnutApi::updatePlant(Plant&plant) { String site =String(API_PLANT) + "?action=get&code=" + String(plant.code); while (!httpRequest(site)) connectToWiFi(); JsonObject&root =parseJson(); if (root.success()) { plant.humidityDataPin =root["dataPin"].as(); plant.humidityCheckInterval =atol(root["interval"].as()); }}void WhiteWalnutApi::sendHumidity(Plant&plant, int vochtigheid) { String site =String(API_PLANT) + "?action=humidity&code=" + String(plant.code) + "&humidity=" + String(humidity); while (!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["waarde"].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=" + String (waarde); while (!httpRequest(site)) connectToWiFi();}bool WhiteWalnutApi::httpRequest(String-site) { // char* cmd; // sprintf(cmd, "GET %s HTTP/1.0\r\nHost:%s\r\nVerbinding:sluiten", site, API_SERVER); /* String cmd =""; cmd +="GET " + site + " HTTP/1.0\r\n"; cmd +="Host:" + String(API_SERVER) + "\r\n"; cmd +="Verbinding:sluiten"; int cmdLength =cmd.length() + 4; Serieel.println(cmd); */ int cmdLength =44 + site.length() + strlen(API_SERVER); // Serial.print (F ("[GEHEUGEN] ")); // Serial.print (freeMemory()); // Serial.print(F(" - ")); // Serial.println(site); // -> 785 for external espSerial.print(F("AT+CIPSTART=\"TCP\",\"")); espSerial.print(API_SERVER); espSerial.println(F("\",80")); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] TCP Connection Error")); onwaar retourneren; } espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); // espSerial.println(strlen(cmd)); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] Send State Error")); onwaar retourneren; } espSerial.print(F("GET ")); espSerial.print(site); 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()); opbrengst; if (!espSerial.find(findDP)) { Serial.println(F("Bytes not sent")); espSerial.print(F("AT+CIPCLOSE")); onwaar retourneren; } 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); onwaar retourneren; } // Check HTTP status if (!espSerial.find(findHD)) { Serial.println(F("[ESP] Invalid response")); onwaar retourneren; } // Skip HTTP headers // if (!espSerial.find(findBT)) { Serial.println(F("[ESP] Bytes not found")); opbrengst; } // 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

Schema's

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.

Productieproces

  1. Web-gestuurde DMX-controller
  2. Arduino Spybot
  3. Arduino Alarmsysteem:SERENA
  4. Arduino + ESP-weerbox
  5. Kelder/kruipruimte ventilatiesysteem
  6. Aanwezigheidssysteem op basis van Arduino en Google Spreadsheet
  7. BLUE_P:Wireless Arduino Programming Shield
  8. Arduino-gebaseerd waarschuwingssysteem voor botsingsdetectie
  9. TFT Shield voor Arduino Nano - Start
  10. Arduino Shield NCS314 NIXIE buizenklok IN-14
  11. Arduino GrowBox-controller