INHOUDSOPGAWE:

DuvelBot - ESP32 -CAM Bierbedieningsrobot: 4 stappe (met foto's)
DuvelBot - ESP32 -CAM Bierbedieningsrobot: 4 stappe (met foto's)

Video: DuvelBot - ESP32 -CAM Bierbedieningsrobot: 4 stappe (met foto's)

Video: DuvelBot - ESP32 -CAM Bierbedieningsrobot: 4 stappe (met foto's)
Video: Трактористы (комедия, реж. Иван Пырьев, 1939 г.) 2024, Junie
Anonim
DuvelBot - ESP32 -CAM Bierbedieningsrobot
DuvelBot - ESP32 -CAM Bierbedieningsrobot

Na 'n harde dag se werk, is daar niks om u gunsteling bier op die bank te drink nie. In my geval is dit die Belgiese blonde ale "Duvel". Na alles wat in duie stort, word ons egter met 'n baie ernstige probleem gekonfronteer: die yskas met my Duvel is 'n onoorbrugbare 20 voet van die bank verwyder.

Terwyl 'n ligte dwang van my kant af en toe 'n yskas -afraaier van tyd tot tyd kan laat beweeg om my week se toelae van Duvel uit te gooi, is die taak om dit eintlik aan sy byna uitgeputte stamvader te lewer, natuurlik 'n stap te ver.

Tyd om die soldeerbout en die sleutelbord uit te breek …

DuvelBot is 'n eenvoudige, op die internet gebaseerde AI-Denker ESP32-CAM-bestuurde webkamera wat u vanaf u slimfoon, blaaier of tablet kan beheer.

Dit is maklik om hierdie platform aan te pas of uit te brei na minder alkoholiese gebruike (dink SpouseSpy, NeighbourWatch, KittyCam …).

Ek het hierdie robot hoofsaaklik gebou om 'n bietjie te leer oor die hele webprogrammering en IoT -dinge, waarvan ek niks geweet het nie. Aan die einde van hierdie Instructable is 'n uitgebreide verduideliking van hoe dit werk.

Baie dele van hierdie instruksies is gebaseer op die uitstekende verduidelikings wat by Random Nerd -tutoriale gevind word, dus besoek hulle gerus!

Voorrade

Wat jy nodig het:

Die onderdele -lys is nie in klip gekerf nie, en baie dele kan in verskillende weergawes en op verskillende plekke verkry word. Ek het die meeste by Ali-Express aangeskaf. Soos Machete gesê het: improviseer.

Hardeware:

  • AI Denker ESP32-CAM module. Dit kan waarskynlik met ander ESP32-CAM-modules werk, maar dit is wat ek gebruik het
  • L298N motorbestuurderbord,
  • 'N Goedkoop robotika-platform met vier wiele,
  • 'N Behuising met 'n groot plat oppervlak, soos die Hammond Electronics 1599KGY,
  • USB-tot-3.3V-TTL-omskakelaar vir programmering.
  • Vir die beligting: 3 wit LED's, BC327 of ander algemene transistor NPN (Ic = 500mA), 4k7k weerstand, 3 82Ohm weerstande, perfboard, kabels (sien skema en foto's).
  • 'N Aan/uit-skakelaar en 'n normaal oop knoppie vir programmering.

Opsioneel:

  • 'N Visoogkamera met langer buiging as die standaard OV2460-kamera wat by die ESP32-CAM-module voorsien word,
  • WiFi -antenna met 'n gepaste lang kabel en 'n ultra miniatuur koaks aansluiting, soos hierdie. Die ESP32-CAM het 'n ingeboude antenna en die behuizing is van plastiek, so 'n antenna is nie regtig nodig nie, maar ek het gedink dit lyk cool, so …
  • Inkjet -afdrukbare plakpapier vir die ontwerp van die voorblad.

Die gewone hardeware gereedskap: soldeerbout, bore, skroewedraaiers, tang …

Stap 1: Bou die robotplatform

Die bou van die robotplatform
Die bou van die robotplatform
Die bou van die robotplatform
Die bou van die robotplatform
Die bou van die robotplatform
Die bou van die robotplatform

Die skematiese:

Die skema is niks besonders nie. Die ESP32-nok bestuur die motors via die L298N-motorbestuurderbord, wat twee kanale het. Motors aan die linker- en regterkant word parallel geplaas en elke kant beslaan een kanaal. Vier klein 10..100nF keramiek kondensators naby die motorpenne is soos altyd raadsaam om RF -inmenging teë te werk. 'N Groot elektrolitiese kap (2200 … 4700uF) op die motor se bord soos aangedui in die skema, maar dit is nie streng nodig nie, maar dit kan ook die rimpeling van die voedingsspanning 'n bietjie beperk (as u 'n gruwelfilm wil sien, moet u Vbat ondersoek met 'n ossilloskoop terwyl die motors aktief is).

Let daarop dat beide motorkanale ENABLE-penne aangedryf word deur dieselfde pulswydte gemoduleerde (PWM) pen van die ESP32 (IO12). Dit is omdat die ESP32-CAM-module nie baie GPIO's bevat nie (die skematiese module is vir verwysing ingesluit). Die LED's van die robot word aangedryf deur IO4, wat ook die ingeboude flits -LED aandryf, dus verwyder Q1 om te voorkom dat die flits -LED in 'n geslote behuizing brand.

Onder die robot is 'n programmeerknop, aan/uit -skakelaar, laaikonnektor en programmeringskonneksie toeganklik. Ek kon 'n baie beter werk vir die programmeringskonneksie gedoen het (3,5 mm -aansluiting?), Maar die bier kon nie meer wag nie. Dit is ook goed om op-die-lug-opdaterings (OTA) op te stel.

Om die robot in die programmeermodus te plaas, druk die programmeerknoppie (dit neem IO0 laag) en skakel dit dan aan.

Belangrik: om die NiMH -batterye van die robot te laai, gebruik 'n laboratoriumtoevoerstel (afgelaai) tot ongeveer 14V en stroom beperk tot 250mA. Die spanning sal aanpas by die spanning van die batterye. Ontkoppel as die robot warm voel of die batteryspanning ongeveer 12,5V bereik. 'N Duidelike verbetering hier sou wees om 'n behoorlike laaier te integreer, maar dit is buite die omvang van hierdie instruksies.

Die hardeware:

Sien ook die aantekeninge op die foto's. Die behuising word op die robotbasis gemonteer met behulp van 4 M4-boute en selfsluitende moere. Let op die rubberbuis wat as afstandhouers gebruik word. Hopelik gee dit ook 'n mate van skorsing aan die Duvel, as die rit hobbelig sou wees. Die ESP32-CAM-module en L298N-motorbord word met kleefvoete van plastiek in die behuizing gemonteer (nie seker of die regte naam in Engels is nie), om te verhoed dat ekstra gate geboor moet word. Die ESP32 is ook gemonteer op sy eie perfboard en steekbare kopkop. Dit maak dit maklik om die ESP32 uit te ruil.

Moenie vergeet nie: as u met 'n eksterne WiFi-antenna in plaas van die ingeboude een gaan, soldeer dan ook die antenne-seleksie-trui aan die onderkant van die ESP32-CAM-bord.

Druk die boonste logo in die lêer DuvelBot.svg uit op inkjetplakkerpapier (of ontwerp u eie), en u is gereed!

Stap 2: Programmeer die robot

Program die robot
Program die robot

Dit is raadsaam om die robot te programmeer voordat u dit toemaak, om seker te maak dat alles werk en geen magiese rook verskyn nie.

U benodig die volgende sagteware -instrumente:

  • Die Arduino IDE,
  • Die ESP32 -biblioteke, SPIFFS (seriële perifere flash -lêerstelsel), ESPAsync Webserver -biblioteek.

Laasgenoemde kan geïnstalleer word deur hierdie ewekansige tutoriaal te volg tot en met die afdeling "organisering van u lêers". Ek kon dit regtig nie beter verduidelik nie.

Die kode:

My kode kan gevind word op:

  • 'N Arduino -skets DuvelBot.ino,
  • 'N Data -subgids wat die lêers bevat wat met behulp van SPIFFS na die ESP -flits opgelaai gaan word. Hierdie gids bevat die webbladsy wat die ESP sal bedien (index.html), 'n logo -beeld wat deel uitmaak van die webblad (duvel.png) en 'n kaskade stylblad of CSS -lêer (style.css).

Om die robot te programmeer:

  • Koppel die USB-TTL-omskakelaar aan soos in die skema getoon,
  • Lêer -> Maak oop -> gaan na die gids waar DuvelBot.ino is.
  • Verander u netwerkbewyse in die skets:

const char* ssid = "yourNetworkSSIDHere"; const char* password = "yourPasswordHere";

  • Tools -> Board -> "AI -Thinker ESP -32 CAM" en kies die toepaslike seriële poort vir u rekenaar (Tools -> Port -> iets soos /dev /ttyUSB0 of COM4),
  • Maak die seriële monitor in die Arduino IDE oop, terwyl u op die PROG -knoppie druk (wat IO0 laag trek), skakel die robot aan,
  • Kyk op die seriële monitor of die ESP32 gereed is om af te laai,
  • Sluit die seriële monitor (anders misluk die oplaai van SPIFFS),
  • Gereedskap -> "ESP32 Sketch Data Upload" en wag totdat dit klaar is,
  • Skakel aan en weer aan met die PROG -knoppie om terug te keer na die programmeermodus,
  • Druk op die "Upload" -pyltjie om die skets te programmeer en wag totdat dit klaar is,
  • Maak die seriële monitor oop en stel die ESP32 terug deur aan/uit te skakel,
  • Sodra dit begin is, let op die ip-adres (iets soos 192.168.0.121) en ontkoppel die robot van die USB-TTL-omskakelaar,
  • Maak 'n blaaier oop by hierdie ip -adres. U moet die koppelvlak sien soos in die prentjie.
  • Opsioneel: stel die mac-adres van die ESP32 in op 'n vaste ip-adres in u router (hang af van hoe u dit moet doen).

Dis dit! Lees verder as u wil weet hoe dit werk …

Stap 3: Hoe dit werk

Nou kom ons by die interessante deel: hoe werk dit alles saam?

Ek sal probeer om dit stap -vir -stap te verduidelik, maar hou in gedagte dat Kajnjaps nie 'n spesialis is in webprogrammering nie. Om 'n bietjie webprogrammering te leer, was eintlik die hele uitgangspunt van die bou van DuvelBot. As ek duidelike foute maak, laat 'n opmerking!

Oké, nadat ESP32 aangeskakel is, word die GPIO's, soos gewoonlik in die opstelling, geïnitialiseer, gekoppel aan PWM -timers vir motor- en LED -beheer. Kyk hier vir meer inligting oor die motorbeheer, dit is redelik standaard.

Dan word die kamera gekonfigureer. Ek het die resolusie doelbewus redelik laag gehou (VGA of 640x480) om trae reaksie te vermy. Let op dat die AI-Thinker ESP32-CAM-bord 'n seriële ram-chip (PSRAM) het wat dit gebruik om kamerarame met 'n groter resolusie te stoor:

if (psramFound ()) {Serial.println ("PSRAM gevind."); config.frame_size = FRAMESIZE_VGA; config.jpg_quality = 12; config.fb_count = 2; // aantal framebuffers sien: https://github.com/espressif/esp32-camera} anders {Serial.println ("geen PSRAM gevind nie."); config.frame_size = FRAMESIZE_QVGA; config.jpg_quality = 12; config.fb_count = 1; }

Dan word die seriële perifere flitslêerstelsel (SPIFFS) geïnisialiseer:

// initialiseer SPIFFS as (! SPIFFS.begin (true)) {Serial.println ("'n Fout het voorgekom tydens die montering van SPIFFS!"); terugkeer; }

SPIFFS werk soos 'n klein lêerstelsel op die ESP32. Hier word dit gebruik om drie lêers te stoor: die webblad self index.html, 'n kaskade -lêerstylblad style.css en 'n-p.webp

Vervolgens maak die ESP32 verbinding met u router (vergeet nie om u geloofsbriewe in te stel voordat u dit oplaai):

// verander die geloofsbriewe van u router hereconst char* ssid = "yourNetworkSSIDHere"; const char* password = "yourPasswordHere"; … // maak verbinding met WiFi Serial.print ("Koppel aan WiFi"); WiFi.begin (ssid, wagwoord); terwyl (WiFi.status ()! = WL_CONNECTED) {Serial.print ('.'); vertraging (500); } // nou aan die router gekoppel: ESP32 het nou 'n ip -adres

Om iets nuttigs te doen, begin ons 'n asynchrone webbediener:

// skep 'n AsyncWebServer -voorwerp op poort 80AsyncWebServer -bediener (80); … bediener. begin (); // begin luister na verbindings

As u nou die ip -adres wat deur die router aan die ESP32 toegeken is, in die adresbalk van die blaaier invoer, kry die ESP32 'n versoek. Dit beteken dat dit op die kliënt (u of u blaaier) moet reageer deur dit iets te bedien, byvoorbeeld 'n webblad.

Die ESP32 weet hoe om te reageer, want tydens die opstelling is die antwoorde op alle moontlike toegelate versoeke geregistreer met behulp van server.on (). Die hoofwebblad of indeks (/) word byvoorbeeld so hanteer:

server.on ("/", HTTP_GET, (AsyncWebServerRequest *versoek) {Serial.println ("/versoek ontvang!"); versoek-> stuur (SPIFFS, "/index.html", String (), false, verwerker);});

As die kliënt dus verbind, reageer die ESP32 deur die lêer index.html vanaf die SPIFFS -lêerstelsel te stuur. Die parameterverwerker is die naam van 'n funksie wat die html vooraf verwerk en spesiale etikette vervang:

// Vervang plekhouers in die html soos %DATA %// deur die veranderlikes wat u wil wys //

Data: %DATA %

Stringverwerker (const String & var) {if (var == "DATA") {//Serial.println("in verwerker! "); retourreeks (dutyCycleNow); } retourreeks ();}

Laat ons nou die webwerf index.html self deaktiveer. Oor die algemeen is daar altyd drie dele:

  1. html -kode: watter elemente moet vertoon word (knoppies/teks/skuifbalk/beelde, ens.),
  2. stylkode, hetsy in 'n aparte.css -lêer of in 'n … afdeling: hoe die elemente moet lyk,
  3. javascript a … afdeling: hoe die webblad moet optree.

Sodra index.html in die blaaier gelaai is (wat weet dat dit html is vanweë die DOCTYPE -reël), loop dit op hierdie reël:

Dit is 'n versoek vir 'n css -stylblad. Die ligging van hierdie blad word gegee in href = "…". So, wat doen u blaaier? Dit stel weer 'n ander versoek aan die bediener, hierdie keer vir style.css. Die bediener vang hierdie versoek op omdat dit geregistreer is:

server.on ("/style.css", HTTP_GET, (AsyncWebServerRequest *versoek) {Serial.println ("css versoek ontvang"); versoek-> stuur (SPIFFS, "/style.css", "text/css ");});

Netjies huh? Terloops, dit kon href = "/some/file/on/the/other/side/of/the/moon" gewees het, vir al u blaaier wat omgee. Dit sal die lêer net so gelukkig gaan haal. Ek sal nie verduidelik oor die stylblad nie, aangesien dit net die voorkoms beheer, dus dit is nie regtig interessant hier nie, maar as u meer wil leer, kyk dan na hierdie tutoriaal.

Hoe verskyn die DuvelBot -logo? In index.html het ons:

waarop die ESP32 reageer met:

server.on ("/duvel", HTTP_GET, (AsyncWebServerRequest *versoek) {Serial.println ("versoek vir duvel-logo ontvang!"); versoek-> stuur (SPIFFS, "/duvel.png", "image-p.webp

.. 'n ander SPIFFS -lêer, hierdie keer 'n volledige beeld, soos aangedui deur 'image/png' in die antwoord.

Nou kom ons by die baie interessante deel: die kode vir die knoppies. Kom ons fokus op die VOORUIT -knoppie:

VOORUIT

Die class = "…" naam is slegs 'n naam om dit aan die stylblad te koppel om die grootte, kleur, ens aan te pas. Die belangrike dele is onmousedown = "toggleCheckbox ('forward')" en onmouseup = "toggleCheckbox ('stop') ". Dit vorm die aksies van die knoppie (dieselfde vir ontouchstart/ontouchend, maar daarvoor is raakskerms/telefone). Hier noem die knoppie -aksie 'n funksie toggleCheckbox (x) in die javascript -afdeling:

funksie toggleCheckbox (x) {var xhr = nuwe XMLHttpRequest (); xhr.open ("GET", "/" + x, true); xhr.send (); // kan ook iets met die reaksie doen as ons gereed is, maar ons doen dit nie}

Deur op die vorentoe -knoppie te druk, word die skakelaar onmiddellik aangeskakel ('vorentoe'). Hierdie funksie begin dan 'n XMLHttpRequest "GET", van die ligging "/forward", wat optree net soos as u 192.168.0.121/forward in die adresbalk van u blaaier sou getik het. Sodra hierdie versoek by die ESP32 kom, word dit hanteer deur:

server.on ("/forward", HTTP_GET, (AsyncWebServerRequest *versoek) {Serial.println ("ontvang/vorentoe"); actionNow = FORWARD; request-> send (200, "text/plain", "OK forward. ");});

Nou antwoord die ESP32 eenvoudig met die teks "OK vorentoe". Let op toggleCheckBox () doen niks met (of wag) op hierdie antwoord nie, maar dit kan soos later in die kamerakode getoon word.

Op sigself stel hierdie program tydens hierdie reaksie slegs 'n veranderlike aksieNU = VOORUIT, as reaksie op die druk op die knoppie. Hierdie veranderlike, nou in die hoofloop van die program, word gemonitor met die doel om die PWM van die motors te verhoog/omlaag. Die logika is: solank ons 'n aksie het wat nie STOP is nie, ry die motors in die rigting totdat 'n sekere nommer (dutyCycleMax) bereik word. Handhaaf dan die spoed, solank die actionNow nie verander het nie:

leemte lus () {currentMillis = millis (); if (currentMillis - previousMillis> = dutyCycleStepDelay) {// stoor die laaste keer dat u die lus previousMillis = currentMillis uitgevoer het; // mainloop is verantwoordelik om die motors op/af te laat as (actionNow! = previousAction) {// afrit, stop dan, verander dan aksie en verhoog dutyCycleNow = dutyCycleNow-dutyCycleStep; as (dutyCycleNow <= 0) {// as na daling 0 dc is, stel in die nuwe rigting, begin by min dutycycle setDir (actionNow); previousAction = actionNow; dutyCycleNow = dutyCycleMin; }} anders // actionNow == previousAction oprit, behalwe as die rigting STOP is {if (actionNow! = STOP) {dutyCycleNow = dutyCycleNow+dutyCycleStep; as (dutyCycleNow> dutyCycleMax) dutyCycleNow = dutyCycleMax; } anders dutyCycleNow = 0; } ledcWrite (pwmChannel, dutyCycleNow); // pas die motorfiets aan}}

Dit verhoog die snelheid van die motors stadig, in plaas daarvan om net op volle snelheid te begin en die kosbare Duvel te mors. 'N Duidelike verbetering sou wees om hierdie kode na 'n timeronderbrekingsroetine te skuif, maar dit werk soos dit is.

As ons nou die vorentoe -knoppie los, bel u blaaier toggleCheckbox ('stop'), wat lei tot 'n versoek om te kry /stop. Die ESP32 stel actionNow op STOP (en reageer met "OK stop."), Wat die hoofloop inloop om die motors te draai.

Wat van die LED's? Dieselfde meganisme, maar nou het ons 'n skuifbalk:

In die javascript word die instelling van die skuifbalk gemonitor, sodat by elke verandering 'n oproep om "/LED/xxx" te kry plaasvind, waar xxx die helderheidswaarde is waarop die LED's gestel moet word:

var slide = document.getElementById ('slide'), sliderDiv = document.getElementById ("sliderAmount"); slide.onchange = function () {var xhr = nuwe XMLHttpRequest (); xhr.open ("KRY", "/LED/" + hierdie.waarde, waar); xhr.send (); sliderDiv.innerHTML = this.value; }

Let op dat ons document.getElementByID ('slide') gebruik het om die skuifvoorwerp self te kry, waarmee verklaar is en dat die waarde by elke teks na 'n tekselement gestuur word.

Die hanteerder in die skets vang alle helderheidsversoeke op deur '/LED/*' in die hanteerderregistrasie te gebruik. Dan word die laaste deel ('n getal) verdeel en tot 'n int gegiet:

server.on ("/LED/ *", HTTP_GET, (AsyncWebServerRequest *versoek) {Serial.println ("geleide versoek ontvang!"); setLedBrightness ((versoek-> url ()). substring (5).toInt ()); versoek-> stuur (200, "text/plain", "OK Leds.");});

Net soos hierbo beskryf, beheer die radioknoppies veranderlikes wat die PWM -standaard stel, sodat DuvelBot stadig met die bier na u kan ry, versigtig om nie die vloeibare goud te mors nie en vinnig terug kombuis toe om nog iets te gaan haal.

… Hoe word die kamerabeeld opgedateer sonder dat u die bladsy hoef te herlaai? Daarvoor gebruik ons 'n tegniek genaamd AJAX (Asynchrone JavaScript en XML). Die probleem is dat 'n kliënt-bedienerverbinding gewoonlik 'n vaste prosedure volg: kliënt (blaaier) rig versoek, bediener (ESP32) reageer, saak gesluit. Klaar. Niks gebeur meer nie. As ons die blaaier op een of ander manier kon mislei om gereeld opdaterings van die ESP32 aan te vra … en dit is presies wat ons met hierdie stuk javascript sal doen:

setInterval (function () {var xhttp = new XMLHttpRequest (); xhttp.open ("GET", "/CAMERA", true); xhttp.responseType = "blob"; xhttp.timeout = 500; xhttp.ontimeout = function () {}; xhttp.onload = function (e) {if (this.readyState == 4 && this.status == 200) {// sien: https://stackoverflow.com/questions/7650587/using… // https://www.html5rocks.com/en/tutorials/file/xhr2/ var urlCreator = window. URL || window.webkitURL; var imageUrl = urlCreator.createObjectURL (this.response); // skep 'n voorwerp uit die blob document.querySelector ("#camimage"). src = imageUrl; urlCreator.revokeObjectURL (imageurl)}}; xhttp.send ();}, 250);

setInterval neem as parameter 'n funksie en voer dit so gereeld uit (hier een keer per 250ms, wat lei tot 4 rame/sekonde). Die funksie wat uitgevoer word, versoek 'n binêre "blob" by die adres /CAMERA. Dit word hanteer deur die ESP32-CAM in die skets as (uit Randomnerdtutorials):

server.on ("/CAMERA", HTTP_GET, (AsyncWebServerRequest * versoek) {Serial.println ("kameraversoek ontvang!"); camera_fb_t * fb = NULL; // esp_err_t res = ESP_OK; size_t _jpg_buf_len = 0; uint8_ * _jpg_buf = NULL; // maak 'n raam vas fb = esp_camera_fb_get (); as (! fb) {Serial.println ("Raambuffer kon nie verkry word nie"); return;} if (fb-> formaat! = PIXFORMAT_JPEG)/ /reeds in hierdie formaat van config {bool jpeg_converted = frame-j.webp

Die belangrikste dele is om die raam fb = esp_camera_fb_get () om te skakel na 'n-j.webp

Die javascript -funksie wag dan totdat hierdie beeld kom. Dan verg dit net 'n bietjie werk om die ontvangen "blob" om te skakel in 'n url waarmee u die beeld op die html -bladsy kan opdateer.

Sjoe, ons is klaar!

Stap 4: Idees en oorskiet

Idees en oorskiet
Idees en oorskiet

Die doel van hierdie projek was vir my om net genoeg webprogrammering te leer om hardeware op die internet te koppel. Verskeie uitbreidings aan hierdie projek is moontlik. Hier is 'n paar idees:

  • Implementeer 'regte' kamerastroom soos hier en hier verduidelik en skuif dit na 'n 2de bediener soos hier op dieselfde ESP32 verduidelik, maar op die ander CPU -kern, en voer dan die kamerastroom in die html bedien deur die 1ste bediener met 'n …. Dit behoort vinniger kamera -opdaterings tot gevolg te hê.
  • Gebruik die toegangspunt (AP) -modus, sodat die robot meer selfstandig is, soos hier verduidelik.
  • Brei uit met batteryspanningsmeting, diep slaapfunksies, ens. Dit is tans 'n bietjie moeilik omdat die AI-Denker ESP32-CAM nie baie GPIO's het nie; benodig uitbreiding via uart en byvoorbeeld 'n slawe -arduino.
  • Skakel oor na 'n kat-soekende robot wat van tyd tot tyd kattekoekies uitstoot deur op 'n groot knoppie te druk, stroom gedurende die dag tonne lekker katfoto's …

Lewer kommentaar as u daarvan hou of vrae het, en dankie dat u gelees het!

Aanbeveel: