Conrad Components 10215 Profi Lernpaket Internet of Things Course material 14 years and over Handleiding

Type
Handleiding
VOOR U BEGINT
Wanneer u het IoT-WiFi-Board (hierna ook
NanoESP- genoemd) voor het eerst aansluit, kan het gebeuren dat de computer de
vereiste driver voor de USB-to-Serial-omzetter niet automatisch vindt. Als dit het
geval is, dient u de driver van de pagina www.iot.fkainka.de/driver te downloa-
den en manueel te installeren. In de Arduino-software kunt u dan de port en als
board Arduino Nano (processor: Atmega328) selecteren. Daarna moet de con-
troller volledig gebruiksgereed zijn.
Om met de seriële monitor te werken, moet u eveneens instellingen uitvoeren. Als
Baudrate wordt hier 19200 Baud gebruikt. Om bevelen te versturen moet u bo-
vendien de optie CR en NL naast het menu voor de Baudrate selecteren.
De juiste instellingen in de Arduino-omgeving
Ik heb met de Arduino-IDE-versies 1.6.5. - 1.6.6. gewerkt. Oudere versies kunnen
problemen veroorzaken. De huidige versie vindt u op de website
www.arduino.cc.
Bij moeilijkheden of problemen met het board of het leerpakket kunt u op elk mo-
ment op de website www.iot.fkainka.de hulp vinden. Op deze website vindt u
bovendien een forum, nieuwe gebruikersprojecten en ook alle hier voorgestelde
programma's in de meest recente versie.
In het leerpakket bevindt zich een breadboard waarop u de
NanoESP, kunt aansluiten, zoals getoond in de onderstaande afbeelding. Daar-
door blijft de meeste plaats voor experimenten terwijl de WLAN-module achteraan
boven het breadboard uitsteekt. De micro-USB-kabel kan dan worden aangeslo-
ten, zoals getoond op de afbeelding in het volgende hoofdstuk, en stoort slechts
minimaal. Gedetailleerde opbouwafbeeldingen vindt u in het overeenkomstig
hoofdstuk.
Het IoT-WiFi-Board (NanoESP)
Het hoofdelement van dit leerpakket is het IoT-WiFi-Board (NanoESP). Zoals men
aan de platine zeer goed kan herkennen, bestaat het board uit twee onderdelen.
Bij de linkerhelft gaat het om een Arduino-compatibel microcontrollersysteem dat
met de Arduino Nano vergelijkbaar is. Het rechterdeel is de WLAN-module met de
omschrijving ESP8266.
Deze beide componenten communiceren met elkaar via een door software gege-
nereerde seriële interface.
De NanoESP op het breadboard
De pin-lay-out van het board
Op het board zijn er veel verschillende elementen, zoals bv. de pins, waarvan
enkele een bijzondere functie hebben of de LED's, wier functies niet altijd op het
eerste zicht zichtbaar zijn. Opdat u het overzicht niet verliest, zijn de belangrijkste
functies en omschrijvingen van de afzonderlijke elementen in de volgende afbeel-
ding aangebracht.
De belangrijkste pins en omschrijvingen van het board
De WLAN-module wordt via zogenaamde AT-commando's gestuurd. Daarvoor is
het Arduino-deel van het board via pins 11 en 12 met de WLAN-module verbon-
den. Een kleine schakeling zet het 5 V-niveau in een compatibel 3,3 V-niveau om.
Pins 11 en 12 mag u dus niet in eigen projecten gebruiken.
Verdere belangrijke hardware-eigenschappen van het board vindt u in de onderste
tabel kort opgelijst.
Technische gegevens
Microcontroller: ATmega328
Flashgeheugen: 32 kB (waarvan 0,5 kB voor de bootloader)
SRAM: 2 kB
EEPROM: 1 kB
Kloksnelheid: 16 MHz
I/O-pins: 20 (waarvan 2 voor de communicatie met de
WLAN-module)
U
waarvan PWM: 6
U
waarvan analoge ingangen: 6
USB-to-Serial-chip: CH340G
Bedrijfsspanning: 5 V
Aangewezen ingangsspanning: 7 12 V
Maximale stroom pre I/O-pin: 40 mA
Belastbaarheid van de 3,3 V-uitgang: 50 mA
WLAN-module: ESP8266
SPI-flash 4 Mbit
Bedrijfsspanning: 3,3 V
WLAN-standaarden: 802.11 b/g/n
WLAN-modi: Wi-Fi Direct (P2P), soft-AP
Firmware: AT-firmware versie 0.22
Overige: Geïntegreerde TCP/IP-stack
+19,5 dBm uitgangsvermogen in de 802.11b-modus
Geïntegreerde low-power-32-bit-CPU
Communicatie via UART
ELEMENTEN IN HET
LEERPAKKET
Hieronder vindt u een overzicht van de elementen die zich in het leerpakket bevin-
den.
1 IoT-WiFi-Board (NanoESP)
1 breadboard
1 m draadbrug
2 knoppen
1 9V-clip
1 LED (rood)
1 RGB-LED (4 contactpennen)
1 weerstand 10 kOhm (bruin-zwart-oranje)
1 weerstand 1 kOhm (bruin-zwart-rood)
1 fototransistor (2 contactpennen)
1 NTC 10 kOhm
1 Piezo-luidspreker
1 potentiometer 10 kOhm met rode draaiknop
DE MODULE LEREN
KENNEN
In dit eerste hoofdstuk gaat het om de algemene werking van de WLAN-module.
De module wordt via zogenaamde AT-commando's gestuurd. Alle hier gebruikte
voorbeeldprogramma's, hulp en andere informatie vindt u overigens op
www.iot.fkainka.de
Het makkelijkst is om het volledige zip-bestand te downloaden en de uitgepakte
map in uw sketch-map te kopiëren. Dan kunt u uit het Arduino-oppervlak alle pro-
gramma's makkelijk na elkaar openen.
1.1
|
Algemene AT-bevelen
Men krijgt de beste eerste indruk van het gebruik van AT-bevelen door ze gewoon
uit te proberen. Daarom leert u in dit hoofdstuk enkele van de algemene bevelen
kennen.
Open hiervoor het programma P01_SoftwareSerial in de Arduino-IDE. Het gaat
om een zeer eenvoudig programma dat niets meer doet dan alle gegevens die via
de seriële hardware-interface van de microcontroller worden ontvangen, via de
zelf gedefinieerde software-interface naar de ESP-controller door te geven. Het
geheel werkt ook in omgekeerde richting. Zoals men in de brontekst kan zien, zijn
beide aansluitingen van de software-interface pins 11 en 12. Deze moeten in ei-
gen projecten niet als GPIO-pins worden gebruikt. U hebt bovendien de Softwa-
reSerial-Library, nodig die bij de meeste Arduino-versies reeds voorgeïnstal-
leerd is indien niet, moet u de library via de manager downloaden.
Nadat het programma werd geüpload, kunt u de seriële monitor van het Arduino-
oppervlak starten. Voor u kunt starten, moet u nog twee belangrijke instellingen
aan de Serial Monitor uitvoeren, namelijk rechtsonder in de hoek de Baudrate op
19200 instellen en in de box links daarnaast de instelling CR en NL uitvoeren.
Nu kunt u reeds een bericht zien, namelijk AT en een paar regels daaronder OK.
Het commando AT werd door microcontroller naar de ESP-module verzonden en
de module heeft met OK geantwoord. Hieraan kunt u herkennen dat de WLAN-
module werkt en gebruiksgereed is.
Terminal-instellingen CR en NL en een Baudrate van 19200
1.1.1 | Basisbevelen
Enkele algemene bevelen van de module kunt u nu testen door het commando
gewoon in te tikken en met
[Enter]
naar de module te zenden. Het is daarbij van
belang om hoofdletters te gebruiken voor het bevel. U kunt uw eerste eigen bevel
aanmaken door
AT
in de seriële monitor in te tikken en op
[Enter]
te drukken. Het opgeladen pro-
gramma geeft het bevel opnieuw naar ESP-module door, dat opnieuw met AT en
daarna OK antwoordt. Het volgende bevel dat u kunt testen, luidt:
AT+GMR
Met dit bevel worden de huidige firmware en het versienummer weergegeven.
Met het bevel
AT+RST
kunt u de module terugzetten. U ziet dan in de terminal eerst een paar onleesbare
tekens en op het einde ready als teken dat de module nu gereed is Een ander
bevel luidt:
ATE0
Hiermee is het mogelijk om de zogenaamde echo van de module te deactiveren.
Dit betekent dat u niet wilt dat het verzonden commando wordt teruggestuurd,
maar alleen het antwoord. Wanneer u bijvoorbeeld AT verzendt, komt niet eerst
AT en dan OK, maar alleen OK terug. Voor uw eerste passen is het echter aan-
gewezen om de echo met
ATE1
opnieuw te activeren.
Eerste verzoeken met de AT-bevelen
1.1.2 | WLAN-bevelen
Met de volgende WLAN-commando's kunt u belangrijke WLAN-eigenschappen
van de module wijzigen. Bij veel bevelen kunt u niet alleen slechts een toestand
vastleggen, maar ook de huidige toestand opvragen. Dit gebeurt door direct na het
bevel een vraagteken in te voeren, bv.
AT+CWMODE?
Als returnwaarde komt in regel
+CWMODE=2
gevolgd door OK. Wanneer u
AT+CWMODE=?
intikt, antwoordt de module met de mogelijke parameters van het bevel; hier na-
melijk 1-3. Bij CWMODE gaat het overigens om het bevel waarmee u de WLAN-
module kunt vastleggen.
Er zijn dus drie bedrijfsmodi die ik hieronder na elkaar vermeld:
1
AT+CWMODE=2 de module als Access Point (AP-modus)
In de leveringstoestand is de module een Access Point. Dit betekent dat u met een
WLAN-compatibel apparaat, zoals een smartphone of een pc, een rechtstreekse
verbinding met de module kunt aanmaken. Daartoe zoekt u gewoon het open WLAN
met de naam NanoESP en verbindt u zich daarmee. In de fabriekstoestand is er
geen wachtwoord gegeven zodat de verbinding zonder problemen kan worden ge-
maakt. Wanneer u met de module verbonden bent, hebt u geen verbinding met het
internet aangezien de module geen router is met een eigen verbinding met het tele-
foonnet. Deze WLAN-modus is echter toch zinvol wanneer u bijvoorbeeld een veilig
afgesloten netwerk nodig hebt. Met betrekking tot veiligheid: De mogelijkheid be-
staat ook om het netwerk van een wachtwoord te voorzien, en wel met behulp van
het bevel:
AT+CWSAP
Er moeten hier nog parameters worden ingevoerd, en wel in volgorde en geschei-
den door een komma:
U
de naam van het netwerk in aanhalingstekens,
U
het wachtwoord in aanhalingstekens,
U
de Channel ID (willekeurige waarde tussen1 en 13),
U
en de encryptiemodus (waarde van 0-4).
Een mogelijke instelling is:
AT+CWSAP="MyNanoESP","MyPassword",5,3
Na korte tijd verschijnt OK als bevestiging. Als een ERROR verschijnt, controleert
u nogmaals uw invoer, vooral de aanhalingstekens. Als ERROR toch verschijnt,
controleert u of de CWMODE echt 2 is.
Wanneer alles heeft gewerkt, kunt u zich met een WLAN-compatibel apparaat met
het board verbinden. Alle met de module verbonden apparaten kunt u met IP- en
MAC-adressen via het bevel
AT+CWLIF
laten weergeven.
De module in stationsmodus. Het IP van de verbonden computer is gemarkeerd.
2
AT+CWMODE=1 de module in de stationsmodus
Met het bevel
AT+CWMODE=1
plaatst u de module in de stationsmodus. Deze modus laat u toe om een verbin-
ding met uw WLAN-router te maken. Daardoor is de module ook met het internet
verbonden en heeft veel meer mogelijkheden.
Vooraf kunt u echter met het bevel
AT+CWLAP
alle netwerken in uw bereik laten oplijsten en zo controleren, of uw netwerk zich in
de ontvangstradius bevindt. Om een verbinding met uw router te kunnen aanma-
ken, hebt u het bevel
AT+CWLAP nodig
Deze bevat, net zoals het CWSAP-bevel, belangrijke parameters, namelijk de
naam van het WLAN-netwerk (ook SSID genaamd) en het wachtwoord, beiden
opnieuw in aanhalingstekens en door een komma gescheiden. Een verbinding
maken met een tweede module dat met de in het vorige hoofdstuk vermelde ge-
gevens is ingesteld, zou er dus als volgt uitzien:
AT+CWJAP="MyNanoESP","MyPassword"
De verbinding aanmaken kan een paar seconden duren en moet dan OK terugge-
ven. U kunt overigens de door de router gegeven IP van de module met het bevel
AT+CIFSR
oproepen. Dit zal later van belang zijn, wanneer u een verbinding met de TCP-
server van de module wilt aanmaken. Met het bevel
AT+CWQAP
kunt u de verbinding met uw router ook opnieuw verbreken.
Het board maakt een verbinding met een tweede NanoESP aan.
3
AT+CWMODE=3 de duale modus
De derde mogelijke modus van de WLAN-instelling is de duale modus. Zoals de
naam reeds laat vermoeden, laat dit u toe om de module zowel in de stations- als
in de AP-modus te gebruiken. Dit betekent dat apparaten zowel een rechtstreekse
WLAN-verbinding met de module kunnen aanmaken of de module via de router
als tussenstation bereiken. Een handige modus,
bv. wanneer men een intern net met meerdere
modules plant en een module toch als server moet
dienen die de gegevens in het net levert. Daarover
later meer.
Bevelenoverzicht in bijlage en op de website
Alle belangrijke bevelen vindt u overigens ook in de bijla-
ge en op de reeds vermelde website www.iot.fkainka.de.
Veel bevelen, zoals het instellen van de Baudrate, wer-
den bewust niet opgelijst aangezien u daarmee de modu-
le onbruikbaar kunt maken.
1.2 | Automatische configuratie
De algemene bevelen kunt u reeds manueel testen. In dit hoofdstuk moet nu de
vraag worden beantwoord, hoe deze bevelen automatisch via de controller kunnen
worden bediend. Bovendien leert u een bijkomend bevel kennen, waarmee u kunt
testen of een pc in het netwerk of een server in het internet bereikbaar is. In dit
voorbeeld wordt namelijk de Google-server aangepingt. In het voorbeeldprogram-
ma P02_GooglePing worden de werkwijzen die u in het eerste voorbeeld manueel
hebt ingetikt, grotendeels geautomatiseerd. De controller stuurt na elkaar bevelen
naar de ESP-module en maakt zo o.m. de verbinding naar de WLAN. De verschil-
lend lange time-outtijden geven de module voldoende tijd om te antwoorden.
Voor het programma echter goed kan werken, moet u uw WLAN-gegevens na #define
SSID en #define PASSWORD onmiddellijk bij het begin van de programma-
broncodes invoeren. De module heeft namelijk toegang tot het internet nodig om zijn
laatste bevel te kunnen uitvoeren. Met het bevel
AT+PING
kunnen andere apparaten in het netwerk worden aangepingd. Pingen betekent dat
men vraagt of een computer in principe bereikbaar is. Hier wordt de Google-server
met AT+PING="www.google.de" aangepingt. Wanneer er een antwoord terug-
komt, verschijnt er een melding in de Serial Monitor en de met D3 aangeduide
LED die op pin D13 aan de boards is aangesloten, wordt geactiveerd. De eerste
communicatie met het internet is dan geslaagd.
Het programma
Hieronder analyseren wij de functies van de programma's stap voor stap. Bij het
begin wordt de communicatie met de module besproken.
1
Seriële communicatie
He geheel werkt via de seriële software-interface die met de SoftwareSerial-
Library beschikbaar wordt gesteld. Bij het initialiseren moeten bovendien de ge-
bruikte pins worden aangegeven, in dit geval pins 11 en 12.
001
#include <SoftwareSerial.h>
002
SoftwareSerial esp8266(11, 12);
Net zoals bij de normale seriële interface kunnen dan bytes of hele regels met de
bevelen esp8266.print of esp8266.println worden overgedragen. Bijzonder prak-
tisch zijn ook de bevelen esp8266.find en esp8266.findUntil waarmee een inko-
mende stream op bepaalde datareeksen kunnen worden getest. Daardoor is het
heel eenvoudig om het passende antwoord van de module te onderscheppen.
Wanneer een verachte datareeks niet opduikt, kan het een hele poos duren tot het
programma verder gaat. De wachttijd (time-out) wordt door esp8266.setTimeout
gedefinieerd. Met findUntil() kan echter ook een tweede datareeks worden gedefi-
nieerd waarbij de zoekfunctie uitstapt en false als returnwaarde levert. Dit gebrui-
ken wij in de functie sendCom():
001
//-------Controll ESP--------
002
003
boolean sendCom(String command, char respond[])
004
{
005
esp8266.println(command);
006
if (esp8266.findUntil(respond, "ERROR"))
007
{
008
return true;
009
}
010
else
011
{
012
debug("ESP SEND ERROR: " + command);
013
return false;
014
}
015
}
Wanneer u de functie oproept, moet u dus het bevel en de verwachte returnwaar-
de aan de functie overgeven, bv. AT en de verwachte returnwaarde OK. Via print-
ln() wordt het commando overgedragen en tenslotte gewacht tot de verwachte
returnwaarde of een ERROR wordt ontvangen. Als de verwachting vervuld is,
geeft de functie de waarde true terug. Indien niet, zendt de module via de debug()-
functie een ESP SEND ERROR en het verzonden commando terug zodat men
makkelijk kan controleren, welk bevel de problemen veroorzaakt.
Niet alle AT-bevelen hebben een eenduidige of uit een regel bestaande return-
waarde. Als bv. het IP-adres wordt gevraagd, is er in regel geen vooraf bekende
waarde. Daarom is er een tweede sendCom()-functie die alleen de parameter
command nodig heeft en dan de hele ontvangen string teruggeeft. De string mag
echter niet te lang zijn want de buffer van SoftwareSerial kan overlopen.
001
String sendCom(String command)
002
{
003
esp8266.println(command);
004
return esp8266.readString();
005
}
2
Zoeken naar fouten
Bij het ontwikkelen van programma's komt het tot fouten en complicaties. Opdat
men überhaupt een kans heeft, zijn er twee debug-functies die via een parameter
helemaal aan het begin van het programma geactiveerd of gedeactiveerd worden.
#define DEBUG true
De eerste functie bewerkt niets meer dan een vereenvoudigde uitvoer van tekst
via de als standaard gedefinieerde seriële interface. Wanneer de constante DE-
BUG waar is, wordt de inhoud van de datareeks Msg verzonden.
001
void debug(String Msg)
002
{
003
if (DEBUG)
004
{
005
Serial.println(Msg);
006
}
007
}
De tweede functie is eveneens snel verklaard. Als de functie
serialDebug wordt opgeroepen, gaat het programma in een permanente lus over
en gedraagt zich vanaf dan zoals het eerst geteste SoftwareSerial-programma. Dit
betekent dat alle gegevens die via de seriële monitor naar de controller worden
verzonden, rechtstreeks naar de module worden doorgezonden en omgekeerd.
Ingeval van fout kan men dus de functie oproepen en manuele bevelen verzenden
om te testen, waar de fout is.
001
//---Debug Functions---
002
void serialDebug() {
003
while (true)
004
{
005
if (esp8266.available())
006
Serial.write(esp8266.read());
007
if (Serial.available())
008
esp8266.write(Serial.read());
009
}
010
}
3
Configuratie
Om de programma's over het algemeen overzichtelijker vorm te geven, werden de
meeste instellingen eveneens in eigen functies ondergebracht, met vooreerst de
functie espConfig, waarin de belangrijkste parameters voor het respectievelijke
programma kunnen worden ondergebracht.
001
//---Config ESP8266---
002
boolean espConfig()
003
{
004
boolean success = true;
005
esp8266.setTimeout(5000);
006
success &= sendCom("AT+RST", "ready");
007
esp8266.setTimeout(1000);
008
009
if (configStation(SSID, PASSWORD)) {
010
success &= true;
011
debug("WLAN Connected");
012
debug("My IP is:");
013
debug(sendCom("AT+CIFSR"));
014
}
015
else
016
{
017
success &= false;
018
}
019
020
success &= sendCom("AT+CIPMODE=0", "OK");
021
success &= sendCom("AT+CIPMUX=0", "OK");
022
023
return success;
024
}
Bij het begin van de functie wordt eerste de variabele success op true gezet aan-
gezien deze variabele nu met verschillende functies En-gekoppeld wordt. Dit bete-
kent dat wanneer er ook slechts een van de functies de waarde false teruglevert,
success eveneens onmiddellijk false wordt en de hele configuratie mislukt. Het
eerste AT-bevel dat zo op succes wordt gecontroleerd, is het Reset-bevel dat bijna
altijd bij het begin van het programma wordt uitgevoerd om te garanderen dat
vorige verzoeken niet nog de module belasten. Het kan in elk geval tot vijf secon-
den duren tot de module de melding ready terugstuurt. Daarom wordt kort voor de
sendCom()-functie, de time-out voor esp8266.findUtil verhoogd. Na het resetten
wordt de time-out opnieuw op de standaardwaarde van een seconde ingesteld.
Wat daarna volgt, is de oproep van een zelf gedefinieerde functie met de naam
configStation()die in het volgend hoofdstuk wordt besproken. Hij dient om de mo-
dule met uw thuisnetwerk te verbinden. Daartoe worden de parameters SSID en
PASSWORD overgedragen die u bij het begin van het programma hebt ingevoerd.
Als de verbinding met succes werd gemaakt, wordt eerst het positieve bericht en
tot slot ook de huidige IP van de module naar de seriële monitor overgedragen.
Tot slot van de functie worden nog parameters ingesteld waarop ik slechts later
zal ingaan. Tot slot wordt de variabele success teruggegeven die hopelijk de
waarde true heeft bevat.
001
boolean configStation(String vSSID, String vPASSWORT)
002
{
003
boolean success = true;
004
success &= (sendCom("AT+CWMODE=1", "OK"));
005
esp8266.setTimeout(20000);
006
success &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\""
+ String(vPASSWORT) + "\"", "OK"));
007
esp8266.setTimeout(1000);
008
return success;
009
}
De functie configStation() werd in de espConfig()-functie opgeroepen. Hier wordt
het instellen van de WLAN-modus op stationsmodus met het bevel CWMODE en
tenslotte het verbinden met het netwerk via het CWJAP-bevel uitgevoerd. Het kan
echt lang duren tot de verbinding wordt gemaakt, waardoor de time-out hier kort-
stondig tot 20 seconden wordt verhoogd. Als u overigens een voorkeur hebt voor
de duale WLAN-modus, kunt u hier voor CWMODE een 3 invoeren.
001
boolean configAP()
002
{
003
boolean success = true;
004
005
success &= (sendCom("AT+CWMODE=2", "OK"));
006
success &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0",
"OK"));
007
008
return success;
009
}
De functie configAP() wordt in dit voorbeeld niet opgeroepen, maar moet echter
kort behandeld worden. Ze geeft zogezegd het contrastuk van de configStation()-
functie weer aangezien hier de module als Access Point wordt ingesteld. Een
langere time-out is hier niet nodig aangezien de module het CWSAP-bevel duide-
lijk sneller kan verwerken. In latere verzoeken wordt dan in de espConfig()-functie
in de plaats van
configStation() de configAP()-functie opgeroepen.
001
void setup()
002
{
003
// Open serial communications and wait for port to open:
004
Serial.begin(19200);
005
// set the data rate for the SoftwareSerial port
006
esp8266.begin(19200);
007
008
if (!espConfig()) serialDebug();
009
else debug("Config OK");
010
011
if (sendCom("AT+PING=\"www.google.de\"", "OK"))
012
{
013
Serial.println("Ping OK");
014
digitalWrite(13, HIGH);
015
}
016
else
017
{
018
Serial.println("Ping Error");
019
}
020
}
021
022
void loop() // run over and over
023
{
024
//Start serial Debug Mode - Type Commandos over serial Monitor
025
serialDebug();
026
}
De belangrijkste functies die u in bijna elk programma zult vinden, zijn daarmee
behandeld. In de bekende Arduino-functies setup() en loop() worden deze functies
nu gebruikt. Eerst worden beide seriële interfaces met 19200 Baud geïnstalleerd.
Pas dan wordt de functie espConfig() opgeroepen. In geval van fout wordt onmid-
dellijk de serialDebug()-functie gestart. Als alles in orde was, wordt een positief
bericht verzonden. In latere programma's zal de LED aan pin 13, die op het board
met D3 is gemarkeerd, bij een succesvolle configuratie bijkomend branden. Daar-
mee hebt u ook feedback wanneer de module niet aan een pc met seriële monitor
is aangesloten. In dit verzoek is de LED alleszins voor de terugmelding van de
ping-status nodig. De vraag gebeurt ook onmiddellijk in de volgende regel na de
configuratie. Het AT+PING-commando met het Google-adres wordt als parameter
verzonden. U kunt in plaats van dit adres ook een IP-adres in uw lokaal netwerk
opvragen. Indien succesvol, verschijnt er een melding en de voornoemde LED D3
wordt geactiveerd. Als laatste actie springt het programma in de loop-functie die
aan uw zijde de serialDebug()-functie oproept. U kunt dus na het programma meer
bevelen testen en zo bijvoorbeeld meer adressen aanpingen.
1.3 | Een netwerk herkennen
In dit hoofdstuk gaat het onder andere voor het eerst over een kleinere hardware-
opbouw. Doel van het project is een soort alarminstallatie, die reageert wanneer
een bepaald netwerk in uw bereik komt of ingeschakeld wordt.
Er worden slechts twee elementen en een beetje
kabel gebruikt. De precieze opbouw vindt u in de
opbouwafbeeldingen.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x Piezo, draadbrug
Aansluiten van de Piezo-luidsprekers
De brontekst voor dit project is hoofdzakelijk in de volgende functies verschillend
van het vorig verzoek:
001
void findSSID()
002
{
003
esp8266.println("AT+CWLAP");
004
if (esp8266.findUntil(ToFindSSID,"OK")) alarm();
005
else debug("SSID not found!");
006
}
007
008
void alarm()
009
{
010
debug("alarm!");
011
012
digitalWrite(LED_ALARM, HIGH);
013
014
for (int i; i <=30; i++)
015
{
016
tone(PIEZO, 400, 500);
017
delay(500);
018
tone(PIEZO, 800, 500);
019
delay(500);
020
}
021
022
digitalWrite(LED_ALARM, LOW);
023
}
De functie findSSID() wordt ca. elke 30 seconden in de loop-routine opgeroepen
en zoekt dan naar alle netwerken in de omgeving. Wanneer het gezochte netwerk
werd gevonden, wordt de functie alarm() geactiveerd die LED D3 inschakelt en
een geluidssignaal aan de Piezo uitgeeft. In het voorbeeldprogramma wordt na
een netwerk met de SSID NanoESP gezocht, in principe dus naar andere Na-
noESP-netwerken in uw bereik. U kunt echter gewoon bij #define ToFindSSID aan
het begin van het programma een andere SSID invoeren. Daardoor kunt u bij-
voorbeeld controleren hoe ver uw WLAN-netwerk reikt.
UDP EN IP
In dit hoofdstuk gaat het om de algemene datauitwisseling tussen twee systemen
via een WLAN-netwerk. Daarbij zullen wij thema's, zoals IP Ports en het UDP-
protocol behandelen. Daarvoor moeten deze algemene begrippen eerst worden
verklaard.
Wat is een IP-adres?
Een IP-adres werkt als een postadres. Via dit adres kan een computer in een
netwerk eenduidig worden geïdentificeerd en geadresseerd. Een IP-adres op
basis van de gangbare IPv4-standaard ziet er bijvoorbeeld als volgt uit:
192.168.4.1
Het gaat om vier getallen of, juister gezegd, om vier bytes. Dit betekent dus dat de
waarde van een getal maximum 255 kan bedragen. In principe zijn er lokale IP-
adressen, i.e. IP's die bv. aan de computers en apparaten in uw thuisnetwerk
worden verdeeld, en globale IP's.
Lokale IP's worden in regel door uw router verdeeld. Zij beginnen meestal met
192.168. Het daarop volgende getal is van router tot router anders. Wanneer de
NanoESP als Access Point fungeert en een computer zich in uw netwerk aan-
meldt, krijgen de pc's een adres dat met 192.168.4 begint. Zo is onmiddellijk een
subnetwerk aangemaakt. Fritz!Box-routers verdelen in regel lokale IP-adressen
volgens het schema 192.168.178.X. U kunt uw IP vinden door bijvoorbeeld in
Windows in de prompt (onder Start -> Programma's -> Accessoires -> Prompt) het
bevel ipconfig invoeren. Er verschijnt een lange lijst die ook het punt IPv4-adres
met uw lokale IP in het netwerk bevat.
Globale IP's worden in regel door internetproviders toegekend. Daarbij gaat het
bijvoorbeeld om het adres via hetwelk uw router in het wereldwijde netwerk te
bereiken is. De router spant het lokale netwerk op en verdeelt de data aan de
clients. Een mogelijkheid om uw globale IP te vinden is bijvoorbeeld de internetsite
http://www.meine-aktuelle-ip.de/ op te roepen. Op deze pagina worden bo-
vendien meerdere door een webserver te raadplegen data weergegeven. U bent
dus niet zo anoniem op het internet als u eventueel denkt.
Wat is een port?
In analogie met een postadres kan een port zoiets als een huisdeur in een woning
zijn. Een computer met een uniek IP kan via verschillende ports verschillende
diensten ter beschikking stellen. U kunt via het IP de server bereiken, maar via de
port moet u ook de te gebruiken dienst kiezen. Dit kan bv. port 20 zijn voor de
FTP-gegevensoverdracht of port 23 voor een telnet-verbinding. U kunt de port in
regel vrij kiezen, maar er zijn wel gestandaardiseerde ports die de omgang met
webtoepassingen makkelijker maken. Een lijst van de gestandaardiseerde ports
vindt u op
https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports
Wat is UDP?
UDP is de afkorting van User Datagram Protocol. Het gaat hierbij om een mini-
maal, verbindingsloos netwerkprotocol. Dat betekent in principe dat het minimalis-
tischer en eenvoudiger is dan andere internetprotocollen, zoals bv. TCP wat we
later zullen behandelen. De vergelijking is op dit moment nog niet bijzonder een-
voudig, maar u kunt het volgende merken over de eigenschappen van het proto-
col:
U
UDP is in staat om te broadcasten.
U
Er is geen controle van de data op correctheid en er is ook geen
correctie van fouten.
U
Er is dus ook geen garantie dat data met succes is overgedragen.
U
Er is bovendien geen garantie dat data niet onderweg worden
vervalst of door derden afgeluisterd.
U
Er moet niet eerst een verbinding worden gemaakt, maar een snelle
gegevensuitwisseling is mogelijk.
U
Er zijn nauwelijks overdrachtsvertragingsschommelingen.
U
Het formaat is bv. geschikt voor VoIP (Voice over IP telefoneren via
het internet).
Dat zijn de belangrijkste principes met betrekking tot de begrippen van de volgen-
de projecten. Men zou het thema nog een beetje diepgaander kunnen behandelen
en op geschikte plaatsen zullen wij nog meer informatie geven. Echter, eerst naar
het praktische deel.
2.1 | Gegevens tussen board en pc met UDP uitwisselen
In het huidige project worden voor het eerst gegevens tussen board en pc via het
WLAN uitgewisseld. Voorwaarde is dat uw computer over een WLAN-adapter
beschikt. Een programma aan pc-zijde zorgt voor het succesvol ontvangen van de
meldingen. Een bijzondere hardware-opbouw is in dit verzoek niet nodig.
Het programma
Wanneer u het programma P04_UDPBasics.ino op de controller laadt, zal de
Controller als AccessPoint worden geconfigureerd en kunt u een open netwerk
met de naam NanoESP vinden. Voor u zich in elk geval met het netwerk verbindt,
moet u eerst nog een programma voor de pc van het internet downloaden. Bij mijn
verzoeken heb ik het programma Packet Sender van Dan Nagle gebruikt, aange-
zien men ze onder de volgende link kan downloaden:
https://packetsender.com/
Na het laden en installeren van het programma kunt u uw pc met het open net-
werk van de NanoESP kiezen. Let op dat de Firewall het netwerk als thuisnetwerk
herkent, zodat er geen gegevens geblokkeerd worden. Uw computer zou nu IP
192.168.4.2 moeten ontvangen hebben. U kunt dit controleren door het AT-bevel
AT+CWLIF
via de seriële monitor naar de module te zenden. Dit bevel geeft alle met het Ac-
cess Point verbonden computers met IP- en MAC-adres aan.
Nu start u Packet Sender, zet u onder Settings -> Network de UDP Server Port op
90 in en klikt u op de checkbox Enable UDP Server an. In regel moet linksonder
dan UDP 90 staan. Indien niet, moet u de software nog eens opnieuw opstarten.
De juiste instellingen in het programma Packet Sender
Het programma op de computer dient nu als UDP-server, terwijl de controller als
UDP-client is ingesteld. In het UDP-protocol is het onderscheid client/server niet
eenduidig, maar in dit geval betekent het dat u met de controller gegevens naar
uw computer verzendt.
Het bericht
werd met succes overgedragen.
Om gegevens te verzenden , gebruikt u het bevel:
AT+CIPSEND=7
Daarbij staat de 7 voor het aantal te verzenden tekens. Het teken > verschijnt als
teruggavewaarde. Dit betekent dat u nu uw bericht kunt overmaken. Tik Hello in
en bevestig opnieuw met
[Enter]
. Als teruggavewaarde zendt de module SEND
OK en dat hoewel u slechts vijf tekens hebt ingevoerd. Dit komt door het feit dat er
na uw invoer nog Carriage Return en New Line mee verstuurd worden, i.e. twee
tekens meer die u in uw berichtlengte moet incalculeren.
Wanneer u opnieuw naar Packet Sender gaat en daar onder Traffic Log kijkt, kunt
u de ingang van het bericht zien. In het ASCII-aanzicht ziet u zelfs beide meege-
zonden tekens, voorgesteld door \r en \n.
Het bericht werd door Packet Sender ontvangen.
001
boolean configUDP()
002
{
003
boolean success = true;
004
005
success &= (sendCom("AT+CIPMODE=0", "OK"));
006
success &= (sendCom("AT+CIPMUX=0", "OK"));
007
success &=
sendCom("AT+CIPSTART=\"UDP\",\"192.168.4.2\",90", "OK");
//UDP-Server
008
return success;
009
}
In het Arduino-programma is voor de communicatieweg vooral de functie confi-
gUDP() beslissend. Daar worden de voor de overdracht belangrijke instellingen
uitgevoerd. Als eerste wordt de datatransparantiemodus met CIPMODE op 0 ge-
zet. Tenslotte wordt met CIPMUX=0 ingesteld dat er slechts een enkele verbinding
is toegestaan. Het beslissende bevel is CIPSTART. Daarmee wordt een verbin-
ding aangemaakt en wel met IP 192.168.4.2, i.e. uw pc en PORT 90 waaraan het
programma Packet Sender met zijn UDP-server afluistert. Dat zijn eerst alle stap-
pen die nodig zijn om een eerste communicatie op te bouwen.
2.2 | Gegevens verzenden en ontvangen met UDP
In het vorige project werd de UDP-communicatie in een richting, i.e. van het board
naar de pc getest. In dit programma wordt de module zo ingesteld dat een com-
municatie ook in de andere richting mogelijk is, bijna als in een chat.
Het programma
Het programma van vandaag bevat in principe slechts een minimale wijziging die
echter een grote invloed op de communicatie met het UPD-protocol heeft. Wan-
neer u het programma uploadt, wordt opnieuw een Acces Point aangemaakt
waarmee u zich met de pc kunt verbinden. Ook deze keer zult u Packet Sender of
een vergelijkbaar programma nodig hebben. Start het programma en stel dezelfde
instellingen als totnogtoe in (File -> Settings -> Network: Enable UDP Server, Port
90). Vervolgens moet u nog in het hoofdvenster in het veld IP-adres het adres van
de module (192.168.4.1) intikken, de port op 91 instellen en in het verder rechts
staande dropdownmenu het punt UDP selecteren. Als beide instellingen zijn ge-
maakt en de Serial Monitor geopend, kunt u het eerste bericht naar de module
zenden door bv. Hi in het met ASCII gemarkeerde veld te tikken.
Wanneer u nu op Send klikt, verschijnt in de Serial Monitor:
001
+IPD,2:Hi
002
OK
Het Packet Sender heeft met succes »Hi« overgedragen.
Het bericht werd dus ontvangen. U kunt nu ook antwoorden door opnieuw het
CIPSEND-bevel te gebruiken, dus bv.:
001
AT+CIPSEND=7
002
>Hello
Het verschil met het vorige programma ligt uitsluitend in een enkele regel:
success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.4.2
\",90,91", "OK");
Zoals u ziet, werd een tweede port aangegeven. Deze port, in dit geval met het
nummer 91, is de port via dewelke de module van zijn kant naar inkomende data
luistert. Met de bijlagen van deze eenvoudige regel is het mogelijk, ook data naar de
module te verzenden. U kunt overigens ook aan dezelfde port, waarnaar u verzendt,
luisteren. U kunt dus ook voor beide ports het getal 90 invoeren. In theorie is het met
de wijziging ook mogelijk dat de module zijn eigen data ontvangt.
2.3 | Een LED met UDP schakelen
In het programma P06_UDPLED.ino gaat het nu eindelijk om het besturen van
hardware via het UDP-protocol. Met dit programma is het mogelijk om een LED met
eenvoudige bevelen in en uit te schakelen. Bovendien wordt een bijkomende instel-
ling aan de UDP-communicatie uitgevoerd die het toelaat dat de hardware door
meerdere computers kan worden gecontroleerd. Daarvoor hebt u een schakeling
nodig, zoals getoond in de onderstaande afbeelding. De LED lijkt erg op een ander
element, de fototransistor. U kunt beide elementen van elkaar onderscheiden door
de kop van het element van bovenaf te bekijken.
De binnenkant van de LED heeft een groot wit vlak.
Het Packet Sender heeft met succes »Hi« overgedragen.
Het programma
Terwijl de vorige voorbeeldprogramma's veel invoer van de gebruiker via de serië-
le monitor vereisten, moet dit programma autonoom werken. Toch wordt voor
debug-doeleinden via de seriële monitor verder informatie uitgegeven.
De controller wacht nu op de door de WLAN-module ontvangen gegevens die via
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x LED (rood), 1 x weer-
stand 1 kOhm (bruin-zwart-rood), draadbrug
de +IPD-melding worden aangekondigd. Legitieme bevelen die u via Packet Sen-
der kunt verzenden, luiden led1 en led0. De controller interpreteert ze en schakelt
dienovereenkomstig de LED in of uit. Een terugmelding naar de zender wordt
eveneens overgedragen. Als een ander bevel wordt verzonden, verschijnt in de
Serial Monitor de melding "Wrong UDP Command". Hetzelfde bericht wordt ook
via het netwerk aan de zender overgedragen. In de brontekst beschouwen wij
eerst opnieuw een regel in de functie configUDP():
success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.4.255
\",90,91", "OK");
Dit keer is het IP namelijk gewijzigd. Dit IP kan grappig lijken want het gaat niet om
het IP van uw computer. Hoe kunnen dan de gegevens überhaupt aankomen? Dat
deze IP werkt, ligt aan het feit dat het om een heel bijzondere IP gaat, namelijk
een zogenaamde Broadcast-IP. Broadcast betekent "uitzenden", bv. van radiouit-
zendingen. Net zoals bij radiouitzendingen kunnen deze Broadcast-gegevens door
meerdere deelnemers worden ontvangen, in dit geval door alle deelnemers die
zich in hetzelfde subnet bevinden. Het adres 255 op het einde van het IP staat
altijd voor een broadcast-adres. U kunt nu bv. op een bijkomende computer het
programma Packet Sender starten en alle verzonden berichten afluisteren en ook
bevelen verzenden. De communicatie vindt dus niet meer alleen tussen twee
deelnemers plaats.
001
void loop() {
002
if (esp8266.available())
003
{
004
if (esp8266.find("+IPD,"))
005
{
006
if (esp8266.find("led")) {
007
int setLed = esp8266.parseInt();
008
digitalWrite(LED, setLed);
009
010
debug("LED=" + String(setLed));
011
if (sendCom("AT+CIPSEND=7", ">"))
012
{
013
sendCom("LED=" + String(setLed), "OK");
014
}
015
}
016
017
else {
018
debug("Wrong UDP Command");
019
if (sendCom("AT+CIPSEND=19", ">"))
020
{
021
sendCom("Wrong UDP Command", "OK");
022
}
023
024
}
025
}
026
}
027
}
Het analyseren van de inkomende bevelen gebeurt in de loop-routine, die perma-
nent wordt doorlopen. Als er data van de module is aangekomen
(esp8266.available()), worden ze geanalyseerd op de aanwezigheid van »+IPD,«.
Als bovendien het bevel led wordt gevonden, wordt via het bevel parseInt() auto-
matisch het volgende getal in de variabele setLed opgeslagen. Dit moet dankzij
onze definitie van de bevelen, ofwel 1 of 0 zijn en zo de LED high of low schake-
len. Als volgende wordt via de debug-functie en het CIPSEND-bevel een bevesti-
ging naar de computer overgedragen. Voor het geval dat het bevel led geen deel
uitmaakte van de door de module ontvangen data, informeert een foutmelding
over een foutief bevel. De eerste aansturing via het netwerk is daarmee volledig.
2.4 | Natwerkschakelaar
In het vorige programma werden eerste commando's door de controller geanaly-
seerd en een LED overeenkomstig geschakeld.
Het volgende programma omvat deze functie, maar kan bijkomend zelfstandig een
commando naar het netwerk zenden. Verbind een knop met de controller, zoals
weergegeven op de opbouwafbeelding.
De schakelaar plaatsbesparend aan D8 aangesloten
Het programma
Het programma analyseert verder de aankomende bevelen. Bovendien wordt de
button echter voortdurend afgetast. Als hij door de gebruiker wordt geactiveerd,
zendt de controller de tekst
Button=1
naar het netwerk. Alle met de module verbonden apparaten met een UDP-server
aan port 90 kunnen het bevel ontvangen. U kunt dit met de Packet Sender op-
nieuw controleren. Wanneer u over twee controllers beschikt, kunt u aan de twee-
de controller dezelfde schakeling opbouwen en met een lichte variatie het pro-
gramma op beide controllers uploaden. Wanneer u namelijk in plaats van het be-
vel Button=1 het bevel led=1 invoert, kunnen de LED's telkens de andere control-
ler via een druk op de knop besturen. Het kan alleszins ook gebeuren dat u de
LED van de eigen controller onmiddellijk meestuurt.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x LED (rood), 1 x knop,
1 x weerstand 1 kOhm (bruin-zwart-rood), draadbrug
Het verloop in het Packet Sender
De wijzigingen in het programma zijn vooral in de loop-routine te vinden. Een een-
voudige if-vraag controleert, of de schakelaar wordt ingedrukt. Als dit het geval is,
geeft de controller de melding Button=1 aan het netwerk door. Bovendien is er een
debug-melding. De daarop volgende while-lus heeft tot gevolg dat niet onmiddellijk
een hele vloed aan commando's wordt verzonden, zolang u de schakelaar inge-
drukt houdt. U moet de knop dus eerst loslaten voor het programma verder gaat.
001
if (!digitalRead(SWITCH))
002
{
003
debug("Button=1");
004
sendUDP("Button=1");
005
while (!digitalRead(SWITCH)) {}
006
}
Bij een huisautomatiseringsproject zou een server bijvoorbeeld de statusmelding
van een bewegingsmelder ontvangen en dan het bevel voor het inschakelen van
het licht naar een andere controller verzenden. Zo kan een heel netwerk van sen-
soren en actoren worden opgebouwd.
2.5 | Analoge sensor
In het laatste project werd met een drukknopschakelaar de eenvoudigste vorm van
een sensor behandeld. Dit keer moet een potentiometer als analoge sensor wor-
den gebruikt om permanent meetwaarden naar het netwerk te zenden. Daarvoor
wordt de meegeleverde potentiometer met 10 kΩ
gebruikt. De opbouw wordt in het onderste afbeel-
ding weergegeven.
De opbouw met potentiometer aan A6
Het programma
Naast de analoge sensor is er nog een bijkomende wijziging in het programma. Dit
keer moet de controller niet langer in de Acces Point-modus worden gebruikt,
maar zich met uw thuisnetwerk verbinden. Uw stationsgegevens kunt u ook dit
keer gewoon bovenaan in het programma invoeren.
Na het uploaden kan het een tijdje duren tot de verbinding met het netwerk wordt
gemaakt. Als dit succesvol was, begint LED D3 die vast op het board aangebracht
is, te branden. Dit is het teken dat de controller gereed is. Zolang de seriële moni-
tor actief is, zult u weliswaar ook een overeenkomstige melding zien, maar bij
latere verzoeken wilt u het board eventueel zelfstandig inzetten en dan kan deze
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x LED, 1 x weerstand 1
kOhm (bruin-zwart-rood), 1 x potentiometer, draadbrug
feedback zeer nuttig zijn. Via de seriële monitor krijgt u ook informatie welk IP het
board van de router kreeg toegewezen. Dit IP is belangrijk aangezien het u het
board later wilt adresseren.
Het communiceren met het board werkt ook op gelijkaardige manier als in de vori-
ge verzoeken. Slechts het IP van de module en uw computer zullen gewijzigd zijn
aangezien beide apparaten nu een IP van de router toegewezen krijgen. Packet
Sender ontvangt na het starten eerst nog geen meetresultaten. U moet eerst een
bericht, bv. het commando led=1, naar de module zenden. Daartoe geeft u in het
Packet Sender het nieuwe IP van de module aan dat u via de seriële monitor kunt
vinden. Na het bevel voert u ca. eenmaal per seconde nieuwe meetdata in.
De meetdata worden door Packet Sender ontvangen
Er is in dit programma een bijkomende wijziging in het CIPSTART-bevel. Ten
eerste werd het broadcast-adres uitgebreid en wel omdat niet kan worden voor-
speld, welk subnet uw router opspant. De tweede wijziging ligt in het toevoegen
van een parameter, hier van de tweede. De nieuwe parameter laat toe dat het
doeladres van het
CIPSEND-bevel kan veranderen. De module luistert dus eerst in de hele ruimte
die met 192.168. begint en van zodra een bevel wordt ontvangen, stelt de module
zich op het nieuwe IP in.
success &= sendCom("AT+CIPSTART=\"UDP\",\"
192.168.255.255\",90,91,2", "OK");
Voor deze parameter zijn er de volgende mogelijkheden:
1
Modus 0: Dit betekent dat het IP en de port niet wijzigen. Dit is ook de default-
instelling, wat duidelijk wordt wanneer u de andere modi beschouwt.
2
Modus 1: De instellingen veranderen een maal. Dit betekent het volgende: Wan-
neer de module met het net gebruikte broadcast-adres start en er dan door een pc
iets wordt ontvangen, stelt de module zich op het nieuwe adres van de pc in. Met
andere woorden wordt dan het doel-IP dat u hebt ingevoerd, overbodig en wordt in
de plaats naar het nieuwe adres verzonden. Dit adres blijft ook bestaan wanneer
de module data van een andere pc gestuurd krijgt.
3
Modus 2: De instellingen wijzigen bij elke ontvangst van een nieuw apparaat. Dit
betekent dat het IP toch op een nieuwe pc kan worden ingesteld, ook wanneer het
reeds eenmaal werd gewijzigd.
Dit is ook de reden waarom u eerst een bevel naar de module moet verzenden
voor u data kunt ontvangen. U moet dan ook vanaf deze computer data kunnen
ontvangen. Tenzij u vanaf de nieuwe pc opnieuw een bericht naar de module
verzendt.
001
boolean sendUDP(String Msg)
002
{
003
boolean success = true;
004
005
success &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2),
006
if (success)
007
{
008
success &= sendCom(Msg, "OK");
009
}
010
return success;
011
}
Het verzenden van de analoge waarde gebeurt in de loop-routine. Daartoe wordt
de functie sendUDP() gebruikt die de bekende functies makkelijker toegankelijk
maakt. Er moet niet absoluut een delay tussen het zenden van bevelen staan
aangezien de overdracht zekere tijd in beslag neemt. Alleszins is de frequentie
waarmee de nieuwe data overgedragen worden, zo hoog dat de pc bijna met be-
richten wordt gebombardeerd.
TCP-CLIENT
In het vorige hoofdstuk ging het om het UDP-protocol waarmee gegevens op een-
voudige wijze verzonden en ontvangen kunnen worden. Met het protocol kan
reeds een hele reeks aan toepassingen worden gerealiseerd. In dit hoofdstuk
zullen wij ons met het TCP-protocol (Transmission Control Protocol) bezig hou-
den. De module zal in dit hoofdstuk de rol van een TCP-client aannemen. Dit is de
rol die uw pc thuis ten opzichte van een webserver aanneemt. Het verschil tussen
TCP en UDP kan grosso modo met de volgende trefwoorden worden samengevat:
U
De verbinding bestaat uitsluitend tussen twee apparaten.
U
De verzonden pakketten worden op overdrachtsfouten gecontroleerd
en evt. gecorrigeerd.
U
TCP wordt vooral in het internet gebruikt.
U
Het protocol is een beetje langzamer dan UDP, maar ook veiliger.
Het protocol wordt dus door uw pc en een webserver gebruikt waarvan u een
website wilt laden om een verbinding tussen beide deelnemers te maken. De ei-
genlijke website-inhouden worden vervolgens met het HTTP-formaat (HyperText
Transfer Protocol) overgedragen. Hoe dat precies werkt, ziet u in het volgende
hoofdstuk.
3.1 | Een browser
Dit verzoek gebruikt opnieuw de bestaande opbouw. Het gaat om het kennisma-
ken met de basisstructuren van de TCP-communicatie met behulp van een seriële
monitor.
Het programma
Het programma komt in haar werkwijze overeen met het SoftwareSerial-
programma van het eerste verzoek, maar maakt in elk geval onder andere de
WLAN-verbinding bij de start zelfstandig aan. Zo spaart u een hoop schrijfwerk en
kunt u sneller starten. Vergeet niet de gegevens van uw thuisnetwerk in het pro-
gramma in te voeren. Tik dan in de seriële monitor, de volgende bevelregel in:
AT+CIPSTART="TCP","www.example.com",80
Met dit commando stelt u een TCP-verbinding naar website www.example.com
in. Port 80 is de standaardport voor HTTP-vragen. Na de bevestiging van de ver-
binding met OK kunt u het volgende bevel intikken, dat u reeds kent:
AT+CIPSEND=40
U wilt nu namelijk een bericht via de net aangemaakte verbinding verzenden.
Wanneer u met > daartoe wordt aangemoedigd. Een tekst in te geven, tikt u eerst
GET / HTTP/1.1
in en druk vervolgens op
[Enter]
.
[Enter]
verschijnt niet in de Serial Monitor,
maar de module heeft het ontvangen. Daarna gaat het bericht verder met
Host:www.example.com
gevolgd door tweemaal
[Enter]
. U moet de invoer in elk geval zeer snel na elkaar
verzenden. Het best bereidt u een tekstdocument voor van waaruit u de regels
snel kunt kopiëren. Er komt opnieuw een langere tekst. Het eerste deel is het
antwoord van de server en bevat wat informatie voor de browser. De tekst na
<!doctype.html> is de website die u ook ziet wanneer u de pagina
www.example.com direct oproept, hier alleszins in zuivere tekstvorm. Een brow-
ser zou deze teksten interpreteren en in een voor ons traditionele vorm weerge-
ven.
Uittreksel uit het antwoord van de webserver
In dit voorbeeld ziet u de basis van het HTTP-formaat. Een client maakt een ver-
binding met een webserver. Dat u het IP niet moet intikken, maar de Domain-
naam in tekstvorm kunt gebruiken, ligt aan het zogenaamde DNS (Domain Name
System). Het stuurt de vraag aan het moeilijk te merken IP door. Als de client
verbonden is, zendt de browser een Get-Request-vraag. In deze vraag moet ten-
minste de gevraagde pagina of het gevraagde ressource (in dit geval de hoofdpa-
gina), het gebruikte protocol (http 1.1) en de opgevraagde host
(www.example.com) worden aangegeven. Het aanduiden van de host is belangrijk
aangezien zich meerdere internetadressen op een server kunnen bevinden en zo
achter een IP kunnen schuilen. Wanneer u een andere pagina dan de hoofdpagi-
na wilt opvragen, schrijft u in de plaats van / bv. /example.html. Naast de gevraag-
de subpagina verzendt uw browser overigens heel wat meer informatie dan
slechts de gevraagde ressource. Daarnaast werden gegevens, zoals bv. de ge-
bruikte browser, besturingssysteem, beeldschermresolutie en nog enkele andere
zaken overgedragen. Daardoor kan de server de inhoud aanpassen. Dan volgt het
antwoord van de server dat er aanvankelijk net zo complex uitziet. Het header-
gedeelte van het antwoord bevat veel bijkomende informatie voor uw browser. Pas
aan het einde volgt de eigenlijke inhoud van de website.
3.2 | Een internetklok
Dit project gebruikt de kennis uit de vorige hoofdstukken om de NanoESP zelf-
standig informatie van een website te laten halen. Concreet laat het programma
de huidige tijd van een speciaal daarvoor geconcipieerde pagina en stelt zo de via
de library gerealiseerde interne klok van de controller om een nauwkeurige tijds-
besteding toe te laten. De tijd wordt via de seriële monitor uitgegeven. Voor de
opbouw hebt u alleen het board nodig.
Het programma
Terwijl het vorige programma van gisteren nog grotendeels met de hand moest
worden bediend, werkt dit verregaand autonoom. Volledig zelfstandig verbindt de
controller zich met de website.
http://chronic.herokuapp.com/
Via de URL kunnen verschillende tijdsystemen en tijdzones worden opgeroepen.
De huidige, in België en Nederland geldige tijd, wordt door de URL
http://chronic.herokuapp.com/utc/in-one-hour
opgevraagd. Daarom staat in de oproep van de later beschreven functie
getTime() als tweede parameter utc/in-one-hour. Uitgaand van de UTC (gecoördi-
neerde wereldtijd) moet u in de zomer de oproep in utc/in-two-hourswijzigen. Vol-
gens hetzelfde systeem kunt u ook alle andere tijdzones behandelen.
De bepaalde tijd wordt nu aan de Time-Library van Michael Margolis doorgeven
(bron: http://www.pjrc.com/teensy/td_libs_Time.html). Omwille van praktische
redenen bevat de Sketch-map een kopie van de door mij gebruikte Time-Library-
versie. Deze moet in de libraries-map van uw Sketchbook-map worden gekopi-
eerd. In de achtergrond wordt permanent de nieuwe tijd berekend en elke seconde
in de terminal uitgegeven. U kunt op een eenvoudige manier een wekker of ande-
re tijdgestuurde toepassing programmeren. Opdat het oproepen van een tijd kan
werken, wordt een nieuwe functie gebruikt:
001
boolean getTime(String Host, String Subpage)
002
{
003
boolean success = true;
004
int xyear, xmonth, xday, xhour, xminute, xsecond; //lokal
variables
005
006
success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host +
"\",80", "OK");
007
String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" +
Host + "\r\n";
008
success &= sendCom("AT+CIPSEND=" +
String(getRequest.length() + 2), ">");
009
010
esp8266.println(getRequest);
011
012
if (esp8266.find("+IPD"))
013
{
014
if (esp8266.find("\r\n\r\n"))
015
{
016
xyear = esp8266.parseInt();
017
xmonth = esp8266.parseInt();
018
xday = esp8266.parseInt();
019
xhour = esp8266.parseInt();
020
xminute = esp8266.parseInt();
021
xsecond = esp8266.parseInt();
022
023
if (xday < 0) xday *= -1; //Because of date seperator -
parseInt detects negativ integer
024
if (xmonth < 0) xmonth *= -1; //Because of date seperator -
parseInt detects negativ integer
025
026
027
setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
028
sendCom("AT+CIPCLOSE", "OK");
029
return true;
030
}
031
else return false;
032
}
033
else return false;
034
}
Aan deze functie worden parameters voor het hostadres en subadres toegekend.
Daaruit wordt tenslotte de Get-Request-vraag aangemaakt en na het aanmaken
van een verbinding, aan de TCP-server van de website overgedragen. Het ant-
woord van de server moet nu geanalyseerd worden. Daartoe wordt het gehele
Request-Header-gedeelte overgelaten door naar \r\n\r\n te zoeken, wat niets an-
ders betekent dan dat het na een dubbele Carriage Return en New Line verder
gaat. De volgende getallen komen met de gezochte datum en tijd overeen die
door een reeks van parseInt()-functie-oproepen in tussenvariabelen worden opge-
slagen. Een bijzonderheid bestaat in de datum, want hier worden de afzonderlijke
waarden met een streepje gescheiden, wat de parseInt()-functie als een negatief
getal interpreteert. Daarom worden de waarden gewoon met -1 vermenigvuldigd.
Tenslotte wordt de tijd met de setTime()-functie ingesteld en door de loop-routine
eenmaal per seconde uitgegeven. De klok is nu volledig functiegereed.
3.3 | Temperatuurweergave
Bij dit project gaat het om de weergave van de actuele temperatuur en het alge-
mene weer. Ook dit keer worden de waarden via de seriële monitor uitgegeven.
Bovendien is er een intuïtieve uitvoer met de
RGB-LED. Men kan dus met een simpele blik
inschatten of het zinvol is om een warme jas mee
te nemen.
Belangrijk bij de opbouw is om de RGB-LED correct aan te sluiten. RGB staat voor
Red, Green, Blue aangezien de LED eigenlijk uit meerdere LED's met een ge-
meenschappelijke kathodenaansluiting bestaat. Door een combinatie van de ver-
schillende kleuren met verschillende helderheden is het mogelijk om bijna elke
kleur weer te geven. De LED moet, zoals getoond in de afbeelding, met voorweer-
standen aan PWM-uitgangen D3, D5, D6 van de controller worden aangesloten.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x RGB-LED (rood), 3 x
weerstand 1 kOhm (bruin-zwart-rood), draadbrug
Aansluiting van de RGB-LED aan de pins D3, D5 en D6
Het programma
In de sketch gaat het opnieuw om de vraag van een internetpagina, maar dit keer
gaat het om een speciaal voor het programma geprogrammeerde pagina die ge-
gevens van de weersite
http://www.openweathermap.com/
onttrekt. Op deze pagina kan men door variatie van de URL, informatie met be-
trekking tot het weer in zijn stad bekomen. De stad, die u wilt bevragen, kunt u in
de brontekst gewoon na City invoeren. Als voorbeeld gebruik ik mijn thuisstad
Essen: www.temp.fkainka.de/?city=Essen
Het programma leest nu uit deze pagina de temperatuur en geeft het resultaat via
de RGB-LED in kleur weer. Tegelijk wordt de waarde via de seriële monitor weer-
gegeven. Het in het voorbeeldprogramma gebruikte temperatuurbereik voor de
weergave aan de LED bedraagt 20 °C tot +40 °C.
In principe werkt het programma bijna zoals het vorige, met slechts een paar klei-
ne bijzonderheden. De functie getTemp() is dit keer voor de berekening van de
data verantwoordelijk en geeft de huidige temperatuur weer, op dezelfde manier
als de tijdfunctie in het vorige programma.
001
void rgbTemp(int val)
002
{
003
int green, blue, red ;
004
005
if (val <= 10 & val >= -20)
006
blue = map(val, -20, 10, 255, 0);
007
else blue = 0;
008
009
if (val >= 10 & val <= 40)
010
green = map(val, 10, 40, 255, 0);
011
else if (val >= -20 & val < 10) green = map(val, -20, 10, 0, 255);
012
else green = 0;
013
014
if (val > 10 & val <= 40) red = map(val, 10, 40, 0, 255);
015
else red = 0;
016
017
analogWrite(RED, red);
018
analogWrite(GREEN, green);
019
analogWrite(BLUE, blue);
020
}
De aanpassing van de LED-helderheid wordt in de functie rgbTemp() uitgevoerd.
Met behulp van het map-bevel worden de waarden in passende Byte-waarden (0-
255) omgezet en naar de LED uitgegeven. Daarbij staat blauw voor bijzonder
koude temperaturen en heeft een invloed in het bereik van 20 °C tot +10 °C.
Groen meet in het hele temperatuurbereik mee, maar bereikt een maximum bij de
waarde 10 °C. Rood vindt men pas vanaf een waarde van +10 °C en heeft een
maximum bij +40 °C. Daardoor is een intuïtieve kleurcodering gecreëerd aan de
hand waarvan men de huidige temperatuur kan inschatten, bovenop de nauwkeu-
riger weergave in de seriële monitor.
TCP-SERVER
Nadat u in het vorige hoofdstuk iets over het gebruik van de module als TCP-client
hebt geleerd, moet de module nu als eigen TCP-server handelen. Praktisch ge-
zien is er ook daarvoor een eenvoudig AT-bevel waarmee u deze complexe ser-
vertoepassing kunt starten. De module gedraagt zich dan als een TCP-server uit
het internet, behalve dan dat u het verzenden van de website zelf moet program-
meren.
4.1 | TCP-webserver
De eerste verzoeken inzake TCP-webserver gebeuren zonder bijkomende hard-
ware-opbouw. Eerst probeert u de belangrijkste bevelen gewoon via de seriële
modus.
Het programma
Voer de WLAN-gegevens in en laad het programma op uw board op. Start dan de
monitor. Het kan opnieuw een paar seconden duren tot de melding verschijnt dat
het board verbonden is. Wanneer de melding dat de verbinding geslaagd is, ver-
schijnt en het IP van de module wordt weergegeven, kunt u in de Serial Monitor
met het eerste bevel beginnen:
AT+CIPMUX=1
Met dit bevel laat u meerdere verbindingen naar de module toe. U kunt toegang
krijgen tot meerdere computers op de webserver. Met het volgende bevel start u
de webserver:
AT+CIPSERVER=1,80
Parameter 1 betekent dat de server wordt gestart. Met 0 beëindigt u een server
opnieuw. Het getal 80 staat voor de port waaronder de server te bereiken is. Door
de browser verzoden HTTP-vragen worden over het algemeen via port 80 verzon-
den.
U kunt nu een browser naar keuze openen en in de adressenlijst het IP van de
module intikken en met
[Enter]
bevestigen. In de browser verschijnt eerst een
laadbericht, maar in de Serial Monitor kunt u een wijziging zien. U ziet een Re-
quest-vraag gelijkaardig aan deze die u reeds manueel hebt verzonden.
De Browser-
vraag
De browser op een antwoord en geeft zolang een laadteken weer tot de verbin-
ding wegens time-out wordt verbroken. U kunt de browser met een variante van
een bekend bevel een bericht sturen:
AT+CIPSEND=0,7
De parameter 0 geeft hier de clnt aan, naar wie het bericht moet worden verzon-
den. Dat is nodig omdat er meerdere verbindingen zijn toegelaten en daarom ook
meerdere clients kunnen zijn verbonden. De tweede parameter, hier 7 geeft op-
nieuw het aantal te verzenden tekens weer. > verschijnt en u kunt een eenvoudig
Hallo
intikken en met
[Enter]
verzenden. In uw browser zal er echter eerst niets veran-
deren aangezien u de verbinding eerst moet sluiten. Gebruik daartoe het bevel:
AT+CIPCLOSE=0
Nu kunt u in de browser een Hallo zien. Daarmee hebt u een eerste webserver-
toepassing gerealiseerd.
Deze eerste test toont veel over de precieze processen van de communicatie in
het internet. De weergave van de '"Hallo" in de browser is daarbij nog eenvoudig
aangezien een simpele tekst in de plaats van een complexe HTML-pagina werd
verzonden. Voor een echte HTML-pagina moet u manueel een hele header zowel
voor het Get-Request als voor de HTML-tekst schrijven. Deze moeite wil ik u in de
eerste test in elk geval besparen.
4.2 | Autonome webserver
De resultaten van vorige verzoek worden nu opnieuw in een autonoom program-
ma gebruikt. Het nieuwe programma verzendt echter niet alleen een gewone web-
site naar de browser, maar maakt het bovendien ook mogelijk om een LED aan te
sturen. Op het opbouwscherm ziet u bovendien hoe u een externe stroomverzor-
ging aan het board kunt aansluiten. Als alternatief
voor dit type stroomverzorging biedt zich ook een
Powerbank (een externe accu, meestal voor
smartphones) aan die het board gewoon via de
micro-USB-aansluiting van stroom kan voorzien.
Zo sluit u een batterij aan de verzoeksopbouw aan.
Het programma
Het programma zendt een ietwat complexere pagina dan het vorige verzoek. Bo-
vendien kunt u de LED aan pin 9 schakelen door deze achter het IP van de modu-
le /LED in te voeren. De huidige toestand van de LED wordt dan omgekeerd, dus
de toestand wordt elke keer omgeschakeld (toggelen).
Voer uw WLAN-gegevens in en laad dan het programma op. Het IP van het board
wordt in de seriële motor weergegeven. Dan kunt u de browser openen en het IP
van het board oproepen. De website heeft nu een titel een een beetje meer tekst.
De tekst wijst er ook op hoe u de LED kunt sturen. Zo hebt u dus een eerste volle-
dig autonome webserver.
001
void loop() {
002
if (esp8266.available()) // check if the esp is sending a message
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x 9-V-clip, 1 x LED
(rood), 1 x weerstand 1 kOhm (bruin-zwart-rood), draad-
brug, 1 x 9-V-batterij (niet in het leerpakket inbegrepen)
003
{
004
if (esp8266.find("+IPD,"))
005
{
006
debug("Incomming Request");
007
int connectionId = esp8266.parseInt();
008
009
if (esp8266.findUntil("LED","\n")) digitalWrite(LED, !digitalRead(LED));
010
011
String webpage = "<h1>Hello World!</h1>Open [IP]/LED to Toggle LED on D9";
012
013
if (sendCom("AT+CIPSEND=" + String(connectionId) + "," + String(webpage.length()),
">"))
014
{
015
sendCom(webpage,"SEND OK");
016
sendCom("AT+CIPCLOSE=" + String(connectionId),"OK");
017
debug("Send and Close");
018
}
019
}
020
}
021
}
Om de webserver te starten, is opnieuw een eenvoudige functie beschikbaar; ze
heeft de naam configTCPServer(). Daarachter schuilt niet anders dan wat u eerder
manueel hebt ingetikt. In de loop-routine wordt gewacht op inkomende data. Wan-
neer deze gegevens "LED" bevatten, wordt de LED getoggeld. Daarbij maakt de
routine geen onderscheid, waar precies "LED" staat. Daarom is het bevel in de
overgedragen URL legitiem. De website zelf bevindt zich in dit verzoek in de web-
page-variabele en bevat de volgende tekst:
001
<h1>Hello World!</h1>
002
Open [IP]/LED to Toggle LED on D9
Daarbij moet <h1> een aanwijzing aan de browser, de tekst tot </h1> als kopregel
van type 1 worden weergegeven. Het gaat nog niet om de juiste HTML-code,
maar veel meer om een eenvoudige vorm van tekstweergave. De lengte van de
website wordt met webpage.length() (een functie van de string-klasse) aan het
CIPSEND-bevel doorgegeven en de pagina tenslotte overgedragen.
4.3 | Website met buttons
Bij dit verzoek is de weergave van de website nog gedetailleerder. Bovendien zijn
er nu ook stuurelementen, via dewelke de LED duidelijk makkelijker kan worden
gestuurd. De opbouw van dit verzoek onderscheidt zich niet van deze van het
vorige: een LED op pin D9 die zich via de module laat besturen. Daarvoor bevat
de brontekst enkele nieuwigheden.
Het programma
Na het uploaden van het programma kunt u de website van de controller opnieuw
via een browser oproepen. Daarvoor moet u alleen het IP van de module intikken
die bij de start via de seriële monitor werd uitgegeven. De website zelf wordt in dit
project alleszins een beetje anders opgeslagen dan in de vorige.
De website van de webserver
Terwijl voorheen de eenvoudig gehouden website in de brontekst was inbegrepen,
wordt deze keer de pagina in een zogenaamde progmen-variabele (Program Me-
mory) opgeslagen. Het gebruik van dit opslagtype ontlast de SRAM van het board,
dat anders voor het opslaan van variabelen verantwoordelijk is. Het SRAM bevat
slechts 2 kB en is door het gebruik van de strings al zeer belast. Door de prog-
mem-functie wordt nu de inhoud van de website in het programmageheugen on-
dergebracht dat met rond 32 kB duidelijk groter is. De toegang tot de data is daar-
door alleszins ook een beetje complexer.
001
const char site[] PROGMEM = {
002
"<HTML><HEAD>\n<meta name=\"viewport\" content=\"width=device-width, initial-
scale=2.0,
003
(…)
004
};
In dit hoofdstuk ziet men hoe de website in de progmem-variabele wordt opgesla-
gen. Het gaat om een langer HTML-document in een C-vriendelijk formaat. Het
formaat kenmerkt zich onder andere daardoor dat aanhalingstekens in de vorm \"
en nieuwe regels door \n worden weergegeven. U kent dit vermoedelijk reeds van
andere projecten waarin strings voorkomen. Een voorbeeldweergave van de web-
site in het HTML-formaat vindt u overigens ook in de programmamap.
001
String createWebsite()
002
{
003
String xBuffer;
004
005
for (int i = 0; i <= sizeof(site); i++)
006
{
007
char myChar = pgm_read_byte_near(site + i);
008
xBuffer += myChar;
009
}
010
011
return xBuffer;
012
}
In de functie createWebsite() wordt de inhoud van de progmem-variabele opgela-
den en als string teruggegeven. Men kan goed zien hoe de progmem-variabele
opnieuw uit het programmageheugen wordt opgeladen.
001
boolean sendWebsite(int connectionId, String webpage)
002
{
003
boolean success = true;
004
005
if (sendCom("AT+CIPSEND=" + String(connectionId) + "," +
String(webpage.length()), ">"))
006
{
007
esp8266.print(webpage);
008
esp8266.find("SEND OK");
009
success &= sendCom("AT+CIPCLOSE=" + String(connectionId),
"OK");
010
}
011
else
012
{
013
success = false;
014
}
015
return success;
016
}
In de loop-routine wordt nu gewacht op een Request-vraag. Als deze komt, wordt
de functie sendWebsite() opgeroepen die als parameter het resultaat aan de crea-
teWebsite()-functie wordt doorgegeven. Daaruit kan dan de lengte van de tekst
door de length()-
functie worden bepaald Na het overdragen van de website wordt de verbinding
tenslotte met het AT+CIPCLOSE-bevel opnieuw gesloten. Het schakelen van de
LED is eveneens deel van de loop-routine en onderscheidt zich lichtjes van het
voorgaande schema. Hoe precies, wordt in de volgende HTML-snelcursus duide-
lijk.
4.4 | Insteekmodule: HTML-snelcursus
In dit hoofdstuk zal ik een snelcursus in HTML geven. De nadruk zal daarbij speci-
aal worden gelegd op het aanmaken van websites voor het besturen van de Na-
noESP. Deel van de cursus zijn de basisstructuren van een HTML-document, het
aanmaken van invoer- en uitvoerelementen en tenslotte het inbinden van enkele
websites in het Arduino-programma.
Een HTML-bestand wordt altijd door <HTML> aan het begin van het document
gekenmerkt. Het einde van het document moet door </HTML> worden geken-
merkt. In regel worden begin en einde van een deel of element in vergelijkbare
vorm weergegeven, zoals men ook bij de header kan zien. In de header staan
belangrijke informatie en vormen, zoals in dit geval bv. de titel van de website die
bovenaan in de browserlijst moet worden weergegeven. In dit geval bevindt zich
bijkomende informatie in de header, die niet bij de basis van HTML behoort, maar
de weergave op mobiele toestellen verbetert (<meta name ="viewport" …). U kunt
deze regels op elk moment in uw HTML-website overnemen.
001
<HTML><HEAD>
002
<meta name="viewport" content="width=device-width, initial-scale=2.0, user-
scalable=yes">
003
<title>
004
Switch LED
005
</title>
006
</HEAD>
Na het HEAD volgt het BODY. Dit bevat de inhoud van de website. In het startbe-
reik van het BODY worden bijkomend parameters, zoals achtergrond- en tekst-
kleur vastgelegd. Deze kunt u natuurlijk op elk moment naar eigen wens aanpas-
sen. Dan volgt het vastleggen van een lettertype en tekengrootte in het FONT-
element. Deze gelden hier echter alleen voor de tekst Switch LED, die daardoor
bijzonder groot verschijnt, aangezien daarna het FONT-element door </FONT>
opnieuw wordt afgesloten.
001
<BODY bgcolor="#FFFF99" text="#000000">
002
<FONT size="6" FACE="Verdana">
003
Switch LED
004
</FONT>
Het volgende deel gedraagt zich net zoals twee nieuwe elementen, namelijk
<HR>, wat een horizontale lijn op de website aanbrengt en <BR>, wat zorgt voor
een sprong naar de volgende regel.
001
<HR>
002
<BR>
003
<FONT size="3" FACE="Verdana">
004
Switch the LED <BR>
005
on D9 ON and OFF
006
<BR>
007
<BR>
Alle totnogtoe vooringestelde elementen waren zuivere vormfactoren, die dienen
voor de vormgeving van de website. Als volgende komt alleszins het belangrijke
form-element waarmee het schakelen van een LED wordt gerealiseerd.
001
<form method="GET">
002
<button type="submit" name="led" value="1">LED ON</button>
003
<button type="submit" name="led" value="0">LED OFF</button>
004
</form>
Het form-element is, zoals de naam doet vermoeden, uitgedacht voor het opmaken
van formuleren in het internet. Daarbij kan het gaan om registratieformulieren voor een
website of voor enquêtes of diens meer. De overdracht van de door de gebruiker in-
gevoerde data kan op een heel verschillende manier gebeuren. In dit element gebrui-
ken wij de GET-methode, waarbij de ingevoerde gegevens gewoon met behulp van de
URL aan de webserver wordt overgedragen. In dit formulier worden daarvoor twee
buttons gebruikt. Ze zijn beide van het type submit, wat betekent dat het formulier bij
het drukken een op beide buttons direct wordt overgedragen. Beide Buttons hebben
de naam led, maar telkens verschillende waarden (values). Bij het drukken op de
eerste knop die het kentekening LED ON draagt, wordt de huidige URL opnieuw op-
geroepen, in elk geval met een kleine toevoeging. Achter de URL, in dit geval ook
achter het IP van de module, staat nu namelijk /?led=1. Precies deze tekst wordt dan
in het Arduino-programma geanalyseerd in die zin dat ernaar wordt gezocht en dan
het daarop volgende getal met parseInt() wordt ingelezen en naar de LED overgedra-
gen. Met deze eerste eenvoudige versie van een formulier is de comfortabele bestu-
ring van een LED dus probleemloos mogelijk.
Zo ziet de URL eruit nadat de button LED ON werd ingedrukt.
001
<BR>
002
<HR>
003
004
</font>
005
</HTML>
De laatste regels van de HTML-brontekst bevatten niets nieuws. Een sprong naar
de volgende regel en een horizontale lijn ronden de afbeelding af voor het docu-
ment met </HTML> wordt beëindigd. U kunt de website in Sketchmap nu naar
eigen wens wijzigen. U kunt bijvoorbeeld de achtergrondkleur wijzigen of meer
tekst in de website invoegen. U mag de pagina in elk geval niet overladen, aange-
zien het SRAM snel overbelast kan zijn. Wanneer u de wijzigingen hebt uitge-
voerd, is het aan de tijd om ze naar uw Arduino-programma over te dragen. Daar-
toe kopieert u de gehele tekst naar de tussenopslag en gaat u naar de website
met de Swiss Converter Tool:
http://www.percederberg.net/tools/text_converter.html
De Swiss-Converter-Tool-site na een geslaagde convertering
Daar voegt u de tekst uit de tussenopslag in en stelt u in punt 2. Select Output: de
instellingen C/C++/PHP StringText en UTF-8 Unix (LF) in. In het onderste
venster verschijnt al snel de Arduino-vriendelijke tekst die u naar de progmem-
variabele site kunt kopiëren. Wanneer u het gewijzigde programma met de nieuwe
variabele uploadt, ziet u de nieuwe website bij het oproepen van het board-IP in
de browser.
4.5 | RGB-LED via TCP besturen
In het huidige project gaat het om de aansturing van de RGB-LED met behulp van
een website op een webserver. Via een overzichtelijk oppervlak kan de kleur van
de LED worden gewijzigd. De website werd aangepast en moet ook smartphones
goed weer te geven zijn. De benodigde opbouw is
op de onderstaande afbeelding te zien.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x RGB-LED (rood), 3 x
weerstand 1 kOhm (bruin-zwart-rood), draadbrug
Aansluiting van de RGB-LED aan de pins D3, D5 en D6
Het programma
De nieuwe website is opnieuw in de progmem-variabelen site te vinden. Ook dit keer
kunt u de HTML-pagina in de Sketch-map bekijken. Na het instellen van de WLAN-
bestanden en het uploaden van het programma kan de website van de webserver
via het IP van de module worden bereikt. De pagina is met betrekking tot de achter-
grondkleur en een titel op gelijkaardige manier vormgegeven dan de vorige. Echter
bevindt zich een nieuw element op de pagina, namelijk het HTML5-element Color
Picker. Daarmee is het mogelijk, een kleur voor de LED te zoeken. Van zodra u de
kleur hebt bevestigd, wordt ze door de LED weergegeven. Daarbij kan de weergave
van het Color Picker element afhankelijk van de gekozen browser sterk verschillen.
De website in de browser
De keuze
van de kleur in de
Chrome-browser
Ook wanneer het design van de website niet zeer van deze van de voorgaande
verschilt, zijn er toch een paar elementen die ik kort in meer detail wil beschrijven.
Ten eerste is er een wijziging in de header van het HTML-document, en wel met
betrekking tot de volgende regel:
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
Deze regel is daar om te zorgen dat de browser na het laden van de website niet
probeert het zogenaamde Favicon te laden. In principe heeft een website namelijk
nog een bijzonder symbool dat van andere websites verschilt en de website in een
browserlijst met meerdere tabs eenduidig identificeert. Opdat de browser dit teken
kan laden, stuurt hij na het oproepen van de site een tweede request-vraag en
vraag naar dit Favicon. In de eerste verzoeken met de TCP-server is deze bijko-
mende Request-vraag u misschien opgevallen. Opdat deze tweede vraag voor-
komen en het board niet onnodig belast wordt, laat de bovenstaande coderegel de
browser verstaan dat hij geen tweede request moet zenden. Ik raad u aan om
deze regel voor uw eigen HTML-pagina's over te nemen.
De tweede bijzonderheid in dit document is het reeds vermelde Color-Picker-
element. Dit vervangt zogezegd de buttons in het vorige voorbeeld. Hij gaat om
een relatief nieuw HTML5-element.
In de vorige website hebben wij gewoon buttons van het type submit gekozen
zodat bij het drukken de formulierwaarden onmiddellijk overgedragen werden. Dit
is bij het invoerelement van het type color jammer genoeg niet mogelijk. Een mo-
gelijkheid om het probleem op te lossen, is een button van het type submit aan te
maken die dan na het instellen van de kleur bijkomend moet worden ingedrukt. Dit
wordt in een latere versie nog gedemonstreerd. Hier werd een kleine JavaScript-
code ingevoegd (het gaat om het deel onchange="this.form.submit()"), dat ervoor
zorgt dat het formulier bij een wijziging onmiddellijk overgedragen wordt.
Het Color-Picker-element in de Android-5.0-
browser
Daardoor spaart men een bijkomende button uit.
001
<form method="GET">
002
<input type="color" name="rgb" onchange="this.form.submit()"><BR>
003
</form>
De gekozen kleur wordt nu in de vorm /?rgb=%23, gevolgd door zes bijkomende
tekens, overgedragen. De uitdrukking %23 wijst erop dat het om een hexadeci-
maal getal gaat. Voor de kleur wit, luidt de URL dus als volgt:
[IP]/?rgb=%23ffffff
Uit dit HEX-getal moet de controller nu de afzonderlijke kleurwaarde van de LED
afleiden, wat in het volgende deel van de loop-functie gebeurt:
001
if (esp8266.findUntil("?rgb=", "\n"))
002
{
003
String hexstring = esp8266.readStringUntil(‚ ‚);
004
long number = (long) strtol( &hexstring[3], NULL, 16);
005
006
int r = number >> 16;
007
int g = number >> 8 & 0xFF;
008
int b = number & 0xFF;
009
010
analogWrite(RED, r);
011
analogWrite(GREEN, g);
012
analogWrite(BLUE, b);
013
}
Door de functie strtol() wordt eerst de ontvangen tekst na %23 in een long-getal en
dit vervolgens door bitmanipulatie in drie bytewaarden omgezet. Deze worden tot
slot met de analogWrite()-functie naar de RGB-LED overgedragen.
4.6 | Lichtsensor
In dit project wordt de website van de webserver niet als stuuroppervlak, maar als
uitvoerelement gebruikt. De via een helderheidssensor gemeten helderheid wordt
als relatieve waarde met een nieuw HTML-element overzichtelijk weergegeven.
Voor de opbouw van het verzoek is de fototransistor, die als lichtsensor dient,
nodig. De fototransistor kan makkelijk met een LED worden vergist. U kunt de
fototransistor onderscheiden door van bovenaf in de kop van het element te kijken.
De fototransistor heeft een groot, zwart oppervlak aan de binnenkant. De opbouw
van het verzoek toont het volgende beeld. De collector van de fototransistor is de
kortere aansluiting, hij ligt aan +5 V. De in serie
met de fototransistor geschakelde weerstand heeft
10 kOhm.
Aansluiting van de fototransistor aan pin 46 met 10 kOhm tegenweerstand
Het programma
Tot nu bestonden de websites van de webserver altijd uit een niet-veranderbare
pagina, die gegevens naar de controller verzonden heeft. Nu moet de website
voor het overdragen naar de browser worden veranderd om de gemeten helder-
heid van de fototransistor weer te geven. Dit werkt omdat in de broncode van de
website een soort wildcard is verborgen. Het programma vervangt nu bij het laden
van de gegevens uit de programmavariabelen de wildcard *bright* door de huidige
helderheidswaarde. Zo wordt de uitgavetekst en de uitslag van de schuifregelaar
gewijzigd. Een andere regel in het HTML-bestand zorgt ervoor dat de pagina au-
tomatisch elke paar seconden opnieuw oplaadt. De huidige helderheid wordt al
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x fototransistor, 1 x
weerstand 10 kOhm (bruin-zwart-oranje), draadbrug
overzichtelijk in de browser weergegeven.
De website van de helderheidssensor
Opdat het systeem kan werken, zijn er in de HTML-bestanden opnieuw een paar
kleine wijzigingen. De eerste wijziging is opnieuw in het Header-bereik te vinden:
<meta http-equiv="refresh" content="3">
Deze kleine regel zorgt ervoor dat de browser de website automatisch alle drie
seconden opnieuw laadt. Dat bespaart u het voortdurend indrukken van
[F5]
om
nieuwe waarden te kunnen zien.
De tweede wijziging bevindt zich op de plaatsen waar u normaal gezien het form-
element vindt:
001
<label for="hell">Current Brightness: *bright*</label> <BR>
002
<input type="range" max = "1024" name="hell" value=*bright*><BR>
Hier is er namelijk dit keer geen formulier nodig want u gebruikt de website alleen
voor de uitvoer. Beide elementen label en range dienen daarbij als uitvoerelement.
In het label, dat normaal gezien voor opschriften wordt gebruikt, kan in de tekst de
plaats *bright* worden gevonden. Het schuifregelknop-element range krijgt als
value de waarde *bright* toegewezen die eigenlijk geen legitieme waarde is, maar
later door een waarde wordt vervangen. De maximumwaarde van range bedraagt
1024 en werd zo aan het 10-bit bereik van de ADC's van de controller aangepast.
In de brontekst moet voor de website wordt overgedragen, alleen ervoor worden
gezorgd dat de wildcard *bright* door een legitieme waarde wordt vervangen.
001
String createWebsite()
002
{
003
String xBuffer;
004
005
for (int i = 0; i <= sizeof(site); i++)
006
{
007
char myChar = pgm_read_byte_near(site + i);
008
xBuffer += myChar;
009
}
010
011
xBuffer.replace("*bright*", String(analogRead(SENSOR)));
012
013
return xBuffer;
014
}
Het vervangen van de wildcard wordt in de functie createWebsite() uitgevoerd.
Eerst wordt de progmem-variabele, zoals gewoonlijk, uit het geheugen geladen en
in een string opgeslagen. Voor de functie deze string teruggeeft, worden alle
*bright*-datareeksen door de huidig gemeten waarde aan de sensor vervangen.
De String-functie replace() voert het werk volautomatisch uit. Tot slot wordt de
gewijzigde string teruggegeven en door de bekende mechanismen naar uw brow-
ser overgedragen.
4.7 | GPIO-Control
Dit nieuwe project maakt het mogelijk om de digitale pins D2-D7 via de website
aan te sturen. De status van de respectievelijke pins wordt eveneens in de brow-
ser weergegeven zodat men nooit het overzicht verliest.
Opdat de toestand van de pins goed kan worden gecontroleerd, is het aangewe-
zen om een opbouw zoals deze in de onderstaande afbeelding te volgen. Zowel
de RGB-LED als de normale LED worden ingezet. De kathoden van de LED's zijn
dit keer echter niet aan de lange massaleiding aan de buitenzijde van het board
aangesloten, maar liggen eveneens aan een digitale uitgang aan. Alleen wanneer
deze pins low geschakeld zijn, kunnen de LED's dus oplichten.
Aansluiting van de LED aan D2-D7
Let op! LED's mogen niet zonder voorweerstanden worden aangesloten. Dat het
in dit geval toegelaten is, ligt aan de on-weerstanden van de interne port-FET's
van ca. 30 Ohm. Omdat de LED's tussen twee ports liggen, werken ze inderdaad
met een voorweerstand van 60 Ohm. Naargelang het LED-type en de LED-kleur
stelt zich daarbij een LED-stroom tussen de 15 mA en maximum 30 mA in, wat
nog toegelaten is.
Het programma
De website van dit programma gebruikt zogenaamde checkboxes als HTML-
elementen. Wanneer u het programma oplaadt en de pagina van het board op-
roept, ziet u een reeks aanklikbare boxes. Een haakje in de box betekent dat de
pin high is. Geen haakje betekent low. U kunt nu proberen welke pins high en
welke low moeten zijn opdat alle LED's oplichten.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x RGB-LED, 1 x RGB-
LED (rood), draadbrug
De website GPIO-control
In deze HTML-code wordt de website zowel als invoerformulier en als uitvoerele-
ment gebruikt. Wanneer u een blik op het vormelement werpt, ziet u dat een reeks
van invoerelementen van het type checkbox wordt gebruikt. U krijgt een individue-
le naam toegewezen, die van de pinnaam wordt afgeleid. Als wildcard in de tekst
dient telkens de tekst *checkedX*. Wanneer de pin low is, wordt de wildcard ge-
woon gewist. Wanneer de Pin high is, zet het programma in de plaats van
*checkedX* CHECKED in, waardoor de checkbox bij het laden met een haakje
wordt weergegeven. Dit maal is er ook een knop waarop na de keuze van de juiste
boxes moet geklikt worden opdat het formulier wordt overgedragen.
001
<form method="GET">
002
<input type="checkbox" *checked2* name="ld2">D2
003
<input type="checkbox" *checked3* name="ld3">D3
004
<input type="checkbox" *checked4* name="ld4">D4
005
<br><br>
006
<input type="checkbox" *checked5* name="ld5">D5
007
<input type="checkbox" *checked6* name="ld6">D6
008
<input type="checkbox" *checked7* name="ld7">D7
009
<br><br>
010
<input type="submit" value="Send">
011
</form></HTML>
De analyse in het programma werkt nu op de volgende manier: We nemen aan
dat in het formulier de boxen 3, 5 en 7 werden geselecteerd. Dan wijzigt de URL
naar:
[IP]/?ld3=on&ld5=on&ld7=on
Dit betekent dat alleen de geselecteerde boxen overgedragen worden en zich aan
de hand van de index laten identificeren. In de loop-routine gebeurt dan dit. Eerst
wordt de hele port D waaraan de digitale uitgangen zijn aangesloten, low gescha-
keld. Dan zoekt een while-lus naar alle "Id"'s in de ressources-link. Aan de hand
van de gevonden ld, bij ld3 is het bv. de 3 en kan door de verschuiving van een 1
in een byte met de voornoemde index 3, het byte 0b0001000 ontstaan. Dit wordt
dan met de huidige waarde van de bytes of-gekoppeld. Dit gebeurt met alle over-
gedragen indices tot het uitvoerregister van D de juiste waarde heeft. Deze vorm
van uitgave in de plaats van digitalWrite() is voor Arduino-gebruikers vermoedelijk
een beetje ongewoon, maar in dit geval duidelijk praktischer.
001
if (esp8266.find("+IPD,"))
002
{
003
debug("Incomming Request");
004
int connectionId = esp8266.parseInt();
005
if (esp8266.find("/?")) PORTD = B00000000;
006
while (esp8266.findUntil("ld", "\n"))
007
{
008
int ld = esp8266.parseInt();
009
PORTD |= (1 << ld);
010
}
011
}
Omgekeerd werkt de uitvoer van de checkboxen als volgt: In de createWebsite()-
functie worden de wildcards uit het HTML-document vervangen. Een for-lus gaat
alle gebruikte ports van de reeks na door. Als de pin high is (ook hier vastgesteld
door de vergelijking met een byte die door verschuiving van high bits op de plaat-
sen van de index werd opgewekt),wordt de wildcard met de index door de tekst
checked vervangen. Wanneer de pin low is, wordt de wildcard gewoon gewist.
Daardoor wordt de juiste weergave van de actieve port gegarandeerd.
001
String createWebsite()
002
{
003
String xBuffer;
004
005
for (int i = 0; i <= sizeof(site); i++)
006
{
007
char myChar = pgm_read_byte_near(site + i);
008
xBuffer += myChar;
009
}
010
011
for (int x = 2; x <= 7; x++)
012
{
013
if (PORTD & (1 << x))
014
{
015
xBuffer.replace("*checked" + String(x) + "*", "checked");
016
}
017
else
018
{
019
xBuffer.replace("*checked" + String(x) + "*", "");
020
}
021
}
022
return xBuffer;
023
}
Bij het creëren van dit programma had ik enkele problemen, wier oorzaak mij eerst
niet duidelijk was. Bij het laden van de website kwam het soms tot fouten en vaak
waren volledig verkeerde checkboxen geselecteerd. Met behulp van de Arduino-
MemoryFree-Master-Library (http://playground.arduino.cc/Code/AvailableMemory)
kwam ik dan op de oplossing: Het SRAM-geheugen was aan zijn grenzen geko-
men en daardoor kwam het tot zeer merkwaardige, onberekenbare fouten. Ik
moest de oorspronkelijke versie van het programma en de HTML-code duidelijk
inkrimpen zodat het programma in deze versie kan werken. Ik vermeld dit aange-
zien u bij het creëren van eigen projecten precies hetzelfde kan overkomen. De
reden voor de grote belasting van de SRAM ligt vooral in het uitgebreide gebruik
van de praktische, maar ook ressources-verslindende gebruik van de string-
functies en algemeen het gebruik van strings in de plaats van char-reeks. Een
string.replace() is zeer praktisch, maar ook geheugenbelastend. Als u dus een
keer op onverklaarbare fouten stoot, raad ik aan om eerst de broncode van het
HTML-bestand te verkleinen en bovendien eventueel enkele string-operaties te
optimaliseren. De bovengenoemde library kan u helpen bij het zoeken naar fouten.
4.8 | Insteekmodule: Vanaf het internet toegang krijgen tot het board
Veel van de hier voorgestelde verzoeken zijn praktisch voor de aansturing van het
board in het eigen thuisnetwerk. Alleszins kan het ook zeer nuttig zijn om het
board van op grotere afstanden te kunnen bereiken. Man kan bv. zo de lichten
thuis inschakelen terwijl men met vakantie is om inbrekers af te schrikken. Of man
controleert via de lichtsensor of het licht ook werkelijk uitgeschakeld werd. Of men
stuurt de achterblijvers thuis een kort berichtje dat het later zal worden. Opdat
deze ideeën echter ook werkelijkheid kunnen worden, moet u een paar instellin-
gen aan uw router uitvoeren.
Normaal gezien gebruiken verschillende routerstypes ook verschillende software.
Ik zal hier de principiële stappen aan de hand van een Fritz!Box-router voorstellen.
De instellingen in uw router moeten zo op gelijkaardige manier lopen.
De meeste moderne routers hebben een eenvoudig weboppervlak, gelijkaardig
aan hoe we ze met de module hebben gemaakt. Ze vereisen een gebruikersnaam
en wachtwoord om zich bij het oppervlak te kunnen aanmelden. Bij routers van het
type Fritz!Box luidt het IP meestal 192.168.178.1. Anders kunt u ook gewoon
http://fritz.box invoeren. Wanneer u een andere router gebruikt, moet u proberen,
het passende IP te vinden. In regel gebruikt de router binnen het subnet het IP
met adres 1. Wanneer het IP van uw computer bv. 192.168.4.2. is, luidt het IP van
uw router hoogstwaarschijnlijk 192.168.4.1. Wachtwoord en gebruikersnaam vindt
u meestal op de achterzijde van de router of in de bijhorende gebruiksaanwijzing.
Wanneer u in het gebruikersoppervlak bent aangemeld, moet u het punt Portvrij-
gave of Portverwijzing vinden. In mijn Fritz!Box stond het punt onder Internet ->
Vrijgave. Maak een nieuwe portregel aan. De instellingen moeten zo worden ge-
kozen dat externe vragen aan port 80 aan het IP van uw board en naar port 80
worden verwezen. In het menu van de Fritz!Box is de instelling vergemakkelijkt en
ik moet alleen het punt HTTP-server selecteren, dan kon ik in het dropdownmenu
gewoon onder beschikbare IP's kiezen. Het resultaat moet er op alle computers
hetzelfde uitzien.
De juiste instellingen in de Fritz!Box
De instellingen in de router zouden daarmee in orde moeten zijn en men kan een
eerste verzoek wagen. Daarvoor hebt u dit keer niet het IP van het board in uw
lokaal netwerk nodig, maar uw globale IP. Dit kunt u opnieuw via de site
http://www.meine-aktuelle-ip.de/
vinden. Wanneer u het daar gegeven IP nu in uw browser invoert, moet de websi-
te van de module verschijnen. Dit keer werd alleszins de lange weg via het inter-
net genomen. Wanneer u niet overtuigd bent, dat het board nu werkelijk via het
internet bereikbaar is, kunt u een smartphone met mobiel internet gebruiken en
daarmee de site oproepen. Wanneer de smartphone niet meteen met uw WLAN is
verbonden, wordt de site in elk geval via het internet opgeroepen.
Het zo door u ingerichte systeem is goed geschikt voor tests. Er zijn in elk geval
twee problemen bij het praktisch gebruik. Ten eerste laat het IP zich niet makkelijk
merken en, ten tweede, wijzigt het vaak. De meeste routers maken minstens
eenmaal per dag een reconnect zodat ook het globale IP van uw router verandert.
Voor deze problemen zijn er hulpmiddelen, namelijk het Domain Name System
(kortweg DNS). Dit systeem zorgt er voor dat u bv. www.google.de kunt oproepen
en daarbij niet het IP moet invoeren aangezien het complexe IP's in makkelijk te
merken namen codeert. Elke normale website gebruikt DNS en voor u is er ook de
gratis mogelijkheid om het systeem te gebruiken.
Er zijn verschillende gratis websites die DDNS aanbieden. DDNS staat voor Dy-
namic Domain Name System en is een dienst die ervoor zorgt dat uw IP aan het
juiste domein wordt toegewezen. Ik stel hier de dienst van de site
http://www.anydns.info/ voor, waarbij u ook elke andere webdienst kunt gebruiken
die deze service aanbiedt.
De website AnyDns.info
Eerst moet u zich op de website registreren en ook reeds een domeinnaam geven.
Ik heb de naam nanoesp gekozen en als host dynpc.net. Daaruit volgt het domain
na de aanmelding:
http://nanoesp.dynpc.net/
Nu moet de dienst alleszins nog hun IP vernemen. Voer de dienst in uw router in,
zodat een nieuw IP rechtstreeks naar de DDNS-dienst wordt doorgestuurd. In de
Fritz!Box moet ik eerst onderaan naar Aanzicht: Klik op geavanceerd zodat alle
opties worden weergegeven. Dan kon ik onder Vrijgaven ook de DDNS-dienst
invoeren.
De instellingen in de Fritz!Box voor het gebruik van Dynamic DNS
Enkele woorden van waarschuwing:
De dynamische DNS-dienst is wel praktisch, maar u moet voorzichtig zijn aan wie
u de domeinnaam vertelt. U maakt uzelf kwetsbaar voor aanvallen want nu hoeft
een hacker alleen uw domain en niet uw huidig IP te kennen om uw router aan te
vallen. Daarom zal ik de bovengenoemde site ook slechts als test in het net laten.
THINGSPEAK
In dit laatste hoofdstuk gaat het om een heel nieuw thema, namelijk om het plat-
form ThingSpeak. Deze site werd speciaal voor het thema Internet of Things ont-
wikkeld en stelt verschillende praktische functies ter beschikking. U kunt onder
andere met behulp van deze site op eenvoudige manier een langdurige bewaking
van meetsensoren protocolleren en in overzichtelijke vorm laten weergeven. Zo-
lang u met het internet verbonden bent, spaart u het opslaan van waarden op een
extern geheugenmedium uit. Bovendien kunt u verschillende aansturingen via de
internetsite realiseren. Hoe precies deze afzonderlijke functies er uitzien, zult u in
de loop van het hoofdstuk vernemen.
5.1 | ThingSpeak
Voor u dus zoals gewoonlijk met de opbouw en het programma begint, moet u een
eerst account op de site
www.ThingSpeak.com
aanmaken. Log dan in met uw gebruikersgegevens onder het punt Sign In . U
ziet een pagina die uw channels (kanalen) weergeeft. Aangezien u nog geen ka-
nalen hebt, zal deze pagina er leeg uitzien. Klik op New Channel en geef dan
een naam, bv. Light, want u zult in dit project de helderheid meten. Onder het
punt Field 1 kunt u nu nog een naam voor het veld geven, evt. Brightness.. Alle
andere velden kunnen voorlopig leeg blijven.
Kanaal op de ThingSpeak-site aanmaken
Klik dan op Save Channel om de instellingen op te slaan. U wordt naar de site
van uw channel gebracht, waarop echter alleen een leeg diagram te zien is. Klik in
de bovenliggende driver op API Keys. De cijfer- en lettervolgorde die u onder het
punt Write API Key vindt, hebt u meteen nodig.
De opbouw van het verzoek bestaat uit een sensor aan de analoge ingang A6.
Een spanningsdeler met 10-kΩ-weerstand en fototransistor maakt het meten van
de huidige helderheid mogelijk. U kunt echter ook de temperatuursensor gebrui-
ken. De schakeling blijft bijna dezelfde, behalve
dat u de lichttransistor door de zwarte NTC ver-
vangt. De verpoling is bij NTC willekeurig.
De opbouw met fototransistor aan A6
Het programma
Het programma meet nu de helderheid. Echter, anders als in het vorige verzoek
worden de gegevens niet op een website uitgegeven, maar rechtstreeks naar de
ThingSpeak-site verzonden. Deze site slaat de data niet alleen op, maar geeft ze
ook overzichtelijk in een diagram weer een zeer praktische functie voor een
meetstation met langdurige bewaking.
Opdat het programma naar de website kan zenden, moet u behalve uw WLAN-
gegevens eerst de bovenvermelde API-key onder het punt ThingSpeakKEY in het
programma invoeren. Na het uploaden ziet u de huidige meetwaarden in de serië-
le monitor. De gegevens worden 15 seconden lang verzameld en tot slot voorge-
legd. Deze waarde wordt dan naar de ThingSpeak-site overgedragen. De 15 se-
conden zijn van belang want u kunt de ThingSpeak-site niet elke seconde met
nieuwe waarden belasten. Het resultaat van de meting ziet u nu op uw Channel-
site in het hieronder weergegeven diagram.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x fototransistor, 1 x
weerstand 10 kOhm (bruin-zwart-oranje), draadbrug
De meetresultaten in het diagram
De brontekst schijnt sterk van alle voorgaande programma's te verschillen, maar
in wezen gaat het om een samenstelling van oude, bekende elementen. Een pro-
gramma-variabele bevat de HTTP-vraag die naar de ThingSpeak-site moet wor-
den verzonden, naast een paar wildcards die telkens na vragen moeten worden
vervangen.
001
POST *URL* HTTP/1.1
002
Host: api.thingspeak.com
003
Connection: close
004
Content-Type: application/x-www-form-urlencoded
005
Content-Length: *LEN*
006
007
*APPEND*
Zoals u ziet, komt de oproep bijna met de bekende Get-oproep overeen. Ook hier
moet weer een *URL* worden aangegeven. Bovendien moet u *LEN* door de
lengte van het bericht vervangen dat u dan in de plaats van *APPEND* invoert.
Dit is het voor de website universeel geldige formaat, waarmee de gegevens met
het POST-verzoek naar de site worden verzonden. Wanneer u nu, zoals getoond
in dit voorbeeld, meetdata in een channel in uw account wilt invoeren, moet u de
volgende structuur gebruiken: *URL* is
/update. Dat is de subpagina waarnaar de gegevens moeten verzonden worden.
Het bericht is nu samengesteld uit uw API-key, het in te vullen veld en de waarde.
De lengte van het bericht kan gewoon door de lengte van de string worden be-
paald. Over het algemeen ziet een voorbeeld-POST er zo uit:
001
POST /update HTTP/1.1
002
Host: api.thingspeak.com
003
Connection: close
004
Content-Type: application/x-www-form-urlencoded
005
Content-Length: 35
006
007
api_key=GXE93O4WF03Q3X8I&field1=954
De website kan aan de hand van de API-key de gebruiker en het channel eendui-
dig identificeren en voert de waarden in. De algemene werking van de vraag-
samenstelling schuilt achter meerdere functies. Om de nieuwe waarde te verzen-
den, moet u slechts de functie sendThingPost() oproepen die als parameter de
KEY en de sensorgegevens nodig heeft. Alle andere gegevens wordt automatisch
op de achtergrond weergegeven.
5.2 | Twitch-weergave
De website ThingSpeak biedt wat meer dan enkel de langdurige bewaking van
sensoren. Het volgende project is gelijkaardig aan de projecten van de TCP-client.
Er wordt namelijk informatie van een website uit het internet gehaald. In dit geval
gaat het erom of een bepaalde stream al of niet on-line is.
Er zijn twee belangrijke voordelen van de ThingSpeak-variant tegenover de eerste
verzoeken. Ten eerste kunnen via de ThingSpeak-pagina ook websites via HTTPS
(HyperText Transfer Protocol Secure) worden aangesproken, terwijl de module
alleen het HTTP-protocol ondersteunt, dat in wezen onveilig is. Ten tweede kan de
website belangrijke informatie voorfilteren en zo de door de controller te bewerken
gegevenshoeveelheid duidelijk verminderen.
In het huidige project zult u een Twitch-Streaming-weergave realiseren als voor-
beeld voor verschillende mogelijkheden. Twitch (www.twitch.tv) is een website
waarop live games of andere inhouden rond het thema computerspellen worden
gestreamd. Een van de bekendste streamingchannels is RocketBeansTV van de
voormalige GameOne-maker. Dit kanaal zendt continu uit en is daarom goed ge-
schikt voor een eerste test. Later kunt u natuurlijk
een kanaal naar keuze instellen.
De verzoeksopbouw met een LED aan pin D9
Het programma
Naast de hardware-opbouw zijn er ook enkele stappen op de ThingSpeak-
-pagina nodig. Wanneer u op de website in het bovenste menu op Apps klikt, krijgt
u een reeks verschillende toepassingsmogelijkheden te zien. Dit keer bekomme-
ren wij ons met de app ThingHTTP. Wanneer u op de overeenkomstige button
klikt, krijgt u eerst een leeg oppervlak te zien. Klik op New ThingHTTP. In het for-
mulier dat nu verschijnt, voert u het volgende in:
Naam: Twitch
URL: https://api.twitch.tv/kraken/streams?channel=
rocketbeanstv
Methode: GET
HTTP-versie: 1.1
Parse String: _total
Indien u voorkeur heeft voor een ander streaming-kanaal, kunt u in het URL na
channel een ander kanaal invoeren. Klik op Save ThingHTTP en kopieer vervol-
gens de in het overzicht verschijnende API-key in de tussenopslag. De Key moet u
nu in het programma kopiëren, na #define ThingHTTP. De WLAN-gegevens niet
vergeten en u kunt het programma uploaden. Eenmaal per minuut wordt nu ge-
controleerd of er een stream kan worden gevonden. Als dit het geval is, begint de
LED op te lichten.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x LED (rood), 1 x weer-
stand 1 kOhm (bruin-zwart-rood), draadbrug
Dit project is mogelijk aangezien de Twitch-site informatie ook in het bekende
JSON-formaat ter beschikking stelt. Via de site
https://api.twitch.tv/kraken/streams?channel=rocketbeanstv
kunt u de editie in JSON-formaat bekijken. Er is een hoeveelheid tekst, maar ons
interesseert alleen het attribuut _total dat het aantal actieve streams weergeeft.
Als dit aantal groter is dan nul, betekent dit dat er minstens een stream actief is.
Dit attribuut wordt nu automatisch door de ThingSpeak-site geanalyseerd en als
overzichtelijke waarde uitgegeven. Deze waarde kan dan gewoon in het pro-
gramma door de functie getThingSpeakHttp() worden opgeroepen en geanaly-
seerd.
5.3 | Twitter-alarminstallatie
Bij dit project gaat het om een alarminstallatie waarmee u bijvoorbeeld kunt con-
troleren, of iemand onbevoegd een lade opent. Er wordt constant gecontroleerd of
er op de aangesloten lichtsensor licht van een vastgestelde helderheid valt. Als dit
het geval is, weerklinkt een alarmsignaal en wordt er bijkomend een bericht via
Twitter verstuurd. De opbouw ziet u in de onderste afbeelding. Anders kunt u na-
tuurlijk ook hier opnieuw de temperatuursensor
gebruiken en de overschrijding van een bepaalde
temperatuur bewaken.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x fototransistor, 1 x
weerstand 10 kOhm (bruin-zwart-oranje), 1 x Piezo,
draadbrug
Lichtsensor aan A0, Piezo aan D8
Het programma
Het thema is onder meer de Twitter-app van de ThingSpeak-site. Klik dus op Apps
en vervolgens op ThingTweet. Met een klik op Link TwitterAccount en het invoeren
van uw toegangsgegevens maakt u een verbinding tussen beide diensten. Als u
nog geen Twitter-account hebt, is het aangewezen om een account aan te maken
als test voor het werken met het leerpakket. Nadat Twitter met succes aan
ThingSpeak werd gekoppeld, kunt u de API-key die onder de Apps/ThingTweet
staat in het programma na het punt #define TwitterKEY invoeren.
Het programma controleert nu permanent of de gemeten helderheid een waarde
van 500 overstijgt. Als dit het geval is, wordt een Twitter-bericht verzonden en
weerklinkt een alarm tot de helderheid opnieuw onder de 500 zakt. De huidig ge-
meten helderheidswaarde kunt u via de Serial Monitor volgen. Voor de eerste
verzoeken raad ik aan om de lichtsensor af te dekken zodat het alarm niet voortijd
wordt geactiveerd.
De nieuwe functie in dit project luidt sendTwitterPost(). Als parameter moeten
uitsluitend de TwitterKEY en het bericht worden aangegeven. De functie zet dan
alle benodigde delen samen om daaruit een ThingSpeak-post te maken. U kunt
dus ook via een druk op de knop berichten laten verzenden of meetresultaten
publiceren. Alles dankzij de eenvoudige ThingSpeak-API.
5.4 | TalkBack
In dit project gaat het om een bijkomende app van de ThingSpeak-site, namelijk
de TalkBack-app. Met deze functie is het mogelijk om een commando aan te ma-
ken dat door de controller wordt geanalyseerd en uitgevoerd. Wat met slechts een
controller aanvankelijk zinloos schijnt, is zinvol wanneer men twee of zelfs een
heel netwerk controllers gebruikt. Enkele boards kunnen dan als sensoren functio-
neren, bijvoorbeeld met bewegingsmelders, en bij het ontdekken van een bewe-
ging een TalkBack-commando verzenden. Een bijkomende module leest het
commando van de ThingSpeak-site en opent dan de deur of meldt alarm.
Voor de opbouw van het verzoek hebt u de twee-
de knop nodig. Een LED met voorweerstand geeft
de huidige toestand weer.
Opbouw met twee schakelaars aan D5 en D10 en een LED aan D9
Het programma
Eerst moet onder Apps/TalkBack een nieuw TalkBack-kanaal worden aange-
maakt. U kunt als naam bv. Doors gebruiken. Wanneer u wilt, kunt u de com-
mando's ook in een channel invoeren. Dit kan het reeds aangemaakte Light-
kanaal van het eerste ThingSpeak-
verzoek zijn of een eigen kanaal. Alle commando's worden dan geprotocolleerd.
De API-key, die u in de plaats #define TalkBackKEY invoert, is vooral van belang.
Bijkomend bij de API-key is deze keer ook een ID nodig die u in het overzicht
onder TalkBack ID vindt, nadat u op Save TalkBack hebt geklikt. Deze ID voert u
na #define TalkBackID in het programma in.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 2 x knop, 1 x LED (rood),
1 x weerstand 1 kOhm (bruin-zwart-rood), draadbrug
Wanneer u nu het programma uploadt en de seriële monitor oproept, krijgt u eer-
ste de melding No Command te zien. Druk nu op één van beide drukknopschake-
laars. Na korte tijd verschijnt dan de melding OpenDoor of CloseDoor, naargelang
de button u hebt ingedrukt. Bij het OpenDoor-commando begint de LED boven-
dien te branden.
Het TalkBack-overzicht bij het invoeren van een commando
Er is natuurlijk ook de mogelijkheid waarmee u commando's rechtstreeks via het
internet kunt invoeren. Wanneer u op de TalkBack-site op uw Doors-kanaal klikt,
ziet u onderaan de optie Add a new command. Daarmee kunt u het commando
OpenDoor of CloseDoor manueel invoeren en zo de module besturen. U kunt het
board dus ook vanaf verschillende bronnen via TalkBack-commando's besturen.
In de brontekst overneemt de functie getTalkBackCom() het opvragen van nieuwe
commando's. Wanneer iets werd gevonden, wordt het commando teruggegeven.
U moet nu de parameters key en id aangeven.
5.5 | Cheerlights
Dit verzoek is gebaseerd op een project van Hans Scharler, dat Cheerlights heet.
Het idee: wereldwijd vernette lichtjes, die zich simultaan via Twitter-commando's
laten sturen. Een goed voorbeeld van het feit dat
de wereld door het internet altijd dichter bij elkaar
komt.
De RGB-LED op het breadboard aan de pins D3, D5 en D6
Het programma
Voor het huidige programma moet u bij uitzondering geen eigen ThingSpeak-
wijzigingen uitvoeren aangezien het project een openbaar kanaal hebt, dat u on-
der
https://thingspeak.com/channels/1417
vindt. Op de site vindt u bovendien altijd de huidige kleur en meer informatie over
het project.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x RGB-LED (rood), 3 x
weerstand 1 kOhm (bruin-zwart-rood), draadbrug
De Cheerlights-
site met de
huidige kleur paars
Voor het programma is bovendien de Crossfrade Library van Radek Wierzbicki
nodig (bron: htt-
ps://github.com/radekw/Arduino/tree/5f24ce7c8db9dfbb5252b59824c3217d851b3
a3c). Omwille van praktische redenen bevat de Sketch-map een kopie van de
door mij gebruikte Library-versie. Deze moet in de map libraries van uw Sketch-
book-map worden gekopieerd. De Library maakt het mogelijk om snel en eenvou-
dig kleuren te definiëren en zorgt er bovendien voor dat de LED's langzaam naar
een andere kleur overgaan (fade genoemd).
Wanneer u nu het programma uploadt, wordt na een paar seconden de huidige
kleur van de LED weergegeven. U kunt nu een Twitter-bericht opmaken en zo uw
en ook de kleur van alle andere Cheerlights-gebruikers wijzigen. Het bericht moet
enerzijds #Cheerlights, @Cheerlights of gewoon het kernwoord Cheerlights bevat-
ten en anderzijds moet een van de voorgedefinieerde kleuren achter het kern-
woord staan. Bij de voorgedefinieerde kleuren horen:
red, green, blue, cyan, white, warmwhite, purple,
magenta, yellow, orange, pink
Een mogelijke tweet kan er bv. zo uitzien:
Testing my #cheerlights project on my #NanoESP with the
color blue #ThingSpeak #IoT
U hebt al de hele wereld een nieuwe kleur gegeven.
De vraag van de huidige kleur wordt met de functie getCheerlightColor()
gerealiseerd. Als parameter worden de host, i.e. api.thingssspeak.com en de URL,
hier /channels/1417/field/1/last.txt, aangegeven. Het gaat dus om een eenvoudige
TCP-clientvraag van het bekende type. Ook hier wordt het antwoord van de server
opnieuw met de relevante tekst afgekort en teruggegeven. De vergelijking met de
kernwoorden levert het gezochte kleur op die dan met behulp van de Crossfade-
library wordt ingevoegd. Een makkelijker verzoek, in vergelijking, met niettemin
een groot woweffect.
5.6 | Twitter-brandmelder met TalkBack-functie
Dit brandmelderproject verbindt twee elementen die u in de loop van het werken
met het leerpakket hebt leren kennen. Het board wordt onder andere ingezet voor
een langdurige bewaking van de temperatuur. Tegelijk kan het board een alarm-
signaal uitgeven wanneer de temperatuur een bepaalde waarde overschrijdt, bv.
omdat er brand ontstaat. Daarbij is de bewaking van de drempeloverschrijding dit
keer niet de taak van het board, maar van de ThingSpeak-app React.
Voor de brandmelder wordt dit keer de anders uitsluitend als lichtsensor-alternatief
voorgestelde NTC (Negative Temperature Coefficient) als sensor gebruikt. Deze
wijzigt zijn weerstand afhankelijk van de temperatuur. Man kan deze goed tegen
een weerstand van 10 kOhm schakelen, maar in
dit geval werd de potentiometer gebruikt aange-
zien men zo de meting noch kan afstellen.
Benodigde elementen
1 x breadboard, 1 x NanoESP, 1 x potentiometer, 1 x Pi-
ezo, 1 x NTC, 1 x RGB-LED, draadbrug
De opbouw van het brandmelderproject
Het programma
Het programma moet meerdere verschillende elementen met elkaar verenigen.
Daarbij speelt de ThingSpeak-site opnieuw een belangrijke rol. Onder andere
wordt deze keer ook de drempelbewaking van de NTC door een ThingSpeak-app
overgenomen. Van daaruit worden dan ook de alarmfuncties uitgevoerd, namelijk
een Twitter-bericht verzonden en een TalkBack-commando ingevoerd, dat op de
controller het alarm activeert.
In de eerste stap moet u op de ThingSpeak-site een nieuw kanaal aanmaken. Dit
kunt u bijvoorbeeld FireAlarm noemen. Het field 1 krijgt dan de omschrijving
Temp. Onder API Key vindt u de eerste sleutel die u voor ThingSpeakKEY moet
invoeren. Zo wordt reeds de overdracht van de huidige temperatuurwaarde gega-
randeerd.
Als tweede stap moet u een nieuw TalkBack-element aanmaken. Als naam kunt u
bijvoorbeeld Alarms gebruiken. Bovendien kunt u de commando's in het Channel
FireAlarm laten loggen.@ De API-key moet u na TalkBackKEY en de ID na Talk-
BackID invoeren. Nu kunt u ook reeds commando's naar het board verzenden. U
kunt commando's ook manueel invoeren door in het TalkBack-overzicht de Alarm-
channels op Add a new Command te klikken en daar onder Command String Alarm
in te voeren. Het is niet nodig de positie aan te geven aangezien het bevel automa-
tisch op de eerste plaats wordt opgeslagen. U kunt het programma nu reeds uploa-
den en testen of de overdracht van de actuele temperatuurwaarde functioneert en of
het board de commando's uitvoert. Hier is het de moeite om met een kamerthermo-
meter de NTC via de potentiometer te kalibreren.
In principe is dit reeds een volwaardig project, maar de bonusfuncties ontbreken
nog. Deze moeten alleszins niet meer in het programma worden uitgevoerd, maar
alleen nog op de ThingSpeak-
-site. Daarvoor gaat u naar Apps en kiest u vervolgens React . Met React kan op
bepaalde gebeurtenissen worden gereageerd. Maak een nieuwe New React -
functie aan door op React te klikken en voer de volgende waarden in:
Name: FireDetect1
Condition Type: Numeric
Test Frequency: On Data Insertion
Condition: If Channel
FireAlarm
field 1 (Temp)
is greater than
40
Action: ThingTweet
then tweet:
Fire Alarm on the #NanoESP! Temp: %%trigger%%C
#ThingSpeak #IoT
Using Twitter Account
[Twitter Account]
Options: Run action only the first time the condition is met
Met Save React slaat u de instellingen op. Daarmee is de eerste stap van de be-
waking reeds uitgevoerd. Wanneer de waarde wordt overschreden, zendt
ThingSpeak via uw account een Twitter-bericht. Voor de tweede stap, het invoeren
van het alarmcommando, moet u nog een beetje dieper in de trukendoos grijpen,
aangezien de functie niet automatisch wordt ondersteund. Wat ondersteund wordt,
is ThingHTTP. Klik dus op Apps en dan op ThingHTTP. Daar maakt u een nieuw
element aan en stelt u het volgende in.
Name: Alarm
URL: https://api.thingspeak.com/talkbacks/[YOUR
TALKBACK ID]/commands
Method: POST
HTTP-versie: 1.1
Host: api.thingspeak.com
Headers:
Body: api_key=[YOUR TALKBACK ID]Key com-
mand_string=Alarm&position=1
Let op dat u [YOUR TALKBACK ID] en [YOUR TALKBACK KEY] in de URL en in
het body-part door uw TalkBack ID en uw KEY vervangt. Nu kunt u een ander
React-element aanmaken dat dezelfde parameters zoals het eerste bevat, maar
met dit verschil dat u bij Action ThingHTTP en daar het punt Alarm selecteert.
Daarmee hebt u gegarandeerd dat een alarm weerklinkt wanneer de kritische
waarde overschreden wordt.
U kunt overigens ook het alarm tijdsgestuurd laten weerklinken. Daarvoor klikt u
onder Apps op TimeControl klikken en maakt u een nieuw element, bv. met de
naam AlarmClockaan. Daar voert u de volgende instellingen uit:
Name: Presents
Frequency: One Time
Time Zone: Berlin
Run At: 2015-24-12 7:00 am
Fuzzy Time: ± 0 minutes
TalkBack: Alarms, add command: Alarm
De juiste TalkBack-instellingen voor het brandalarm
Voor een eerste test is het aangewezen om een tijdstip in een paar minuten te
kiezen. Wanneer dit gefunctioneerd heeft, kan men het juist tijdstip instellen. Het is
beslist niet het mooiste geluid om gewekt te worden, maar in elk geval bijzonder
doeltreffend.
APPENDIX
AT-commando's
Bevel
Schrijfwijze
Testbevel
AT
Reset
AT+RST
Firmware-info
AT+GMR
Echo Aab/Uit
ATE<1/0>
WLAN-modus
(1 = Client, 2 = AP, 3 = Dual)
AT+CWMODE=<mode>
WLAN-netwerken zoeken
AT+CWLAP
WLAN verbinden
AT+CWJAP=«<ssid>«,«<pass
WLAN verbreken
AT+CWQAP
WLAN-Access-Point-instellingen
AT+CWSAP=«<ssid>«,«<pas
s>«[,<chan>,<enc>]
IP-adres uitgeven
AT+CIFSR
DHCP activeren/deactiveren
AT+CWDHCP=<1/0>
Automatisch met WLAN verbinden
AT+CWDHCP=<1/0>
MAC-adres van het station wijzigen
AT+CIPSTAMAC=<MAC>
IP-adres instellen (station)
AT+CIPSTA=<IP>
IP-adres instellen (Access Point)
AT+CIPAP=<IP>
Starte SmartConfig
AT+CWSTARTSMART=<typ>
Stoppe SmartConfig
AT+CWSTOPSMART
Functie Ping
AT+PING=<HOST>
Meerdere verbindingen toelaten
AT+CIPMUX=<mode>
Datamodus
(0=transparant, 1=datamodus)
AT+CIPMODE=<mode>
Structuur van de ontvangen gege-
vens
+IPD,<id>,<len>:<data>
Verbinding maken
AT+CIPSTART=«<type>«,«<a
ddress>«,<port>
Data verzenden
AT+CIPSEND=<id>,<len>
Verbinding verbreken
AT+CIPCLOSE=<id>
Server starten
AT+CIPSERVER=1,<port>
Server beëindigen
AT+CIPSERVER=0
Serverstatus & verbonden clients
AT+CIPSTATUS
Server time-out vastleggen
AT+CIPSTO=<timeout>
Verbonden clients weergeven
AT+CWLIF
Pinout
  • Page 1 1
  • Page 2 2
  • Page 3 3
  • Page 4 4
  • Page 5 5
  • Page 6 6
  • Page 7 7
  • Page 8 8
  • Page 9 9
  • Page 10 10
  • Page 11 11
  • Page 12 12
  • Page 13 13
  • Page 14 14
  • Page 15 15
  • Page 16 16
  • Page 17 17
  • Page 18 18
  • Page 19 19
  • Page 20 20
  • Page 21 21
  • Page 22 22
  • Page 23 23
  • Page 24 24
  • Page 25 25
  • Page 26 26
  • Page 27 27
  • Page 28 28
  • Page 29 29
  • Page 30 30
  • Page 31 31
  • Page 32 32
  • Page 33 33
  • Page 34 34
  • Page 35 35
  • Page 36 36
  • Page 37 37
  • Page 38 38
  • Page 39 39
  • Page 40 40
  • Page 41 41
  • Page 42 42
  • Page 43 43
  • Page 44 44
  • Page 45 45
  • Page 46 46
  • Page 47 47
  • Page 48 48
  • Page 49 49
  • Page 50 50
  • Page 51 51
  • Page 52 52
  • Page 53 53
  • Page 54 54
  • Page 55 55
  • Page 56 56
  • Page 57 57
  • Page 58 58
  • Page 59 59
  • Page 60 60
  • Page 61 61
  • Page 62 62
  • Page 63 63
  • Page 64 64
  • Page 65 65
  • Page 66 66
  • Page 67 67
  • Page 68 68
  • Page 69 69
  • Page 70 70
  • Page 71 71
  • Page 72 72
  • Page 73 73
  • Page 74 74
  • Page 75 75
  • Page 76 76
  • Page 77 77
  • Page 78 78
  • Page 79 79
  • Page 80 80
  • Page 81 81
  • Page 82 82
  • Page 83 83
  • Page 84 84
  • Page 85 85
  • Page 86 86
  • Page 87 87
  • Page 88 88
  • Page 89 89
  • Page 90 90

Conrad Components 10215 Profi Lernpaket Internet of Things Course material 14 years and over Handleiding

Type
Handleiding