-
In de inleiding heb ik de redenen aangehaald om over te schakelen van een klassieke computersturing van de centrale verwarming naar een arduino sturing van de gasverwarming. De arduino software listing staat op een aparte pagina. Hier wordt er uitleg gegeven over de software. De listing die hier gegeven wordt komt ondertussen al niet meer overeen met de werkelijkheid. De listing wordt regelmatig bijgewerkt.
Serial of SoftwareSerial?Om te communiceren met een LCD paneel heeft de arduino een ingebouwde hardware seriële poort die verbonden is met de digitale port 1, maar het is ook mogelijk een software poort aan te maken via een #include <SoftwareSerial.h>. Dit kan bijvoorbeeld nodig zijn als je meerdere panelen wilt aansturen.Een beter alternatief, als je echt veel displays moet aansturen is een switch IC te gebruiken die de TX lijn van de arduino met de corresponderende RX lijn van het display verbindt. De software poort kan echter niet samenwerken met de servomotor sturing: beide routines gebruiken een tijdsvertraging, en blijkbaar heeft de arduino slechts één timer. Als er data naar de seriële poort verstuurd moet worden, dan wordt de servo-puls verlengt, waardoor dat de motor zich gaat verdraaien. De oplossing is hier de ingebouwde poort te gebruiken (TX op digitale poort 1), dit is de hardwarematige oplossing die verder besproken wordt. Deze oplossing heeft ook nadelen. Wat zijn dan de mogelijkheden?
Hierboven een voorbeeld als het LCD paneel op de verkeerde baudrate werkt. Je hebt geluk, een probleem met de baudrate is gemakkelijk op te lossen. Je moet de software aanpassen om op de correcte baudrate te werken (bijvoordeeld LCDSerial.begin(2400)) en alle baudrates overlopen totdat je opnieuw normale tekst hebt. Als dat lukt kan je een commando doorsturen naar het scherm om terug te keren naar 9600 baud. Omdat het scherm gereset is op de juiste baudrate is er nu geen communicatie meer mogelijk todat de baudrate in de software opnieuw aangepast is.
Op de softwarelisting zie je hoe ik dat aangepakt hebt, met een boolse variabele servodrive als de servomotor aangestuurd moet worden. Als de positie van de servomotor gewijzigd moet worden, dan wordt de variabele true gezet. In de volgende lusdoorgang zijn er geen LCD schrijfopdrachten mogelijk, maar kan de servomotor wel gebruikt worden. Ik laat de servomotor kleine stapjes zetten om de thermostaat niet te forceren. Om toch output naar het scherm te hebben wordt er afwisselend naar het scherm geschreven in de ene lus en wordt de servomotor gestuurd in de andere lus (boolse variabele blinker die ook gebruikt wordt om leds te doen knipperen).
ConstantenDe gebruikte poorten worden als constanten aangegeven. Als een poort defekt zou gaan (nooit gebeurt), dan moet je enkel de constante wijzigen.Ik probeer het aantal constanten te beperken: de constanten worden in het begin van het programma gedefinieerd, en ergens gebruikt. Op de plaats waar de constante dan gebruikt wordt, weet je soms niet goed meer wat die voorstelt. In het algemeen is het beter geen constanten vooraf te definieren, als je die maar op één plaats in het programma gebruikt. Als tijdens de testfase of later een constante gewijzigd moet worden, dan moet je op 2 plaatsen kijken.
VariabelenVoor de variabelen probeer ik integer-waarden te gebruiken, behalve voor variabelen die een continue waarde voorstellen zoals de temperaturen. De temperatuurwaarden worden trouwens als integer ingelezen (0..1023) maar verder verwerkt als floats zodat de PID-berekening nauwkeuriger is en een trend sneller opgemerkt kan worden.PID parameters zijn eigenlijk integers met 2 cijfers na de komma. Als ze gebruikt moeten worden, worden ze omgezet naar een float en door 100 gedeeld. Let op met de scope van de variabelen: variabelen gedefinieerd aan het begin van de code zijn geldig voor het volledig programma (globale variabelen), variabelen gedefinieerd in een routine zijn enkel geldig in de betreffende routine (ook de loop). Het is beter de scope van een variabele beperkt te houden zodat je geen ongewenste invloeden hebt (een tel-variabele die ook in een andere routine gebruikt wordt en waarvan de waarde niet meer juist is in de aanroepende routine). Het maakt ook de code duidelijker: je weet welke variabelen hier gebruikt worden. In routines definieer je de variabelen beter als static zodat ze hun waarde behouden tussen twee aanroepen van de routines. Als de routine later opnieuw uitgevoerd wordt, dan hebben de variabelen dezelfde waarbe behouden als bij het verlaten van de routine. Niet-static variabelen worden op nul geïnitialiseerd aan hetbegin van de routine. Dit maakt niet veel uit, de lokale variabelen krijgen toch meestal een nieuwe waarde bij de start van de routine, maar het is onnodig om daarom de variabele eerst op nul te zetten. In sommige routines kan het nuttig zijn dat bepaalde variabelen hun waarde behouden tussen de aanroepen: daarvoor moet je geen globale variabelen definieeren, maar gewoon een locale static variabele.
Algemene routinesDit zijn standaard-troutines om de led status te tonen, om de led status op nul te zetten, om waarden naar de display te schrijven, enz. Deze routines worden op verschillende plaatsen opgeroepen.
Initialisatie (setup)De initialisatie wordt slechts éénmaal doorlopen na een reset. Dit deel wordt gebruikt om de digitale poorten te definieren (ingang of uitgang), om tabelwaarden een beginwaarde te geven, om gegevens die in EEPROM opgeslagen zijn te lezen,...Als je een beginwaarde aan een variabele wenst te geven, dan kan dat beter direct bij de definitie van de variabele.
Hoofdprogramma (loop)Na het uitvoeren van de initialisatie wordt de loop uitgevoerd. Is de loop ten einde, dan wordt die opnieuw uitgevoerd. Let hier dus op met het verschil in variabelen: globale variabelen behouden hun waarde, locale static variabelen behouden ook hun waarde, niet static variabelen worden terug geïnitialiseerd. |
Publicités - Reklame