Het kan ook zonder Amazon!
Wifi-buttons op batterijen voor IoT zelf bouwen en programmeren
Amazon verkoopt zijn Dash-buttons met wifi-ondersteuning niet in Nederland en België. Moeten we het dan doen zonder deze handige apparaatjes? Nee hoor, we bouwen ze gewoon zelf! Dan heb je ook de server van Amazon niet meer nodig.
Een van de opvallendste IoT-apparaten van 2016 was toch wel de Amazon Dash Button van 5 dollar. Met dit kleine apparaatje op batterijen kun je letterlijk met één druk op de knop verbruiksproducten bestellen bij Amazon. Denk aan wasmiddel, scheermesjes, condooms of koffie. Helaas is deze hele hype ons in de Benelux tot nu toe voorbij gegaan, net als de Amazon Echo en Dot met Alexa-stembediening overigens. In de landen om ons heen, zoals Groot-Brittannië, Duitsland, Oostenrijk, Frankrijk, Spanje en Italië zijn de slimme knoppen wel te koop, voor 5 euro per stuk.
Op internet duiken intussen ook nog eens talloze ideeën op waarvoor je die Dash Buttons zou kunnen gebruiken, los van de door Amazon bedoelde bestelfunctie. Maar het nadeel van zo'n hack is dat de Amazon Dash Button altijd contact moet maken met een server van Amazon. Je zou een oplossing kunnen bedenken waarmee je de buttons met een Raspberry Pi van de Amazon-server kunt bevrijden. Maar het beste is een knop waarbij je zelf bepaalt met welke server hij contact maakt.
En precies daarvoor gebruiken we de in de maker-scene populaire ESP-01 wifimodule met de ESP8266 microcontroller. Diens 80MHz-cpu heeft genoeg power voor versleutelde communicatie via TLS 1.1 en in stand-by verbruikt hij zo weinig stroom dat de button het jarenlang uithoudt op twee AAA-batterijen. Het printje met SoC, antenne en aansluitpinnen is niet groter dan een vingerkootje. Zodoende past het geheel makkelijk in de behuizing van een simpel led-kastlampje op batterijen (zoek op: push light). Met een usb-naar-serieel adapter (via AliExpress te koop voor nog geen twee euro) sluit je de ESP-module op de computer aan en programmeer je hem
met de Arduino-programmeeromgeving (IDE). De zelf geschreven firmware in C heeft dankzij de goede bibliotheken voor de ESP8366 niet meer dan 150 regels code nodig.
Wat heb je nodig
Om zelf een Dash Button te maken, heb je wel wat gereedschap nodig: een soldeerbout, een stanleymes en een figuurzaagje om de plastic behuizing van het kastlampje aan te passen. Bovendien moet je er een paar uurtjes voor uittrekken.
In het lijstje met benodigdheden staat wat je allemaal nodig hebt voor één button. De seriële USB-UART-interface (Universal Asynchronous Receiver Transmitter) en de aansluitkabel hoef je natuurlijk maar een keer te kopen, hoeveel knoppen je ook maakt. Als je door dit artikel de smaak te pakken krijgt en meer wilt gaan experimenten met de ESP8266, is het de moeite waard om een breadboard inclusief 3,3Vvoeding te kopen. De opgegeven prijzen zijn de laagste prijzen die we vonden bij bestellen in China. Denk er wel aan dat het dan ongeveer drie weken duurt voordat je de producten in huis hebt. Wanneer je de onderdelen in een webshop in Nederland bestelt, duurt zoiets maar drie dagen, maar dan betaal je wel circa 7 euro per knop en 4 euro voor de interface en kabeltjes.
Hardware
Je doe-het-zelf Dash Button moet net als het origineel op batterijen werken. De buttons zijn namelijk pas echt handig als ze niet afhankelijk zijn van een stopcontact. De ESP8266 is bedoeld voor een voedingsspanning van 3,3 volt. Maar hij werkt ook zonder problemen op 3 V. Daarom kun je hem gewoon met twee in serie geschakelde AAA-batterijen gebruiken. Denk eraan dat je met de 4,5 V van drie batterijen of de 5 V die je voor Arduino-bordjes kunt gebruiken, de chip kapot maakt. Bij het zoeken naar een geschikte behuizing voor twee batterijen en een knop kwamen we terecht bij ledlampjes voor drie AAA-batterijen, die als nachtlampje of kastverlichting worden verkocht. De ronde lampjes zijn ongeveer zo groot als je handpalm en kosten nog geen euro (bij de Action krijg je er drie voor 2 euro). Het zijn eigenlijk grote drukknoppen met een doorzichtige bovenkant en daaronder drie of vier in een reflector ingebouwde leds. Deze leds zitten samen met de aan-/uitschakelaar op een klein driehoekig printplaatje tussen de drie batterijen.
De schakelaar heeft een mechaniek dat lijkt op dat van een balpen. Dit zet hem na een keer indrukken vast op de ingeschakelde toestand. Dit gebeurt door een klein haakje binnenin het houdertje van de schakelaar. Met een kleine schroevendraaier kun je de klemmetjes van dit houdertje openen en het haakje met een pincet of een klein tangetje verwijderen. Daarmee verander je de aan-/uitschakelaar in een drukknop.
Omdat de processor maar op twee batterijen werkt, kun je op de plaats van de derde batterij ruimte maken voor de ESP01 module. We gebruiken daarvoor een figuurzaagje. De ESP-01 is namelijk iets breder dan een AAA-batterij.
Ten slotte moeten we nog het driehoekige printplaatje aanpassen. Daarvoor gebruiken we de soldeerbout. De powerleds moeten eruit, want die gebruiken te veel stroom. Op de plek van een van de leds zetten we een low current led (2mA). Deze moet de status van de knop weergeven. Hij staat in serie met een weerstand van 2,2 kΩ. Een van de 10 kΩ-weerstanden zet op IO pin 0 een spanning van 3 V, om de ESP in zijn normale toestand te zetten. De tweede zet de reset-pin op 3 V. Zolang de ESP draait en reset op 3 V staat, start hij niet opnieuw op. Aan de reset-pin hangt ook nog de knop die hem met de aarde (GND) verbindt. Wanneer de knop wordt ingedrukt, komt er geen 3 V meer op de reset-pin en is hij in plaats daarvan met de aarde verbonden. Deze reset-aarde-verbinding zorgt ervoor dat de microcontroller opnieuw opstart.
Je kunt deze schakeling ook op het driehoekige plaatje bouwen. Het is voldoende om een printbaan op een plek te onderbreken, een extra gat te boren en aan de bovenkant een draad toe te voegen. Afhankelijk van de fabrikant van het led-lampje kan de lay-out van het printje afwijken van ons exemplaar.
Voor de verbindingen met de ESP01 kun je bijvoorbeeld koperlakdraad of dunne montagedraad gebruiken die je aan de onderkant van de pinnen moet solderen. Voor het programmeren moet je namelijk op de aarde-pin ook nog een jumperkabel kunnen steken.
Programmeermodus
Voor het programmeren verbind je de ESP01 met de seriële usb-interface. Let erop dat de interface niet meer dan 3,3 V op de dataverbindingen zet. Sommige kun je namelijk omschakelen tussen 3,3 V en 5 V. Zorg met een jumperkabel voor een gemeenschappelijke aarde en verbind met twee andere jumperkabels de Rx met de Tx en omgekeerd. Als laatste verbind je de interface via USB met de computer.
Met deze opbouw kun je bijvoorbeeld met de Java-tool ESPlorer (zie link onderaan dit artikel) de standaard geïnstalleerde AT-firmware op de ESP aanspreken. Om deze firmware te vervangen door je eigen programma, moet je de ESP eerst in de programmeermodus zetten.
Deze krijg je als de GPIO 0 bij een reset aan de aarde hangt. Verbind daarom bijvoorbeeld met een kabel met krokodillenklemmen GPIO 0 op de print met aarde. Zorg dat de verbinding voor de 10kΩweerstand zit, omdat je anders kortsluiting veroorzaakt. Druk vervolgens op de knop, die dan de reset tot stand brengt.
In principe kun je de verbinding tussen GPIO 0 en aarde nu verwijderen. De ESP blijft in de programmeermodus staan totdat je er een programma op hebt gezet, of weer een reset uitvoert. Meteen na een succesvolle upload start hij weer op in de normale modus (onafhankelijk van de spanning op GPIO 0) en voert het geüploade programma uit. Dat is erg handig, omdat je het programma zo altijd direct na het uploaden automatisch kunt testen. Krijg je daarbij een fout, dan kun je met een reset direct weer naar de programmeermodus – tenminste, als je de aardeverbinding op de GPIO 0 niet verwijderd hebt.
Arduino-IDE
Om met de Arduino-IDE de ESP8266 te programmeren moeten we eerst de BoardsManager ('Bordenbeheerder') uitbreiden. Typ daarom onder 'Bestand/Voorkeuren' in de regel 'Additionele Bordenbeheerder URLs' de volgende url in:
http://arduino.esp8266.com/stable/—
package_esp8266com_index.json
Open daarna de Bordenbeheerder ('Hulpmiddelen / Board / Bordenbeheerder') en voer in het zoekveld 'esp' in. Klik op het item 'esp8266 by ESP8266 Community' in de zoekresultaten en klik op Installeren.
Na de installatie kies je onder 'Hulpmiddelen/Board' 'Generic ESP8266 Module', zet je de 'Upload Speed' op 115200 en 'Poort' op de eerste usb-poort. Als je wilt experimenteren, vind je onder 'Bestand/ Voorbeelden' ook een submenu voor de ESP8266 met voorbeeldprogramma's voor
de meest voorkomende toepassingen. Onze firmware haal je uit de repository (zie link) of je kloont hem met git direct in je Sketchbooklocatie:
git clone https://github.com/pinae/ ESP8266-Dash.git Arduino/
De volledig broncode zit in het projectbestand ESP8266-Dash.ino.
De nieuwe firmware
Een blik in de broncode (ESP8266-Dash.ino) laat zien, hoe weinig daar echt gebeurt. In de ESP8266WiFi-bibliotheek zit het complexe deel van de wifi-communicatie, terwijl het hoofdprogramma alleen de grote lijnen definieert. Dat begint in de functie setup() in regel 21. Eerst configureert de firmware met de functie pinMode() GPIO 2 als output en zet er met digitalWrite() een waarde op. Vervolgens bouwt de firmware de wifiverbinding op:
WiFi.begin(WLAN_SSID, WLAN_PASS);
WLAN_SSID en WLAN_PASS in regel 6 en 7 zijn vast gedefinieerde strings, die je moet aanpassen aan je eigen wifi-toegangsgegevens. Het opbouwen van de verbinding duurt ongeveer twee seconden, zodat het programma ook zo lang moet wachten voordat het de verbinding kan gebruiken. De code kan herkennen of het opzetten van de verbinding is voltooid, doordat WiFi.status() de waarde WL_CONNECTED aanneemt. Om te zorgen dat het programma niet oneindig naar een niet aanwezig netwerk zoekt, gaat het na 30 seconden zonder verbinding in stand-by:
int failcounter = 300; while(WiFi.status() != WL_CONNECTED){ delay(100); if(failcounter <= 0){ blinkError(); shutdown(); } failcounter--;
}
In regel 124 en 142 definieert de code de functies blinkError() en shutdown(). De blinkfunctie laat de led gedurende zeven seconden knipperen. shutdown() zet de microcontroller met ESP.deepSleep(0) tot de volgende reset in een diepe slaapstand waarin hij maximaal 10 μW verbruikt.
Vervolgens komt de WiFiClientSecure waar in regel 17 de variabele client aan toegewezen wordt. De methode client .connect() bouwt met de opgegeven host een verbinding op. Deze meldt of de opgegeven host in principe requests accepteert. Een SSL-verbinding met de Raspberry Pi met ip-adres 192.168.12.1 bouw je op de volgende manier op:
const char* host = “192.168.12.1”; int port = 443; if (client.connect(host, port)) {
Bij zo'n verbinding antwoordt de server eerst met zijn certificaat, dat normale clients via de certificaatketen en een lijst met vertrouwde CA's controleren. Maar de ESP8266 heeft niet de rekenkracht voor zo'n uitgebreide controle en ook niet de geheugenruimte voor een omvangrijke lijst van CA's. Daarom maken we de certificaatcontrole beknopter door alleen te controleren of de SHA1-hash van het certificaat overeenkomt met een vast ingeprogrammeerde waarde. Daarmee pinnen we ook tegelijk het servercertificaat [1]. Deze controle gebeurt met de functie verifyFingerprint():
void verifyFingerprint() { if (! client.verify(FINGERPRINT,
CERT_NAME)) { // Connection insecure! blinkError(); shutdown();
} }
De constanten FINGERPRINT en CERT_NAME worden door het programma in regel 11 en 12 gedefinieerd. CERT_NAME moet precies overeenkomen met de Common Name in je certificaat en FINGERPRINT met de SHA1-
hash. Je geeft de hash op als een in paren gegroepeerde tekenreeks met hexadecimale cijfers.
Deze manier van certificaatcontrole heeft als nadeel dat het certificaat niet mag veranderen. Als je dus op de server waarmee je button contact maakt, een ander certificaat wilt gebruiken, moet je ook de firmware van de button aanpassen en opnieuw flashen.
Wanneer het belangrijk is dat het certificaat kan veranderen, moet je de firmware zo uitbreiden, dat die achtereenvolgens meerdere hashes controleert en de lijst met hashes ook nog kan vervangen. Maar dat valt buiten het kader van dit voorbeeldproject.
Na het controleren van het certificaat kun je met een gerust hart requests over de versleutelde verbinding sturen. Een leeg GET-request aan de default-pagina van de host ziet er bijvoorbeeld zo uit:
client.print(String(“GET /”)+ “HTTP/1.1\r\n”+
“Host: “+ host + “\r\n”+ “Connection: close\r\n”+ “\r\n”);
Kort daarop stuurt de server zijn antwoord terug. We zoeken daarin alleen naar een regel die met 'OK' begint. Als die gevonden wordt, gaan we ervan uit dat het indrukken van de knop geregistreerd is. Zodra de server de verbinding verbreekt, heeft de button het complete antwoord ontvangen. Net als bij het opbouwen van de wifiverbinding voorkomt de code in ieder geval een oneindige lus:
int success = 0; failcounter = 10000; while (client.connected()) { if (client.available()) {
String line = client
.readStringUntil(‘\n’); if (line[0] == ‘O’ &&
line[1] == ‘K’){ digitalWrite(LED, LOW); success = 1;
}
} if (failcounter <= 0){ blinkError(); shutdown();
} failcounter--; Daarna signaliseert het programma de succesvolle communicatie met blinkSuccess() of het mislukken ervan met blinkError(). Bij de functie blinkSuccess() hebben we de knipperfrequentie voor de aardigheid van snel naar langzaam laten gaan. Daarmee willen we aangeven dat de data met succes van de button naar de server gaan.
Zelfbouw-IoT
Bij het energieverbruik hebben we 0,5 mWh per knopdruk gemeten. Met normale AAA-batterijen zou je dan tweeduizend keer op de knop moeten kunnen drukken – genoeg om de button een paar jaar te gebruiken zonder de batterijen te hoeven wisselen. Het verbruik in stand-by was voor ons niet te meten. De door Espressif, de fabrikant van ESP, opgegeven waarde van 10 μW belooft eveneens vele jaren gebruik. Maar ook als je heel veel zou willen drukken, hoef je niet bang te zijn. Want in tegenstelling tot de Amazon-button die dichtgeplakt is, kun je de batterijen van deze zelfbouw-button makkelijk vervangen.
En dat betekent dat je alleen nog een paar goede ideeën nodig hebt, wat je allemaal met een wifi-button zou willen schakelen. Je kunt hem bijvoorbeeld op je wasmachine plakken en zo 'waspoeder' op je boodschappenlijstje laten zetten. Op die manier kun je mooi de prijzen en aanbiedingen vergelijken en hoef je nog niet meteen online te bestellen zoals bij de buttons van Amazon het geval is. Of je kunt ermee registreren hoe vaak je de hometrainer gebruikt of de koelkast openmaakt. Voor de koelkast kun je de ESP8266 overigens ook direct in de deur inbouwen. Of je activeert met de button de koffiemachine voor het eerste kopje zwarte goud na het opstaan, lekker lui vanuit je bed. En als je nog geen koffiemachine met wifi hebt, dan kun je je bestaande machine gewoon ombouwen; je kent nu de ESP8266 immers en weet hoe je hem moet programmeren.