De Programmeerbare Plantenkas: De Kas Verwarmen Met Verwarmingsmatten

DE PROGRAMMEERBARE PLANTENKAS: DE KAS VERWARMEN MET VERWARMINGSMATTEN

De zaden van warmteminnende planten, zoals citrussen, paprika's en tomaten, ontkiemen beter wanneer de aarde waarin ze gezaaid worden warm is. De optimale bodemtemperatuur voor de ontkieming van deze zaden ligt vaak ergens tussen de 25 en 35 graden Celsius. Tenzij je de verwarming héél hoog zet, wordt de zaaigrond zelfs als je binnen in huis zaait niet zo warm. Om de warmteminnende planten sneller en krachtiger te laten ontkiemen, kun je deze planten daarom in een klein kweekkasje zaaien die je van verwarmingsmatten voorziet. In de nacht en op bewolkte dagen, wanneer de zon de kas onvoldoende opwarmt, kun je de verwarmingsmatten aanzetten om de temperatuur te verhogen. In deze tutorial vertellen we hoe je verwarmingsmatjes aansluit en programmeert om een vensterbankkas tot een vooraf ingestelde temperatuur te verwarmen.

Aansluiten

In dit voorbeeld gebruiken we twee verwarmingsmatjes van Sparkfun of Adafruit. Deze matjes zijn 10 centimeter lang en 5 centimeter breed. Ze zijn gemaakt van twee aansluitdraden met daartussen weerstandsdraad. De matjes zijn omhuld in geelkleurig kapton, een hittebestendig kunststof.

Wanneer je met deze verwarmingsmatjes gaat experimenteren kom je er al snel achter dat ze erg gevoelig zijn. Gebruik je een te zwakke voeding, dan gebeurt er bijna niets, terwijl een sterkere voeding de verwarmingsmatjes binnen een zeer korte tijd gevaarlijk heet maakt. Voordat je zaaibakken met kostbare zaadjes op de de verwarmingsmatjes legt, is het belangrijk om eerst wat meer te weten te komen over het specifieke matje dat je gaat gebruiken. Hiervoor kun je het beste eerst de datasheet van de verwarmingsmat doorlezen.

Door het lezen van de datasheet van de specifieke verwarmingsmat die wij gebruiken, van 10 centimeter bij 5 centimeter, weten we dat deze verwarmingsmat met een weerstand van ongeveer 8,5 Ohm, ongeveer 0,8 ampère verbruikt als de mat aangesloten is op een voeding van 5 volt. Bij een voeding van 5 volt kan er de mat volgens de datasheet maximaal 42 graden Celsius worden. In dit voorbeeld worden twee van deze verwarmingsmatjes in serie aan elkaar verbonden. Om er voor te zorgen dat de matjes niet te heet kunnen worden, maar wel warm genoeg, hebben we ze in dit voorbeeld op een relais aangesloten die weer aangesloten is op een 12 volt adapter die 1,8 ampère levert. Per matje zou er dan dus ongeveer 0,9 ampère beschikbaar zijn, en zal de maximale temperatuur die de verwarmingsmatjes kunnen behalen net iets boven de 42 graden Celsius liggen.

verwarmingsmat
Verwarmingsmatten zijn gemaakt van weerstandsdraad en twee aansluitdraden.

Er zijn twee manieren om de temperatuur van een verwarmingsmatje te regelen: Je kunt de matjes aansluiten op een MOSFET en dan afhankelijk van het verschil tussen de werkelijke en de gewenste temperatuur kleiner of grotere pulsen naar de verwarmingsmatjes te sturen. Het nadeel hiervan is dat de verwarmingsmatjes meer dan 1 ampère gebruiken, waardoor de MOSFET gekoeld zou moeten worden. Aangezien we voor dit project geen extreme precisie nodig hebben, hebben we er daarom voor gekozen om een relais te gebruiken die alleen maar aan of uit gestuurd kan worden. Door de matjes niet te lang achter elkaar aan te zetten, voorkomen we dat de verwarmingsmatjes te warm worden voor de zaaibakken.

De verwarmingsmatjes die wij gebruiken zijn voorzien van twee korte aansluitdraden. Voor onze vensterbankkas, van IKEA, zijn deze draden te kort, dus verlengen we alle aansluitdraden eerst. Dit doen we met behulp van soldeerhulzen, omdat deze de draden niet alleen door middel van soldeertin aan elkaar vast zetten, maar de verbinding ook meteen een waterdichte huls voorzien. Uiteraard kun je er ook voor kiezen om de draden eerst aan elkaar vast te solderen, en daarna een krimpkous om de verbinding te doen.

verwarmingsmat, arduino, kasverwarming
Verleng de aansluitkabels van de verwarmingsmatten met soldeerhulzen. De lengte van de draden is afhankelijk van de plek waar de matten komen.
verwarmingsmat, arduino, kasverwarming
Door het gebruik van soldeerhulzen, zijn de verbindingen waterdicht, wat een must is als de verwarmingsmatten op een natte plek komen.

In dit voorbeeld werken we met twee verwarmingsmatten, die in serie aan elkaar verbonden zijn. Om dit te doen gebruiken we weer een soldeerhuls. Aan de ene kant van de soldeerhuls steken we de twee verlengde, rode draden van de twee verwarmingsmatjes. Aan de andere kant van de soldeerhuls steken we een nieuwe, rode draad die we later op de relais aansluiten. Als dit gelukt is, dan doen we hetzelfde met de zwarte draden.

verwarmingsmat, arduino, kasverwarming
Om de rode draden aan elkaar vast te maken, verbinden we de rode draden van de matjes met een nieuwe rode draad.
verwarmingsmat, arduino, kasverwarming
Steek de draden die uit de verwarmingsmatten komen aan de ene kant in de soldeerhuls, en de nieuwe rode draad aan de andere kant.
verwarmingsmat, arduino, kasverwarming
Met een heteluchtpistool smelt je de soldeerhulzen aan elkaar. Gebruik wel een mat die beter bestand tegen hitte is dan op deze foto!

In dit voorbeeld maken we gebruik van een standaard relais van de Grove serie van Seeed Studio. Op deze relais gaan we de rode draad van onze verwarmingsmatjes aansluiten en de rode, positieve, draad van de draad waarop we de voeding aansluiten. De zwarte draad van onze verwarmingsmatjes verbinden we met de zwarte draad van de kabel waarop we de voeding aansluiten. Aangezien we van plan zijn om deze voedingskabel binnenkort voor een ander project te gebruiken, hebben we er deze keer voor gekozen om de zwarte draad van onze verwarmingsmatjes aan de zwarte draad van de voedingskabel te solderen, en te voorzien van isolerende tape. Wanneer je van plan bent om dit project voor een langere tijd te gaan gebruiken, dan is het aan te raden om voor deze verbinding ook een soldeerhuls te gebruiken.

verwarmingsmat, arduino, kasverwarming
De verwarmingsmatten worden uiteindelijk aangesloten op een Grove relay. De zwarte kabel van de verwarmingsmatten wordt aan de aarde draad van de voedingskabel bevestigd.
verwarmingsmat, arduino, kasverwarming
Je kunt de zwarte draad van de verwarmingsmatten door te solderen of met een soldeerhuls vast maken aan de zwarte aarde draad van de voedingskabel.

De rode draad van de kabel waarop we de voeding gaan aansluiten en de rode draad van het verwarmingsmatje schroeven we vast in de twee schroefaansluitingen van de relais. De Grove relais is een "normally open" relays, en heeft maar twee schroefaansluitingen. Andere relays hebben vaak meerdere schroefaansluitingen, waarbij de voeding altijd in dezelfde schroefaansluiting zit, maar de draad van de module die je wilt regelen, in dit geval de verwarmingsmatjes, in een "normally open" of in een "normally closed" schroefaansluiting bevestigd kan worden. Voor dit voorbeeld zou je dan dus kiezen voor de "normally open" schroefaansluiting.

verwarmingsmat, arduino, kasverwarming
De rode kabel van de voedingskabel wordt in één van de twee schroefaansluitingen van het Grove relay ontwikkelaarsbord geschroeft.
verwarmingsmat, arduino, kasverwarming
De rode kabel van de verwarmingsmatten wordt in de andere schroefaansluiting van het Grove relay ontwikkelaarsbord gemonteerd.

De verwarmingsmatjes zouden nu stevig vast moeten zitten aan elkaar, aan de relais en aan de kabel waarop de voeding wordt aangesloten. Als alles op zijn plaats zit, kan het matje worden aangebracht in de kas. Hierna kun je de relais met een Grove kabel aansluiten op een Grove Base Shield, die weer bevestigd is op een Arduino UNO. In dit voorbeeld hebben we de matjes alleen vast geplakt met hittebestendige tape. Eventueel zou je hier bovenop nog een warmtegeleidende plaat kunnen aanbrengen, waardoor de verwarmingsmatjes beter beschermd zijn en waardoor de warmte gelijkmatig over de bodem van de zaaibakken wordt verdeeld.

verwarmingsmat, arduino, kasverwarming
Uiteindelijk zijn de verwarmingsmatjes dus aan elkaar en aan de relay verbonden, die weer verbonden is met de voedingskabel.
verwarmingsmat, arduino, kasverwarming
Voor dit voorbeeld hebben we de verwarmingsmatjes met hittebestendige tape op de bodem van ons kasje bevestigd. De draden passen net tussen de opening van de zijwanden.

Naast het verwarmingsmatje, maken we ook gebruik van een temperatuursensor, in dit geval een Grove DHT11 temperatuur- en luchtvochtigheidssensor, een Grove encoder, en een Grove OLED display. De temperatuursensor sluiten we aan op de D6 aansluiting van de Grove Base Shield, de encoder op de D2 aansluiting en het OLED display op een I2C aansluiting. Het is belangrijk dat de encoder is aangesloten op een pin die een "interrupt" kan uitvoeren. Bij de Arduino UNO is dit pin 2, maar bij andere microcontrollers kan dit een andere pin zijn. Controleer dit dus even voordat je aan de slag gaat.

verwarmingsmat, arduino, kasverwarming
We gebruiken een Grove encoder om het setpunt in te stellen.
verwarmingsmat, arduino, kasverwarming
We meten met een Grove DHT11 temperatuursensor.
verwarmingsmat, arduino, kasverwarming
We tonen de temperatuur op een Grove OLED display

verwarmingsmat, arduino, kasverwarming
De kas wordt door de verwarmingsmatten op de juiste temperatuur gehouden, zodat de zonnebloemzaadjes snel ontkiemen.

Programmeren

In deze tutorial maken we gebruik van de verwarmingsmatjes die op een relay zijn aangesloten, een DHT11 temperatuursensor, een OLED 0,96" display, en een encoder. Met zo veel verschillende onderdelen, is de code die nodig is om de microcontroller alle taken uit te laten voeren ook redelijk lang. We zullen de voorbereiding, de setup, en de aansturing van de verschillende modules daarom één voor één bespreken.

DHT11 TEMPERATUURSENSOR

In dit voorbeeld maken we gebruikt van een DHT11 temperatuursensor om de huidige temperatuur te bepalen. Hoe deze sensor aangesloten en geprogrammeerd kan worden, is uitvoerig besproken in het artikel "De Programmeerbare Plantenkas: De DHT11 Temperatuursensor Aansluiten En Programmeren Om De Temperatuur Te Meten". Het enige verschil met die voorbeeld code, is dat we de temperatuur in dit voorbeeld niet opslaan als een float variabele, ofwel een kommagetal, maar als een heel getal, ofwel een int variabele. Verder is de voorbereiding, waar de bibliotheek wordt ingesteld, de setup fase, waar de communicatie met de sensor aan wordt gezet, de functie die de temperatuur opslaat, en de commando's in de loop, waar de functie voor het opslaan van de temperatuur wordt geactiveerd, hetzelfde als in het artikel "De Programmeerbare Plantenkas: De DHT11 Temperatuursensor Aansluiten En Programmeren Om De Temperatuur Te Meten".

Encoder

Om te weten hoe warm of hoe koud het zou moeten zijn, moeten we de microcontroller vertellen wat onze gewenste temperatuur is. Wanneer de kas altijd dezelfde temperatuur moet hebben, dan kun je deze enkele waarde via een commando zoals #define setpunt 25 in de voorbereidingsfase van de code definiëren.

Wanneer je regelmatig wat anders kweekt, dan kan het handig zijn om het setpunt te kunnen veranderen zonder dat je de microcontroller op de computer hoeft aan te sluiten. In dit voorbeeld hebben wij er voor gekozen om een Grove encoder, ook wel pulsgever genoemd, te gebruiken om het setpunt in te stellen. We gebruiken de Encoder bibliotheek van Paul Stoffregen om de encoder uit te lezen. In de voorbereidingsfase activeren we deze bibliotheek met het commando #include <Encoder.h>. Vervolgens vertellen we de bibliotheek van de encoder op welke pinnen de encoder is aangesloten. Dit doen we met het commando Encoder Enc(2, 3);. In dit voorbeeld is de encoder dus aangesloten op de pinnen D2 en D2. Dit zijn speciale pinnen waarop later de digitalPinToInterrupt functie uitgevoerd kan worden. 

In de voorbereidingsfase moeten we ook nog een aantal variabelen maken en een aantal waardes definiëren voor de encoder. Allereerst maken we twee long variabelen, die het signaal van de encoder op slaan. Dit doen we met de commando's long opslaanPositie = -999; en long setpuntTemperatuur;. We maken ook nog een BOOL variabele, die alleen de waardes "HOOG", ofwel 1, en "LAAG", ofwel 2, kan hebben. We doen dit met het commando bool interrupt = LOW;. Het is belangrijk dat je deze variabele in de voorbereidingsfase niet leeg laat, maar op "LOW" zet, anders kan het programma vast lopen bij het opstarten. Om te voorkomen dat het te heet wordt in de kas, is het aan te raden om een maximum, en eventueel ook een minimum, temperatuur in te stellen. Deze temperaturen slaan we op met de commando's #define maxTemp 35 en #define minTemp 0

In de setup fase geven we het commando attachInterrupt(digitalPinToInterrupt(2), TEMPERATUURKNOP, CHANGE); om de encoder onze loop te laten onderbreken als er aan de knop van de encoder wordt gedraaid.  Zodra de waarde die de encoder naar digitale pin 2 wordt gestuurd veranderd, dan wordt de functie encoderKnop, die we later bespreken, uitgevoerd.

De functie encoderKnop() wordt dus aangeroepen zodra de microcontroller merkt dat er iets in de waarde van digitale pin 2 veranderd. Het doel van deze functie is het bijwerken van het setpunt, op basis hoe er aan de encoder knop is gedraaid. Het eerste wat we in deze functie doen, is de variable interrupt op "HIGH" zetten, met het commando interrupt = HIGH;. Dit zorgt ervoor dat de functies in het loop gedeelte niet worden uitgevoerd wanneer er aan de encoder wordt gedraaid. 

Het volgende commando in de functie is het commando setpuntTemperatuur = Enc.read();. Hiermee leest de bibliotheek het signaal van de encoder uit, en slaat het op in de variabele setpuntTemperatuur. Als blijkt dat deze waarde niet gelijk is aan de vorige waarde van de encoder, dan wordt het setpunt aangepast. Dit doen we door verschillende if-loopen met elkaar te combineren. Allereerst beginnen we met de if-loop if (setpuntTemperatuur != opslaanPositie) {}. Dit zorgt ervoor dat wanneer de waarde in variabele setpuntTemperatuur niet gelijk is aan de waarde in opslaanPositie, de commando's tussen de {} wordt uitgevoerd. Het eerste commando tussen de {} is het commando if (setpuntTemperatuur > maxTemp) {setpuntTemperatuur = maxTemp;}. Deze if-loop zorgt ervoor dat als het setpunt groter is dan de maximum temperatuur, die we in de voorbereiding hebben gedefinieerd, de waarde van de variabele setpuntTemperatuur gelijk is aan de maximum temperatuur. Dit zorgt ervoor dat ook al draai je de encoder twintig keer in de rondte, de temperatuur blijft altijd op de maximum temperatuur staan. Hetzelfde hebben we gedaan voor de minimum temperatuur, met het commando else if (setpuntTemperatuur < minTemp) {setpuntTemperatuur = minTemp;}

Als laatste geven we het commando opslaanPositie = setpuntTemperatuur; in deze functie. Dit commando zorgt ervoor dat de variabele opslaanPositie dezelfde waarde krijgt als setpuntTemperatuur. De volgende keer dat de functie voor de encoder wordt aangeroepen, dan wordt de nieuwe waarde dus met deze waarde vergeleken.

In de loop fase wordt de functie encoderKnop() niet opgeroepen. Dit wordt namelijk automatisch gedaan door ons digitalPinToInterrupt commando die we in de setup fase hebben gegeven. Wel zetten we in de loop fase de variabele interrupt op "LOW" met het commando interrupt = LOW;. Dit zorgt ervoor dat de andere functies in de loop fase weer worden herstart. Dit doen we door voor de verschillende functie het commando if (!interrupt) te plaatsen. 

Verwarmingsmatten

Als de DHT11 temperatuursensor en de encoder knop goed werkt, kunnen de variabelen voor de gemeten temperatuur en de gewenste temperatuur, ofwel het setpunt, gebruikt worden om te bepalen of, en zo ja, hoelang de verwarmingsmatten aangezet moeten worden. Zoals we in het stuk over het aansluiten van die verwarmingsmatjes al hebben verteld, hebben we in dit voorbeeld de verwarmingsmatjes aangesloten op een relais die we aan en uit kunnen zetten. Om de verwarmingsmatjes te bedienen, moeten we eerst weer een aantal waardes opslaan en een variabele maken. Eerst geven we aan op welke pin de relais is aangesloten, met het commando #define VERWARMINGPIN 4. Mocht je de verwarmingsmatjes op een andere digitale pin hebben uitgesloten, dan moet je hier natuurlijk even het nummer wijzigen.

Er zijn vier waardes die we voor de verwarmingsmatten in de voorbereidingsfase definiëren. Allereerst geven we het commando #define schakelVerschil 2. Wanneer de gemeten temperatuur onder het setpunt licht, maar minder dan 2 graden Celsius er vanaf ligt, dan zetten we de verwarmingsmat een kortere tijd aan dan wanneer het verschil groter dan 2 graden Celsius is. Hierdoor is de kans kleiner dat de temperatuur boven het setpunt uit komt.

Daarna definiëren we drie tijden, met de commando’s #define langeTijd 4000, #define korteTijd 2000, en #define wachtTijd 5000. Wanneer het verschil tussen het setpunt en de gemeten temperatuur grover is dan 2 graden Celsius , dan zetten we de verwarmingsmatjes elke keer 4 seconden, ofwel 4000 milliseconden, aan. Als de gemeten temperatuur minder dan 2 graden Celsius onder het setpunt ligt, dan zetten we de verwarmingsmatjes elke keer 2 seconden, ofwel 2000 milliseconden, aan. Als de verwarmingsmatjes na twee of vier seconden weer uit gezet worden, dan wordt er altijd 5 seconden, ofwel 5000 milliseconden, gewacht tot de volgende meting. Hierdoor heeft de temperatuursensor tijd om op te warmen, en is de kans dat de temperatuur boven het setpunt uitkomt kleiner. Het kans zijn dat deze tijden aangepast moeten worden als je met een krachtigere of juist minder krachtigere verwarmingsmat werkt.

Als laatste voorbereiding maken we nog een BOOL variabele aan, met het commando bool verwarmingStatus;. Deze variabele kunnen we later gebruiken om de status van de verwarmingsmat op het display te laten zien.

Het aansturen van de verwarmingsmatten doen we met de functie temperatuurRegelaar(). Deze functie starten we met het commando void temperatuurRegelaar(). In deze functie beginnen we met het bepalen van het verschil tussen de gemeten temperatuur, die uit de temperatuursensor komt, en het setpunt, die met de encoder is ingesteld. Om dit te berekenen, geven we het commando int verschil = setpuntTemperatuur - DHT11gradenC;. Dit maakt een tijdelijke variabele verschil aan die alleen door deze functie wordt gebruikt.

Vervolgens kijken we met een if-loop of het verschil kleiner is dan het verschil dat we in de voorbereiding hebben gedefinieerd. Hiervoor geven we het commando if (verschil < schakelVerschil) {}. Tussen de {} zetten we vervolgens de commando’s die uit gevoerd moeten worden als het verschil kleiner is dan, in dit geval, 2 graden Celsius. Het eerste commando dat we tussen de {} zetten is het commando digitalWrite(VERWARMINGPIN, HIGH);. Hiermee zetten we de relais waarop de verwarmingsmatten aangesloten zijn aan. Vervolgens zetten we ook de variabele verwarmingStatus op HIGH, met het commando verwarmingStatus = HIGH;.

In dit voorbeeld laten we de status van de verwarmingsmatten zien op een OLED display. Daarom geven we als de matjes aan staan het commando OLED(); om de functie die het OLED scherm bediend te activeren. Verderop vertellen we hoe dit werkt. We willen het verwarmingsmatje maar een beperkte tijd aan zetten, om te voorkomen dat de bodem van de zaaibakken te heet worden. Om de tijd dat de verwarmingsmatten aan staan te controleren, geven we het commando delay(korteTijd);, dat er voor zorgt dat er 2 seconden niets gebeurd, vervolgd door het commando digitalWrite(VERWARMINGPIN, LOW);, verwarmingStatus = LOW; en OLED();. Hierdoor wordt het verwarmingsmatje weer uit gezet en wordt de weergave van het OLED scherm weer gewijzigd.

Door de OLED functie aan te zetten tussen het aanzetten van de verwarmingsmatten en het starten van de vertraging, zal er iets meer dan 2 seconden tussen het aanzetten en uitzetten van het matje zit. Om deze extra vertraging van de OLED functie te vermijden, kun je er voor kiezen om de status van de mat nergens weer te geven, of met een led lampje dat je gelijktijdig met de verwarmingsmatten aan en uit zet.

Het laatste commando die wordt uitgevoerd door deze if-loop, is het commando delay(wachtTijd);. Dit zorgt ervoor dat er 5 seconden wordt gewacht voordat het programma weer verder gaat. Op die manier kan de hitte van de verwarmingsmatjes de kas in trekken, en heeft de temperatuursensor tijd om op te warmen.

Als het verschil tussen de gemeten temperatuur groter dan 2 graden Celsius is, dan wort de else if-loop geactiveerd. Deze loop wort gestart met het commando else if (verschil >= schakelVerschil) {}. De commando’s in deze else if-loop zijn hetzelfde als bij de vorige if-loop, alleen is de variabele korteTijd vervangen door de variabele langeTijd.

verwarmingsmat, arduino, kasverwarming
Wanneer de relais aan gaat, dan hoor je een klik en dan zie je het rode lampje branden. Hierdoor kun je de werking van het programma testen zonder dat de verwarmingsmatten op de relais zijn aangesloten.

In de loop fase wordt eerst de temperatuur uit de temperatuursensor gehaald, met het commando if (!interrupt) GROVEDHT11();. Vervolgens bepalen we of de temperatuur onder het setpunt ligt, met het commando if (DHT11gradenC < setpuntTemperatuur) {}. Als de gemeten temperatuur onder het setpunt ligt, dan wordt het commando if (!interrupt) temperatuurRegelaar(); uitgevoerd. Als de gemeten temperatuur gelijk aan of hoger dan het setpunt is, dan gebeurt er niets.

OLEd scherm

Als laatste moeten we nog het OLED display instellen. Het OLED display gebruiken we om de gemeten temperatuur, het setpunt en de status van de verwarmingsmatten weer te geven. Om het OLED display in te stellen, maken we gebruik van twee bibliotheken. Allereerst de OneWire bibliotheek, omdat dit scherm gebruikt maakt van de I2C aansluiting, en de SeeedOLED bibliotheek, die speciaal voor dit display is gemaakt door Seeed Studio. In de voorbereiding laden we deze bibliotheken met de commando’s #include en #include . Verder hoeven we voor het OLED display niets voor te bereiden.

In de setup fase zetten we eerst de communicatie met het OLED scherm aan. Dit doen we met het commando Wire.begin();. Vervolgens gebruiken we een aantal commando’s uit de bibliotheek om het scherm in te stellen. We beginnen met het commando SeeedOled.init(); om het scherm te initialiseren. Daarna geven we het commando SeeedOled.clearDisplay(); om het display leeg te maken, voor het geval er nog wat op stond. Vervolgens geven we het commando SeeedOled.setNormalDisplay(); om het scherm in de normale modus te zetten. Als laatste geven we het commando SeeedOled.setPageMode(); om aan te geven welke methoden we gebruiken om te bepalen wat waar komt op het scherm.

We hebben een aparte functie gemaakt om de gegevens op het OLED scherm te updaten wanneer dit nodig is. Het maken van de functie doen we met het commando void OLED() {}. Wanneer de functie wordt aangeroepen, dan beginnen we met het aangeven wat er op die eerste lijn van het scherm komt. Hiervoor geven we eerst het commando SeeedOled.setTextXY(0, 0);. Dit betekend dat we de cursor op de eerste lijn aan het begin van de lijn zetten. Vervolgens geven we het commando SeeedOled.putString("Temperatuur:”);. Dit zorgt ervoor dat er op de eerste lijn “temperatuur:” komt te staan. Op de volgende lijn zetten we de gemeten temperatuur, die opgeslagen is in de variabele DHT11gradenC, met eerst het commando SeeedOled.setTextXY(1, 0); om aan te geven dat we de cursor aan het begin van de tweede lijn zetten, en dan het commando SeeedOled.putNumber(DHT11gradenC); om aan te geven dat we de waarde van variabele DHT11gradenC willen weergeven.

Hetzelfde doen we voor het setpunt. Hier printen we eerst “Setpunt:” af en daaronder het ingestelde setpunt, met de commando’s SeeedOled.setTextXY(2, 0);, SeeedOled.putString("Setpunt:”);, SeeedOled.setTextXY(3, 0);, en SeeedOled.putNumber(setpuntTemperatuur);.

Als laatste willen we laten zien of de verwarmingsmatten aan of uit staan. Dit doen we door eerst “Verwarming:” af te printen, met het commando SeeedOled.setTextXY(4, 0); en het commando SeeedOled.putString("Verwarming:”);. Vervolgens laten we AAN afprinten als de verwarmingsmatten aan staan. Hiervoor gebruiken we de if-loop if (verwarmingStatus == HIGH) {SeeedOled.setTextXY(5, 0); SeeedOled.putString("AAN”);}, en de else if-loop else if (verwarmingStatus == LOW) {SeeedOled.setTextXY(5, 0); SeeedOled.putString("UIT”);}. Deze twee loops zorgen ervoor dat er AAN wordt geprint als de variabele verwarmingStatus op 1 staat, en dat er UIT wordt geprint als de variabele op 0 staat.

In de loop fase roepen we de OLED functie twee keer aan, eerst nadat de temperatuur voor de eerste keer is opgevraagd uit de temperatuursensor, en daarna nog een keer nadat het verwarmingsmatje eventueel is aangegaan en de temperatuur opnieuw bepaald is. Zo is de temperatuur die op het OLED scherm staat altijd redelijk accuraat.

Arduino IDE code


/*
   Voorbeeld code gemaakt door www.foodplanting.com
   voor de Programmeerbare Plantenkas serie.

   Deze code is gemaakt om de temperatuur in de kas te verhogen
   met een verwarmingsmat (Sparkfun of Adafruit, 10 x 5 cm), op basis van
   de temperatuursensor DHT11. De gewenste temperatuur wordt ingesteld
   via een encoder en de gegevens worden gepresenteerd
   op een Grove OLED b0.96"display.

   Deze code maakt gebruikt van de DHT bibliotheek
   voor de Grove Temperature and Humidity Sensor
   van Seeed Studio.
   Meer info over deze bibliotheek vindt je hier:
   https://github.com/Seeed-Studio/Grove_Temperature_And_Humidity_Sensor
   Deze code maakt ook gebruik van de Encoder
   bibliotheek van Paul Stoffregen.
   Meer info over deze bibliotheek vindt je hier:
   https://github.com/PaulStoffregen/Encoder
   Deze code maakt ook gebruik van de OneWire
   bibliotheek van Paul Stoffregen.
   Meer info over deze bibliotheek vindt je hier:
   https://github.com/PaulStoffregen/OneWire
   Deze code maakt ook gebruik van de SeeedOLED
   bibliotheek van Seeed Studio.
   Meer info over deze bibliotheek vindt je hier:
   https://github.com/Seeed-Studio/OLED_Display_128X64
*/

// Voorbereiding DHT11 temperatuursensor:
#include <DHT.h> // Dit laadt de bibliotheek die nodig is om de temperatuursensor te lezen.
#define DHTPIN 6 // Dit geeft aan op welke digitale input de sensor is aangesloten, in dit geval D6.
#define DHTTYPE DHT11 // Dit geeft aan om wel type DHT sensor het gaat, in dit geval DHT11, maar er zijn ook andere zoals DHT21 en DHT22. 
DHT dht11(DHTPIN, DHTTYPE); // Dit verteld de bibliotheek hoe we de sensor gaan noemen, welke sensor het is en waar hij op aan gesloten is.
int DHT11gradenC; // Dit creëert een globale variabele waarin de gemeten temperatuur wordt opgeslagen.

// Voorbereiding verwarmingsmat:
#define VERWARMINGPIN 4 // Dit geeft aan op welke digitale input de relay van de verwarmingsmat is aangesloten, in dit geval D4.
#define schakelVerschil 2 // Dit geeft aan bij welk verschil tussen het setpunt en de gemeten temperatuur de korte verwarmingstijd en de lange verwarmingstijd in gaat.
#define langeTijd 4000 // Dit geeft aan hoelang de verwarmingsmat aan wordt gezet als het verschil boven het schakel verschil ligt.
#define korteTijd 2000 // Dit geeft aan hoelang de verwarmingsmat aan wordt gezet als het verschil onder het schakel verschil ligt.
#define wachtTijd 5000 // Dit geeft aan hoelang er wordt gewacht nadat de verwarmingsmat weer is uit gezet.
bool verwarmingStatus; // Dit creëert een globale variabele waarin op geslagen wordt of de verwarmingsmat aan of uit staat.

// Voorbereiding encoder:
#include <Encoder.h> // Dit laadt de bibliotheek die nodig is om de encoder te lezen.
Encoder Enc(2, 3);  // Dit geeft aan op welke twee digitale pinnen de encoder de is aangesloten, in dit geval D2 en D2. Kies pinnen die kunnen interrupten.
long opslaanPositie  = -999; // Dit creëert een globale variabele die de vorige positie van de encoder opslaat.
long setpuntTemperatuur; // Dit creëert een globale variabele waarin de gewenste temperatuur wordt op geslagen, die via de encoder gewijzigd kan worden.
bool interrupt = LOW; // Dit creëert een globale variabele waarin we aangeven of de encoder wordt gewijzigd.
#define maxTemp 35 // Dit geeft aan wat de maximale setpunt temperatuur is die ingesteld kan worden.
#define minTemp 0 // Dit geeft aan wat de minimale setpunt temperatuur is die ingesteld kan worden.

// Voorbereiding Grove OLED 0.96" scherm:
#include <Wire.h> // Dit laadt de bibliotheek die nodig is om de OLED te bedienen.
#include <SeeedOLED.h> // Dit laadt de bibliotheek die nodig is om de OLED te bedienen.

// Setup fase:
void setup() {
  pinMode(VERWARMINGPIN, OUTPUT); // Zet de pin waarop de verwarmingsmat is aangesloten in de output modus.
  attachInterrupt(digitalPinToInterrupt(2), encoderKnop, CHANGE); // Zorg dat de encoder het programma onderbreekt als eraan gedraaid wordt.
  dht11.begin(); // Zet de communicatie tussen de microcontroller en de sensor aan.
  Wire.begin();  // Zet de communicatie tussen de microcontroller en de OneWire bibliotheek aan.
  SeeedOled.init(); // Initialiseer het OLED scherm
  SeeedOled.clearDisplay();// Verwijder alles wat nog op het OLED scherm stond.
  SeeedOled.setNormalDisplay(); // Stel het OLED scherm in op de normale modues.
  SeeedOled.setPageMode(); // Stel in hoe we aangeven waar wat op het OLED scherm komt.
}

// Loop fase:
void loop() {
  interrupt = LOW; // Zet de interrupt, die aangaat als er aan de encoder gedraaid wordt, uit.
  if (!interrupt) GROVEDHT11(); // Vraag de microcontroller om de functie die de temperatuur uit de sensor ophaalt uit te voeren.
  // Als de gemeten temperatuur onder het setpoint ligt, dan begint de temperatuurregelaar,
  // anders staat de verwarmingsmat uit.
  if (!interrupt)OLED(); // Update de gegevens op het OLED scherm.
  if (DHT11gradenC < setpuntTemperatuur) {
    if (!interrupt) temperatuurRegelaar(); // Vraag de microcontroller de funcite die de verwarmingsmat aan zet uit te voeren.
  }
  if (!interrupt) GROVEDHT11(); // Vraag de microcontroller om de functie die de temperatuur uit de sensor ophaalt uit te voeren.
  if (!interrupt)OLED(); // Update de gegevens op het OLED scherm.

}

// Functie voor bedienen verwarmingsmat:
void temperatuurRegelaar() {
  int verschil = setpuntTemperatuur - DHT11gradenC; // Maak een tijdelijke variabele met daarin het verschil tussen het setpoint en de gemeten temperatuur.
  // Als het verschil tussen het setpoint en de gemeten temperatuur klein is,
  // dan wordt de mat elke keer een korte tijd aan gezet.
  if (verschil < schakelVerschil) {
    digitalWrite(VERWARMINGPIN, HIGH); // Zet de verwarmingsmat aan.
    verwarmingStatus = HIGH; // Zet de status van de verwarmingsmat die door de OLED wordt gebruikt op "aan".
    OLED(); // Update de gegevens op het OLED scherm.
    delay(korteTijd); // Wacht terwijl de verwarmingsmat op warmt.
    digitalWrite(VERWARMINGPIN, LOW); // Zet de verwarmingsmat uit.
    verwarmingStatus = LOW; // Zet de status van de verwarmingsmat die door de OLED wordt gebruikt op "uit".
    OLED(); // Update de gegevens op het OLED scherm.
    delay(wachtTijd); // Wacht voordat de loop verder gaat.
  }
  // Als het verschil tussen het setpoint en de gemeten temperatuur groot is,
  // dan wordt de mat elke keer een langere tijd aan gezet.
  else if
  (verschil >= schakelVerschil) {
    digitalWrite(VERWARMINGPIN, HIGH); // Zet de verwarmingsmat aan.
    verwarmingStatus = HIGH; // Zet de status van de verwarmingsmat die door de OLED wordt gebruikt op "aan".
    OLED(); // Update de gegevens op het OLED scherm.
    delay(langeTijd); // Wacht terwijl de verwarmingsmat op warmt.
    digitalWrite(VERWARMINGPIN, LOW); // Zet de verwarmingsmat uit.
    verwarmingStatus = LOW; // Zet de status van de verwarmingsmat die door de OLED wordt gebruikt op "uit".
    OLED(); // Update de gegevens op het OLED scherm.
    delay(wachtTijd); // Wacht voordat de loop verder gaat.
  }
}

// Functie voor encoder:
void encoderKnop() {
  interrupt = HIGH; // Zet de interrupt, die aangaat als er aan de encoder gedraaid wordt, aan, waardoor alle functies wordden gestopt.
  setpuntTemperatuur = Enc.read(); // Lees de encoder uit.
  // Als de encoder een andere stand heeft dan eerder, dan wordt het nieuwe setpoint bepaal.
  if (setpuntTemperatuur != opslaanPositie) {
    // Als de encoder verder naar rechts wordt gedraaid dan de maximale temperatuur
    // of verder dan links dan de minimale temperatuur dan blijft het setpoint op
    // de maximale of minimale temperatuur staan.
    if (setpuntTemperatuur > maxTemp) {
      setpuntTemperatuur = maxTemp;
    }
    else if (setpuntTemperatuur < minTemp) {
      setpuntTemperatuur = minTemp;
    }
    opslaanPositie = setpuntTemperatuur; // Sla het setpunt op, om te weten of het veranderd is.
  }
}

// Functie voor luchttemperatuursensor DHT11:
void GROVEDHT11() {
  DHT11gradenC = dht11.readTemperature(); // Dit haalt de temperatuur uit de sensor op.
  return DHT11gradenC; // De functie zal de waarde van variabele AHT20gradenC updaten met de gemmeten temperatuur.
}

// Functie voor het OLED scherm:
void OLED() {
  SeeedOled.setTextXY(0, 0); // Geef aan dat er op de eerste lijn geprint gaat worden.
  SeeedOled.putString("Temperatuur:"); // Print Temperatuur: nt gaat worden.
  SeeedOled.setTextXY(1, 0); // Geef aan dat er op de eerste lijn geprint gaat worden.
  SeeedOled.putNumber(DHT11gradenC); // Print de gemeten temperatuur
  SeeedOled.setTextXY(2, 0); // Geef aan dat er op de derde lijn geprint gaat worden.
  SeeedOled.putString("Setpunt:"); // Print Setpunt:
  SeeedOled.setTextXY(3, 0); // Geef aan dat er op de vierde lijn geprint gaat worden.
  SeeedOled.putNumber(setpuntTemperatuur); // Print het ingestelde setpunt.
  SeeedOled.setTextXY(4, 0); // Geef aan dat er op de vijfde lijn geprint gaat worden.
  SeeedOled.putString("Verwarming:"); // Print Verwarming:
  // Print de status van de verwarmingsmat.
  if (verwarmingStatus == HIGH) {
    SeeedOled.setTextXY(5, 0); // Geef aan dat er op de vijfde lijn geprint gaat worden.
    SeeedOled.putString("AAN"); // Print AAN als de verwarmingsmat aan staat.
  }
  else if (verwarmingStatus == LOW) {
    SeeedOled.setTextXY(5, 0); // Geef aan dat er op de vijfde lijn geprint gaat worden.
    SeeedOled.putString("UIT"); // Print UIT als de verwarmingsmat uit staat.
  }
  return;
}


Vragen en opmerkingen

We proberen de serie "De Programmeerbare Plantenkas" zo toegankelijk mogelijk te maken voor iedereen. Toch zijn sommige concepten best wel ingewikkeld, omdat er kennis van heel veel verschillende domeinen, zoals natuurkunde, elektrotechniek en computerwetenschappen, samen komen. Het kan daarom best zijn dat we iets niet goed uitgelegd hebben. Mocht er iets niet duidelijk zijn of iets niet zo werken zoals we het in deze tutorial uitgelegd hebben, stuur dan gerust een berichtje via de Disqus op deze pagina. Je kunt de Disqus vinden door naar beneden te scrollen, tot onder de advertenties.

BRONNEN EN VERDER LEZEN