In het vorige deel hebben we met de ESP32 DevKitC, van een RGB-LED en een lichtgevoelige weerstand een klein apparaat gebouwd, dat periodiek helderheidswaarden meet en de resultaten naar het cloud-platform AllThingsTalk zendt. Daar worden ze weergegeven op een door de gebruiker te configureren webpagina. Om dat te laten werken, moet de ESP32 eerst inloggen op een WLAN en daarna via TCP/IP en MQTT verbinding maken met de MQTT-broker van AllThingsTalk. Als dat gelukt is, dimt de RGB-LED periodiek van groen naar omlaag. Elke twee seconden wordt met de ADC een helderheidswaarde gemeten en die wordt gepubliceerd via MQTT. De benodigde configuratieparameters (b.v. de SSID van het WLAN) kunnen worden ingesteld op een webpagina, die de ESP32 via een zelf opgezet WLAN en een eigen webservertje beschikbaar stelt.

Dat is een goed begin. Maar ik had er nog helemaal geen aandacht aan besteed, dat de verbinding ook kan wegvallen. Bij het testen voor de vorige aflevering heb ik het apparaat ook eens een halve dag laten lopen, tot de accu van mijn powerbank leeg was (naar energiebesparing gaan we in een latere aflevering nog kijken). Zo kon het gebeuren, dat de WLAN-verbinding werd verbroken. Maar het programma had dat helemaal niet in de gaten. De groene LED bleef mooi staan te faden, maar er kwamen natuurlijk geen waarden meer aan bij AllThingsTalk. Een goede datalogger doet dat anders.
 

De ESP32 pingt

We krijgen van de broker geen terugmelding als we een MQTT-bericht publiceren. Maar MQTT biedt wel een ping-mechanisme om vast te stellen, of er nog een MQTT-verbinding is. Daarom heb ik om te beginnen een regelmatig aanpingen van de AllThingsTalk-broker toegevoegd in mijn Arduino-sketch. Om te veel dataverkeer te voorkomen, doe ik alleen na elke vijfde keer verzenden van een sensorwaarde een ping-verzoek. Met een tellertje is dat gemakkelijk te realiseren. Ik heb de teller en het pingen helemaal aan het begin van de Loop-lus geïmplementeerd in het codefragment waar het faden en de MQTT-functies worden aangeroepen. Als het pingen mislukt, wordt MQTTClient_Connected weer van true op false teruggezet, de waarde, die deze variabele ook bij de start van het programma heeft. Daarna volgt in de sketch meteen het codefragment, waar verbinding met de broker wordt gemaakt. Hier hoefde ik niet veel te veranderen. Ik heb alleen toegevoegd, dat in geval van mislukken
 
RouterNetworkDeviceState = NETWORKSTATE_NOTLOGGED;

moet worden. Ik neem namelijk aan, dat we waarschijnlijk de verbinding met het WLAN zijn kwijtgeraakt, als na het pingen ook het verbinden via MQTT niet lukt.
Nu moest ik nog in de hoofdlus een test op
 
RouterNetworkDeviceState != NETWORKSTATE_LOGGED;

inbouwen, gevolgd door een (herhaalde) poging tot inloggen.

Een paar kleine functies

Zo’n poging moet nu op drie verschillende plaatsen in de code worden geïnitieerd: Bij de start van het programma in de setup-functie, na de ontvangst van het ingevulde configuratieformulier en na een mislukte ping gevolgd door mislukt connect-verzoek. Dat vraagt natuurlijk om het schrijven van een eigen functie. Ik heb deze LoginRouterNetworkAndSetRGB() genoemd. Maar ik roep die functie niet rechtstreeks aan op die drie plaatsen in de code. In plaats daarvan heb ik op die plekken alleen
 
RouterNetworkDeviceState = NETWORKSTATE_NOTLOGGED;

gezet. Het inlog-verzoek komt dan niet meteen, maar pas als bij het doorlopen van de Loop-lus de test wordt uitgevoerd. Om te voorkomen dat ik door continu herhaalde inlog-pogingen het hele programma zou lamleggen, heb ik ook hier een tellertje toegevoegd. Er is nu altijd ongeveer twee seconden “leegloop” tussen twee inlog-pogingen. Het asynchroon aanroepen van de functie LoginRouterNetworkAndSetRGB() heeft nu trouwens het voordeel, dat na het verzenden van het configuratieformulier naar de ESP32-webserver niet meteen een inlog-poging wordt gedaan. Daardoor wordt de nieuwe webpagina sneller uitgeleverd (adres 192.168.4.1, raadpleeg voor meer details de eerdere afleveringen). Maar op deze manier bouwen we een klein schoonheidsfoutje in. We krijgen het adres van de ESP32 in het routernetwerk pas teruggemeld, als de poging tot inloggen slaagt en de groene LED begint te faden. We moeten daarna opnieuw de Submit-button in het formulier aanklikken.
Vervolgens heb ik ook het publiceren van de sensorwaarden en het webserver-codegedeelte in eigen functies ondergebracht. Dat maakt de hoofdlus overzichtelijk en kort, zoals in het screenshot te zien is.


 
In de code herkennen we de drie tellers en het zetten van de twee toestandsvariabelen MQTTClient_Connected en RouterNetworkDeviceState. Ook de setup-functie is slanker geworden (de nieuwe sketch is zoals altijd te downloaden, zie onderaan deze pagina). Tenslotte heb ik nog mijn kleine WLAN-netwerk-library omgezet in een klassebibliotheek, net zoals ik dat in het vorige deel gedaan heb met de TCP/IP- en MQTT-functies. De files WiFiNetwork.h/.c zijn ondergebracht in een gelijknamige map, die bij het compileren in de map Libraries van de Arduino-werkomgeving moet staan. Ik heb de seriële uitvoer uit de functies gehaald en die verplaatst naar het hoofdprogramma. Daarvoor heb ik ook nog de functie GetOwnIPAddressEenRouterNetwork() gemaakt, die het adres van de ESP32 in het routernetwerk teruggeeft. Het aanroepen van de WLAN-netwerk-functies gaat nu met de objectgeoriënteerde schrijfwijze. Zo wordt bijvoorbeeld:
WiFi_SetBothModesNetworkStationAndAccessPoint();
nu:
myWiFiNetwork.SetBothModesNetworkStationAndAccessPoint();

Deze veranderingen voegen helemaal geen functionaliteit toe aan het project en kunnen misschien wat saai lijken, maar we zullen van de toegenomen modulariteit van de software later nog profiteren, als we andere platforms gaan uitproberen.
 

Compact en voordelig: ESP32-PICO-KIT

Als u in het bezit bent van een ESP32DevKit C kunt u de nieuwe software meteen uitproberen. Maar er is een andere mogelijkheid, die zelfs nog compacter is: de ESP32-PICO-KIT, die ook wordt gebruikt voor de nu lopende ESP32-ontwikkelwedstrijd. Het kleinere board heeft het voordeel, dat het op breadboards meer ruimte vrij laat.



De sketch kon 1:1 op het nieuwe board worden geladen, ik heb geen verschillen kunnen vinden. De door mij gebruikte pennen liggen op de connectors wel op een andere plaats, maar dat is op een breadboard geen probleem. Ik heb de rode test-LED nu aangesloten aan pen 15 in plaats van aan pen 12 (en de code hierop aangepast). En er is nog een verandering: na een tijdelijke onderbreking van de voedingsspanning moeten we op de EN-button drukken, anders start het programma niet.

Tijdens de uitvoering is het regelmatige aanpingen te herkennen aan een korte onderbreking van het faden van de LED. Verdere aanwijzingen zijn te vinden aan het einde van het vorige deel. Ik heb het apparaatje een hele dag laten lopen, en tussentijds ook het verbreken van de WLAN-verbinding gesimuleerd. Op mijn AllThingsTalk-webpagina heb ik de gemeten en gepubliceerde sensorwaarden in een staafdiagram laten weergeven. In het screenshot aan het begin van dit artikel is te zien, hoe het in mijn „Home Office“ ’s middags langzaam donker werd. Toen ik tegen 18:00 uur het licht aandeed, was er een kleine piek te zien. :-)

In het volgende deel gaan we weer verder!