SOFTWARE
Een volledig functionele versie van het PC-programma kun je hier downloaden (ebrew_Qt_exe.zip file, v3.20). Voor een goede werking heb je uiteraard ook nog de hardware met de juiste firmware nodig.
Op de hardware / elektronica pagina heb je kunnen zien, dat er een behoorlijke hoeveelheid elektronica ontwikkeld is om de brouwinstallatie te automatiseren. Maar deze hardware is nutteloos zonder bijbehorende software, die een en ander controleert en bestuurt. Toen ik startte met het ontwerp van mijn systeem, was flexibiliteit een belangrijke voorwaarde. Ik kon een ontwerp maken op basis van een microcontroller, waarin ik embedded software plaatste, zodat je geen PC nodig had. Maar omdat ik toch verschillende PCs in mijn huis heb, is het wel net zo makkelijk om een PC te gebruiken voor het besturen van je brouwerij. Op deze manier is het makkelijk om nieuwe functionaliteit toe te voegen. Als ik een nieuwe functie wil toevoegen aan de besturing, dan maak ik een update van het bestaande programma, ik test het en daarna installeer ik het op de PC in de brouwerij (via het netwerk).
Deze opzet heeft vele jaren succesvol gewerkt. De aangesloten hardware was via de parallelle poort aangesloten. Met de overgang naar nieuwe hardware werd ook dit bijgewerkt naar een (meer gebruikelijke) USB verbinding. En dan wordt toch een ontwerp m.b.v. een microcontroller weer interessant. De laatste versie van de hardware maakt gebruik van een Ethernet verbinding en wordt de USB verbinding alleen nog voor debugging gebruikt.
In de nieuwe opzet, die hier beschreven is, is dit dan ook gerealiseerd. Veel oude functionaliteit, bijvoorbeeld het opwekken van een PWM signaal, is standaard aanwezig in zo'n microcontroller. Dus kon ook de hoeveelheid hardware componenten verminderd worden. Aan de ene kant heb je dus het PC-programma dat via Ethernet communiceert met een Arduino Nano met een ATmega328 microcontroller, waar ook weer software op draait. Die laatste noemen we echter firmware, om een onderscheid te maken met de PC-software. We hebben dus twee soorten software: het PC-programma en de firmware op de microcontroller.
Welke programmeertaal kan nu het beste gebruikt worden voor beide systemen? Voor de firmware is dat duidelijk: ik maakte tot 2022 gebruik van een Arduino Nano, die ik via Atmel Studio in de C programmeertaal aanstuur, zie github.com/Emile666/Brew_Arduino. De laatste versies van de brouwhardware hebben geen Arduino Nano meer aan boord, maar een STM microcontroller, de STM8S207, een 64 pins IC. Om de firmware hiervoor te schrijven, gebruik ik IAR Embedded Workbench - STM8 series, uiteraard ook weer in de C programmeertaal, zie github.com/Emile666/Brew_HW_Stm8s207. In Embedded land is C de standaard en zijn zelfs vrijwel geen andere programmeertalen met een goede ontwikkelomgeving voorhanden.
De keuze voor een programmeeromgeving en -taal voor het PC-programma is minder duidelijk, door het grote aanbod op PC gebied. Ik ben niet echt een voorstander van moderne programmeertalen zoals Java en C#/.Net. Normaliter schrijf ik mijn programma's in the programmeertaal C, maar voor een programma onder Windows heb ik een programmeertaal nodig waarmee ik ook redelijk makkelijk een front-end GUI (windows, menus, muis etcetera) kan maken. Op zich is de taal C daar minder goed geschikt voor. De oplossing lag echter voor de hand: gebruik de programmeertaal C++ (object georiënteerd). Hiermee kun je ook je bestaande routines uit de taal C gebruiken en tegelijkertijd toch een mooi Windows programma maken.
Voor de opzet van het PC-programma, zoals dat tot 2017 gebruikt is, is Borland's C++ Builder gebruikt. Dit is inmiddels achterhaald en er zijn dan ook betere ontwikkelomgevingen beschikbaar. Voor de huidige versie van het PC-programma wordt de Qt omgeving gebruikt (zie www.qt.io) met C++ als programmeertaal.
Oke, de configuratie is gekozen, de programmeertaal en omgeving zijn ook geselecteerd. Wat kunnen we nog meer doen? Welnu, ik zou wat kunnen vertellen over de interne structuur van mijn brouwprogramma (die ik ebrew! gedoopt heb, hetgeen staat voor elektronisch brouwen). Deze pagina bestaat dan ook uit de volgende paragrafen:
- 1. Grafische User Interface (GUI)
- 2. Overview / Software-Architectuur
- 3. De Scheduler
- 4. Het toestandsdiagram
- 5. Firmware voor de Arduino Nano / ATmega328
1. GRAFISCHE USER INTERFACE (GUI)
Om de complexiteit van de software voor een groot deel af te kunnen schermen van de gebruiker, is het van belang om een goede gebruikersinterface (Graphical User Interface of GUI) te realiseren, die ervoor zorgt dat tijdens het brouwen alles zo makkelijk en efficiënt mogelijk verloopt. Na opstarten van het PC-programma verschijnt het hoofdscherm, waarvan hierboven een screenshot gegeven is.
Er is het nodige op te zien, wat ideaal is wanneer je aan het brouwen bent en je snel even bepaalde waarden wilt zien of controleren:
- Setpoint (SP) en actuele temperatuurwaarden van HLT ketel, MLT ketel, kookketel en uitgang van tegenstroomkoeler. het plaatje laat een actuele HLT temperatuur zien van 18.33 °C en een actuele MLT temperatuur zien van 19.55 °C. De gewenste (referentie) temperatuur voor de MLT is hier 71 °C en voor de HLT is dat 74.5 °C (dit screenshot is genomen tijdens een debugsessie, het zijn dus geen echte waarden uit de praktijk).
- Menubalk met checkboxes. Deze checkboxes kunnen aangevinkt worden om aan te geven dat een bepaalde actie uitgevoerd is, bijvoorbeeld "Malt added to MLT".
- Huidige toestand: Dit label geeft de actuele toestand weer van het toestandsdiagram. De huidige toestand in het screenshot is "01. Wait for HLT Temperature (74.5 °C)".
- De actuele vermogens van de ketel: de HLT branders staan nu op 100 % en de branders van de kookketel staan nu nog op 0 %.
- De actuele volumes in de ketels: in het screenshot is het volume voor de warmwaterketel (HLT) 160.0 L, voor de maischketel (MLT) is dit -9.0 L en de kookketel nog 1.4 L. De volumes worden hier niet direct ingelezen, maar bepaald via de waarden van de flowsensoren. Alles wat uit de kookketel loopt, gaat van dat volume af en wordt bij het volume van de MLT opgeteld.
- De waarden van de flowsensoren: er zijn vier flowsensoren aanwezig in het brouwsysteem. De eerste sensor is gemonteerd tussen de warmwaterketel en de maischketel, de tweede flowsensor is gemonteerd tussen de maischketel en de kookketel, de derde flowsensor is op de uitgang van de tegenstroomkoeler gemonteerd en de vierde flowsensor is tussen de HLT en de MLT retourleiding gemonteerd. Deze waarden geven het totaal aantal liters weer dat door de sensoren gestroomd is en het debiet (aantal liters per minuut). In dit geval staan de eerste en de vierde sensor nog op 0.0 L, sensor 2 is nu actief (groen) en staat op 9.0 L totaal met een flow van 7.6 L per minuut. Flowmeter 3 ziet nu een flow van 6.4 L per minuut de andere sensoren staan nog op 0.0 L. Deze waarden zijn van een debugsessie genomen (flow2 kan bijvoorbeeld geen flow zien, omdat klep V7 nog dicht staat en de pomp staat uit).
- De status van de pomp: drie opties zijn hier mogelijk: "Auto", "Pump Off (M)" en "Pump On (M)". Deze opties kunnen geselecteerd worden door met de rechter muis toets op de pomp te klikken. Wanneer de optie "Auto" geselecteerd is, dan zal het brouwprogramma (en dan met name het toestandsdiagram) de pomp in en uit schakelen. De brouwer kan deze automatische werking overrulen door een van de handmatige opties te kiezen (dat wordt dan aangegeven door een (M) bij het symbool van de pomp. In het screenshot staat de brouwpomp P1 op Automatisch en uitgeschakeld, terwijl de pomp P2 (die zorgt voor circulatie van het water in de HLT) op Automatisch staat en nu aan staat.
- De status van iedere elektrische klep: wederom zijn, voor iedere klep, drie opties mogelijk: "Auto", "Off (M)" en "On (M)". In het screenshot staan de kleppen V3, V6 en V7 op automatisch en staan ze dicht. Klep V2 is nu handbediend en staat dicht en de kleppen V4 en V1 zijn ook handbediend en staan nu open. automatische besturing en staan ze allemaal uit.
- De status balk: de status balk geeft de nodige informatie weer, zoals de instellingen voor alarmen (de brouwhardware gaat piepen bij een temperatuur of een flow sensor fout), het maischschema (temperaturen met bijbehorende verblijftijden), de hoeveelheid maisch- en spoelwater, de huidige index in het maisch en spoelschema en het versienummer (dat is nu R3.20 voor het PC-programma en R2.02 voor de brouw hardware).
- Er is ook een lijstje te zien met toetscombinaties. Zo kan met een nummer de bijbehorende klep aan- of weer uitgezet worden en kun je met een 'A' alles automatisch zetten. Dit is m.n. handig wanneer je een klep of pomp met de hand bediend hebt en je zeker wil weten dat alles weer door het programma geregeld gaat worden.
Als een van de ingelezen waarden vanuit de brouw-hardware niet goed is, of er is geen communicatie, dan kleuren de bijbehorende waarden rood. In het screenshot hierboven worden alle temperaturen correct ingelezen en worden de flows van flowmeter 2 en 3 ook ingelezen.
1.1 FUNCTIES VAN HET PC BROUWPROGRAMMA
De menu-balk van het brouwprogramma bevat de volgende menu items:
- File -> Exit: afsluiten van het brouwprogramma, alle elektronica wordt uitgezet en de communicatie met de hardware (Ethernet of USB) wordt afgesloten.
- Edit -> Mash Scheme... (Ctrl+M): met deze optie kunnen tot 10 temperatuur-tijd paren ingevoerd worden. Hiermee kunnen specifieke tijden en temperaturen voor een maischschema ingevoerd worden. Ook kan het hopgift schema ingevoerd worden en de hoeveelheid maisch- en spoelwater. Het is gebruikelijk om voor ieder recept een eigen maischschema bestand te maken.
- Edit -> Fix Parameters... (Ctrl+F): iedere variabele die van belang is, kan een waarde gegeven worden m.b.v. deze functie. Voorbeeld: het brouwprogramma leest standaard de waarde van de HLT temperatuur van de digitale temperatuursensor. Stel nu dat de gebruiker een bepaalde waarde voor deze temperatuur wil instellen (bijv. om iets te testen), waarbij het standaard inlezen dus overruled gaat worden. Met behulp van deze functie kan een specifieke waarde ingesteld worden. Na vrijgeven van deze variabele neemt het brouwprogramma de controle weer over voor deze variabele. Deze functie is alleen zinvol bij testen en wanneer een fout optreedt, bij een normale brouwsessie is dit scherm niet nodig.
- Edit -> Terminal Editor (Ctrl+E): ook dit is weer een scherm dat bij een normale brouwsessie niet nodig is. Er wordt een terminal editor geopend, waarmee direct commando's naar de brouwhardware gestuurd kan worden.
- View -> Mash/Sparge Progress (Ctrl+P): deze optie toont een scherm met de status van alle maisch- en spoel-timers. Hiermee kun je direct zien hoe lang een bepaalde rust nog duurt, welke al geweest zijn en wat het spoelschema is.
- View -> Status and Alarms (Ctrl+A): deze optie toont een scherm waarop alle sensoren te zien zijn (temperatuur en flow). Als een sensor het niet doet, is dat direct op dit scherm te zien. Ook kan bekeken worden wat de interne waarden van de PID-regelaars zijn, dat is weer handig als je bezig bent om de regelaars in te stellen.
- View -> Task-list and Timings (Ctrl+T): deze optie toont een scherm met daarop de software taken en de hoeveelheid en maximum tijd die ze nodig hebben. Dit wordt gedaan voor zowel het PC-programma als de firmware van de brouwhardware. Ook wordt een overzicht gegeven van de gevonden hardware ICs en sensoren. In onderstaand screenshot worden vier I2C-to-One-Wire bridges (DS2482 IC) en twee LM92 temperatuursensoren gevonden. Ook worden er in totaal vier One-Wire temperatuursensoren gevonden.
- Help -> About...: laat het versienummer zien van het brouwprogramma.
- Help -> About Qt...: laat algemene info over Qt zien.
- Options -> System Settings...: dit dialoogscherm bestaat weer uit drie deelschermen, namelijk 'Heater Options', 'Communications' en 'Brew-Kettle Volumes'. Alle instellingen die hiermee gedaan kunnen worden, worden opgeslagen in de Registry van Windows, zodat je bij de volgende keer starten van het programma direct de laatst ingestelde waarden hebt.
- Options -> PID Controller Settings...: hiermee kunnen verschillende parameters ingesteld worden die te maken hebben met de PID regelaar.
- Options -> Brew Day Settings...: dit dialoogscherm bestaat weer uit vier deelschermen, namelijk eentje voor Maischen, voor Spoelen, voor Koken en voor Schoonmaken (Clean-in-Place). De meeste instellingen spreken voor zich en zijn ook nog voorzien van een korte helptekst.
- Options -> Measurements Settings...: dit dialoogscherm bestaat weer uit twee deelschermen, namelijk eentje voor de temperatuursensoren en eentje voor de flowsensoren.
Bij Heater Options kun je aangeven welke branders aanwezig zijn in het brouwsysteem. In het plaatje hierboven zijn voor zowel de HLT als de kookketel een modulerende gasbrander en twee elektrische verwarmingselementen ingeschakeld. De modulerende gasbrander wordt aangezet bij een warmtevraag van meer dan 4 % en gaat weer uit onder de 2 %. Een eventuele niet modulerende gasbrander zou in- en uitgeschakeld worden bij 35 % en 30 % warmtevraag. En de elektrische verwarmingselementen worden uitgeschakeld wanneer de interne temperatuur van de elektronica boven de 75 % komt.
Bij Communications kun je aangeven wat het COM-poort nummer of het netwerkadres is van de brouwhardware, alsmede de instellingen zelf. In het midden van het scherm (dikgedrukt) wordt weergegeven wat het programma zelf al gevonden heeft. In dit geval is COM4 gevonden (de brouwhardware was ook via de USB poort aangesloten) en is het IP adres van de brouwhardware gelijk aan 192.168.1.11. Het poortnummer waarmee de brouwhardware communiceert is altijd 8888. Na het instellen van dit gevonden IP-adres en poortnummer verloopt alle communicatie tussen het PC brouwprogramma en de brouwhardware op deze manier.
Bij Brew-Kettle Volumes kun je de minimum en maximum volumes ingeven van de ketels. De minimum waterniveaus voor de HLT en kookketel zijn van belang bij elektrisch verwarmen. Dit zijn de minimum waterniveaus waarmee de verwarmingselementen nog onder water staan. Door het grote vermogen van deze elementen zouden ze direct kapot gaan als ze niet meer onder water staan. De elektrische verwarmingselementen worden dan ook uitgeschakeld wanneer het vloeistofniveau onder deze waarden komt.
De eerste temperatuuroffset die ingesteld kan worden, is bedoeld voor het inmaischen. Dit is de offset die bovenop de eerste maischtemperatuur komt en compenseert de temperatuurdaling als gevolg van het toevoegen van de mout aan het water. Stel dat de gewenste eerste temperatuur gelijk moet worden aan 63 °C.
Dan wordt de temperatuur van de HLT ingesteld op 63 °C + deze temperatuuroffset.
De volgende temperatuuroffset is bedoeld om de warmteverliezen tussen HLT en MLT te compenseren. Ook al isoleer je de leidingen goed, dan nog heb je een (klein) temperatuurverlies. Deze offset compenseert daarvoor.
De volgende temperatuuroffset is bedoeld voor het starten van de maisch timer. In dit geval wordt de timer al gestart bij 62.5 °C en niet pas bij 63 °C.
Met 'Dynamic Preheat Timing' wordt een tijd terug gerekend, op basis van de 'HLT Burner Capacity', wanneer de HLT brander aangezet moet worden. Stel dat de volgende temperatuurstap 10 °C verder is, dan zijn er 900 seconden (15 minuten) voor nodig om dat te bereiken. In dat geval wordt de laatste 15 minuten de HLT alvast voorverwarmd voor de volgende temperatuur.
Als dit vinkje uit staat, dan wordt met een vaste tijd ('HLT Preheat-Timer') gewerkt.
Bij het inmaischen kun je ervoor kiezen om eerst de mout toe te voegen en daar het opgewarmde water over te sproeien. Staat het vinkje uit, dan wordt eerst al het water in de MLT toegevoegd en pas daarna kan de mout gestort worden.
Na het inmaischen kun je ervoor kiezen om de pomp eerst vijf minuten uit te zetten (zet het vinkje bij 'Enable Mash Rest' aan). Dit voorkomt dat het graanbed dicht slaat.
Als laatste kun je instellen dat de pompen aan blijven, wanneer de ingestelde MLT temperatuur bereikt is. Zet dit vinkje uit als je direct de mout wilt toevoegen wanneer de temperatuur bereikt is.
Het systeem gaat uit van 'batch sparging', hetgeen betekent dat je in een aantal stappen spoelwater toevoegt. Dat aantal stappen kun je hier instellen, meestal wordt dit op 4 tot 5 stappen ingesteld.
De tijd tussen twee stappen kan ook ingesteld worden. Meestal stel je hier een waarde in tussen de 10 en 20 minuten.
Het systeem berekent automatisch hoeveel wort er uit de MLT per stap naar de kookketel gepompt wordt. Bij de eerste keer pompen van MLT naar kookketel kun je ervoor kiezen om meer wort naar de kookketel te pompen. Stel dat er per stap 10 liter wort naar de kookketel gepompt zou worden. Met deze instelling wordt er dus de eerste keer 25 L naar de kookketel gepompt.
De eerste instelling voorkomt dat de gasbrander aangezet wordt, terwijl er nog geen wort in de kookketel zit. Er moet dus eerst een minimum temperatuur (deze parameter) gedetecteerd worden in de kookketel en pas dan wordt de brander aangezet.
Met de tweede parameter kan de temperatuur ingesteld worden, voordat er gekookt gaat worden. Dat is dus tijdens de verschillende spoelstappen. Je wilt het wort in de kookketel zo dicht mogelijk tegen het koken aan hebben, zonder dat het echt gaat koken.
De derde parameter zorgt ervoor dat gedetecteerd wordt wanneer het koken begonnen is. Als de temperatuur van de kookketel boven deze waarde komt, dan is het wort in de kookketel aan het koken.
De volgende parameter stelt de referentietemperatuur voor de kookketel tijdens het koken in. Zet deze op bijvoorbeeld 105 °C, zodat de PID-regelaar voluit komt te staan (want deze temperatuur wordt nooit bereikt bij koken).
De volgende parameter begrenst het maximale vermogen voor de branders van de kookketel tijdens het koken. Stel deze waarde zodanig in dat een mooie rollende kook bereikt wordt (niet te hard, maar ook niet te langzaam).
Na het koken kan er vijf minuten gewacht worden (zet vinkje aan bij 'Apply time-rest of 5 minutes after Boiling'), zodat alle vaste deeltjes (hop e.d.) neerslaan op de bodem van de kookketel. Hiermee voorkom je dat het filter in de kookketel dicht slaat.
Er kan een piepje gegeven worden als er hop toegevoegd moet worden tijdens het koken. Zet hiervoor het vinkje 'Add 4-beep Alarm for hop-gift during boiling' aan.
Na het koken kun je ervoor kiezen om direct te koelen en te pompen naar het gistvat, maar je kunt er ook voor kiezen om te koelen en te hercirculeren terug de kookketel in. Hiermee verlaag je de temperatuur van het wort in de kookketel en haal je een deel van de warmte er al uit. Hiermee kun je uiteindelijk op een
lagere temperatuur in het gistvat komen, dan wanneer je direct naar het gistvat pompt. Vooral in de zomer is dit nuttig. Zet het vinkje aan bij 'Start Chilling with recirculating through Boil-kettle'. Het hercirculeren terug de kookketel in stopt wanneer een bepaalde temperatuur bereikt is.
Dat is de temperatuur die ingesteld wordt bij 'Lower-Limit Temperature for Boil-kettle recirculation'. Hierna wordt het wort verder gekoeld en naar het gistvat gepompt.
Er is een apart toestandsdiagram gemaakt voor het schoonmaken van het brouwsysteem. Dit heet Clean-In-Place (CIP). Je begint typisch met het vullen van de kookketel met een 1 % NaOH oplossing. Deze oplossing wordt eerst opgewarmd naar de temperatuur, zoals ingesteld bij 'CIP Setpoint Temperature'.
Hierna wordt deze vloeistof door alle leidingen van het systeem gepompt gedurende een tijd die ingesteld staat bij 'CIP Circulating-time'. Hierna wordt de pomp uitgezet en zit de vloeistof een bepaalde tijd ('CIP rest-time between circulations') in het systeem. Hierna wordt vers water (uit de HLT) een bepaalde tijd ('CIP Time for cleaning every output-pipe')
door iedere uitgaande leiding gepompt. Goed naspoelen is erg belangrijk, dus maak deze tijd niet te klein. Hierna worden alle inputs gereinigd (de pomp staat dan uit) en hiervoor is de parameter 'CIP time for cleaning every input-pipe'.
De optie 'Clean-In-Place' kan geactiveerd worden door in de menu-balk het vinkje bij 'Start Clean-In-Place (CIP)' aan te zetten.
Voor iedere aangesloten temperatuursensor kan er een offset (positief of negatief) toegevoegd worden. Hiermee wordt het mogelijk om de sensoren onderling allemaal dezelfde temperatuurwaarde te laten weergeven bij een bepaalde temperatuur.
Verder kan voor de HLT sensoren aangegeven worden welke sensoren de HLT temperatuur bepalen. In de huidige opzet is er een I2C sensor (een LM92) en/of een One-Wire sensor (een DS18B20) aanwezig. Je kunt er ook voor kiezen om beide sensoren de HLT temperatuur te laten bepalen, de HLT temperatuur is dan het gemiddelde van deze twee waarden.
Maar je kunt hier dus ook instellen dat je alleen een One-Wire sensor of alleen een I2C sensor gebruikt voor het bepalen van de HLT temperatuur.
Eenzelfde instelling kun je ook maken voor de MLT temperatuur.
Iedere flowsensor kan apart gecalibreerd worden op het aantal liters dat er doorheen stroomt. Je kunt bijvoorbeeld beginnen met nauwkeurig 20 L af te meten en dit door een flowsensor te laten stromen. De waarde van de flowsensor kun je dan aflezen en middels dit scherm corrigeren totdat je de juiste waarde hebt.
Omdat het volume van een vloeistof wat groter wordt bij een hogere temperatuur, kun je er hier ook voor kiezen om hiervoor te compenseren. Doe dit door het vinkje bij 'Enable Temperature Compensation for flowmeter readings' aan te zetten.
Als laatste zijn er twee parameters die bepalen wanneer de MLT ketel of de kookketel leeggepompt zijn. Bij leegpompen van een ketel is er een bepaald debiet (aantal liters per minuut). Dit wordt bepaald door de leidingen en de kracht van de pomp. Dit debiet wordt gemeten door het programma en wanneer dit debiet onder een ingesteld percentage van het nominale debiet komt,
dan is de betreffende ketel leeg. Als je deze waarden te groot zet, dan stopt het systeem te snel met leegpompen. Zet je deze waarden te laag, dan blijft de pomp aan staan, terwijl er bijna niets meer in de ketel zit. Een waarde tussen de 2 % en 5 % lijkt een goed resultaat te geven.
2. SOFTWARE ARCHITECTUUR
Het PC-programma bevat een aantal belangrijke componenten die gezamenlijk een geheel volgen. Omdat de taal C++ object georiënteerd is, is het logisch om een aantal objecten of classes tegen te komen. De belangrijkste onderdelen zijn:
- Een Scheduler met diverse taken die op vaste momenten uitgevoerd moeten worden.
- Een toestandsdiagram die voor de overall besturing van het programma zorgt. Zie de methode StateMachine() binnen het object MainEbrew.
- Diverse grafische objecten (zie de file hmi_object.cpp en hmi_objects.h), zoals PowerButton, Tank, Pipe en Display. Verder is er een algemeen object Actuator en hiervan zijn de objecten Valve en Pump afgeleid.
- Diverse control objecten (zie de file controlobjects.cpp en controlobjects.h), zoals PidCtrl (de PID regelaar), MA (moving-average filter) en SlopeLimiter (hellingsbegrenzer). De implementatie van de PID-regelaar wordt in meer detail beschreven bij Implementatie PID regelaar
- Diverse routines die de lees- en schrijf-operaties naar een COM-poort en de Ethernet verbinding verzorgen. De COM poort is niet fysiek aanwezig, maar wordt via de USB-poort gerealiseerd. Dit wordt een 'virtuele COM poort' genoemd.
Het PC-programma verzorgt met name allerlei mogelijke instellingen van het brouwprogramma (tijden, temperaturen, parameters) en verstuurt op vaste tijdstippen commando's naar de hardware via een standaard communicatieprotocol. De reacties van de hardware worden weer op het scherm zichtbaar gemaakt. Een overzicht van alle bestanden en schermen ziet er als volgt uit:
Alleen al het hoofdobject (heet MainEbrew) bevat al ongeveer 2200 Lines of Code (LOC). De totale PC-applicatie omvat ongeveer 5600 regels C++ code.
Naast het PC-programma is er uiteraard nog een tweede belangrijke deelcomponent in het totale systeem en dat is de firmware die op de ATmega328 van de Arduino Nano draait. Ook dit softwaresysteem omvat weer de nodige regels code: bij R1.45 waren dit ongeveer 3550 regels C code. Alles bij elkaar dus ruim 9000 regels C en C++ code!
Terug naar boven3. SCHEDULER
De e-brew! applicatie vraagt strakke timingseisen en er moet veel gebeuren op vaste tijdstippen. Er moeten commando's naar de hardware gestuurd worden, er worden temperaturen en volumes ingelezen, het scherm moet bijgewerkt worden, etcetera. Het zou heel mooi zijn om de beschikking te hebben over een real-time embedded operating systeem (RTOS genoemd), maar Windows komt bij zoiets nog niet eens in de buurt. Om de 100 milliseconden iets uitvoeren, wordt al erg lastig. Gelukkig zijn temperaturen geen snel veranderende grootheden en hoeft er niet zo snel geregeld en gestuurd te gaan worden. Maar er is wel iets nodig om ervoor te zorgen dat alle verschillende taken ook aan bod komen. Hiervoor is een aparte scheduler geschreven. Een scheduler is software die ervoor zorgt dat de verschillende taken in een software programma op het juiste tijdstip en met de juiste frequentie uitgevoerd worden. De gebruikte scheduler is non pre-emptive, hetgeen wil zeggen dat als een taak gestart is, deze niet meer onderbroken kan worden door een andere taak. Een volgende taak kan pas starten als de huidige taak is afgelopen. Voor ons brouwsysteem is dit voldoende en met wat aandacht voor de duur van een taak levert dit geen problemen op.
Taken zijn op deze manier makkelijk toe te voegen, om dit te illustreren onderstaande stukje C code (zoals dit ook in het PC-programma aanwezig is):
//-----------------------------------------
// Now add all the tasks for the scheduler
//-----------------------------------------
scheduler->add_task("aliveLed" , 0,TS_LED_MSEC ,Ebrew,SLOT(task_alive_led())); // TASK 0
scheduler->add_task("readTemps" , 100,TS_TEMPS_MSEC,Ebrew,SLOT(task_read_temps())); // TASK 1
scheduler->add_task("pidControl", 300,TS_PID_MSEC ,Ebrew,SLOT(task_pid_control())); // TASK 2
scheduler->add_task("updateStd" , 400,TS_STD_MSEC ,Ebrew,SLOT(task_update_std())); // TASK 3
scheduler->add_task("readFlows" , 600,TS_FLOWS_MSEC,Ebrew,SLOT(task_read_flows())); // TASK 4
scheduler->add_task("wrLogFile" ,1600,TS_WR_LOGFILE,Ebrew,SLOT(task_write_logfile())); // TASK 5
Het toevoegen van taken is op deze manier eenvoudig en overzichtelijk. De taak task_update_std() voert bijvoorbeeld iedere seconde (1000 msec.) het toestandsdiagram uit. Je kunt ook nog een offset meegeven: in het geval van task_update_std() start deze op tijdstip 0.4 (400 msec.) en daarna weer op tijdstip 1.4, 2.4, 3.4 etcetera. Bij de PID regelaar, task_pid_ctrl(), is iets bijzonders aan de hand: de aanroepfrequentie is afhankelijk van de parameter Ts, die in seconden weergegeven is. Als in het PC-programma deze tijd bijvoorbeeld op 20 seconden ingesteld staat, dan zorgt deze aanroep ervoor dat de PID regelaar iedere 20 seconden aangeroepen wordt. Het belangrijkste is nu nog om ervoor te zorgen dat de taken niet teveel tijd in beslag nemen. De scheduler meet daarom ook de tijdsduur en maximale tijdsduur van iedere taak, dat kan er als volgt uitzien (in een log-file):
Task-Name T(ms) Stat T(μs) M(μs)
--------------------------------------
aliveLed 500 0x02 407 1339
readTemps 2000 0x02 15236 15699
pidControl 1000 0x02 1421 1767
updateStd 1000 0x02 681 1040
readFlows 2000 0x02 55684 55684
wrLogFile 5000 0x02 167 167
Uit dit overzicht blijkt dat updateStd() maximaal 681 usec. geduurd heeft. Samen met het hierboven gedefinieerde overzicht levert dit een goed inzicht op in de diverse taken op. Foutzoeken is op deze manier eenvoudig te doen. De scheduler zelf wordt vanuit een Timer routine aangeroepen, dit gebeurt iedere 100 milliseconden. Belangrijkste functie van deze routine is het bijhouden van alle timers en het inschakelen en uitschakelen van taken. De feitelijke aanroep van de taken gebeurt hier niet in!
Terug naar boven4. TOESTANDSDIAGRAM
Volgens de free online dictionary of Computing is een toestandsdiagram (state transition diagram, of STD) "een diagram die uit cirkels bestaat, die toestanden voorstellen. Ook bestaat zo'n diagram uit gerichte pijlen tussen die toestanden. Deze stellen de overgangen voor. Een of meerdere acties (outputs) kunnen gekoppeld worden aan zo'n overgang.". Kijkend naar de e-brew! applicatie, dan is een STD een centrale besturingsfunctie, die de verschillende fasen van het brouwproces coördineert. Een toestand kan zoiets zijn als 'maisch rust' of 'voorverwarmen'. Een overgang van de ene toestand naar de andere toestand wordt uitgevoerd wanneer de bijbehorende conditie WAAR is (bijv. de 'temperatuur is ok'). Condities zijn in het toestandsdiagram (zie plaatje hieronder) met GROEN aangegeven. Wanneer een overgang naar een andere toestand uitgevoerd wordt, dan kan er ook een bijbehorende actie uitgevoerd worden. (bijv. 'zet pomp aan'). Acties zijn met ROOD aangegeven. Samengevat: er zijn toestanden, overgangen tussen die toestanden, condities en acties. Het toestandsdiagram behorende bij het totale brouwproces bestaat uit 19 unieke toestanden, waarvan een aantal toestanden cyclisch doorlopen kunnen worden. Het ziet er als volgt uit:
Al met al een complex toestandsdiagram, die de totale besturing voor zijn rekening neemt. Een korte uitleg per toestand is dan ook wel handig om hier te geven:
- 00. Initialization: deze toestand wordt actief na het opstarten van het brouwprogramma. Het programma blijft in deze toestand zolang de brouwer de PID regelaar niet ingeschakeld heeft. In deze toestand staan alle kleppen en de pomp uit.
- 01. Wait for HLT temp.: in deze toestand heeft de brouwer de PID regelaar ingeschakeld en wordt het water in de HLT opgewarmd. Maar de inmaisch temperatuur is nog niet bereikt. Als de optie "Add Malt First" is aangevinkt, dan kan nu de geschrote mout in de MLT gestort worden.
- 14. Prime Pump: De magneetpomp is niet zelf aanzuigend en moet dus gevuld zijn met water om te kunnen werken. Dat gebeurt in deze toestand: er loopt water uit de HLT de pomp in gedurende 1 minuut
- 02. Fill MLT: De HLT temperatuur is OK, de pomp wordt aangezet. Hierdoor wordt de MLT gevuld met de ingestelde hoeveelheid water.
- 03. Wait for MLT Temp.: De MLT temperatuur heeft nog niet de vooraf ingestelde maischtemperatuur bereikt. Het water in de MLT wordt door de warmtewisselaar van de HLT gepompt en wordt op die manier dus indirect verwarmd.
- 19. Ready to add Malt: De MLT temperatuur heeft de vooraf ingestelde maischtemperatuur bereikt. In deze toestand blijft het water in de MLT circuleren, omdat de pomp aan blijft. Als het vinkje bij 'Start adding malt to MLT' in de menubalk aangevinkt wordt, dan wordt naar de volgende toestand gegaan.
- 15. Add Malt to MLT: Dit is een handmatige actie voor de brouwer: de geschrote mout wordt toegevoegd aan het water in de maischketel, dat inmiddels op de juiste temperatuur is aanbeland. De pomp is in deze toestand uitgezet. Na afloop kan de brouwer aangeven dat de mout toegevoegd is door de optie 'malt added to MLT' aan te vinken. Deze toestand wordt maar 1 keer uitgevoerd en alleen wanneer de parameter "Add Malt First" niet is aangevinkt.
- 18. Mash Rest 5 Min.: Geef de geschrote mout tijd om water op te nemen. Direct de pomp starten kan het filterbed dicht laten slaan.
- 04. Mash timer running: De maischrust timer is gestart, maar heeft nog niet zijn eindwaarde bereikt. Deze toestand is actief zolang deze timer nog loopt. Als alle temperaturen afgehandeld zijn, dan wordt een overgang gemaakt naar de spoelfase (05. Sparging Rest). Deze toestand bepaalt, samen met de toestanden 03. Wait for MLT Temp. en 13. Mash preheat HLT het totale temperatuur-tijd traject van het maischen. Ze worden dus meerdere keren (afhankelijk van het aantal ingestelde temperaturen) cyclisch doorlopen.
- 13. Mash preheat HLT: de totale maischrust is nog niet klaar, maar de HLT wordt alvast opgewarmd naar de volgende maischtemperatuur (de pomp wordt uitgezet in deze toestand om te voorkomen dat ook de MLT wordt opgewarmd). Wanneer er een time-out optreedt van de maischrust timer, dan wordt toestand 03. Mash in progress actief, en wordt de mash-index met 1 verhoogd.
- 05. Sparge Timer Running: deze toestand wordt actief wanneer alle maisch temperaturen en tijden afgehandeld zijn. Het maischen is nu voorbij en het spoelen wordt gestart. Wanneer deze toestand voor het eerst actief wordt, (komende vanuit toestand 04. Mash timer running), dan wordt er direct een overgang gemaakt naar de toestand 06. Pump from MLT to Boil-Kettle. In die toestand wordt een deel van de wort naar de kookketel gepompt. In alle andere gevallen blijft het toestandsdiagram in deze toestand voor een bepaalde tijd (12-20 minuten), waarna via een korte vertraging, nieuw water wordt toegevoegd vanuit de HLT. Een overgang naar de toestand 09. Empty MLT wordt gemaakt wanneer het aantal cycli spoelen van de mout overeenkomt met het vooraf ingestelde aantal (meestal 4-5 keer). Dit betekent dat we klaar zijn met spoelen.
- 06. Pump from MLT to Boil. Een deel van het wort wordt overgepompt van de maischketel (MLT) naar de kookketel. Wanneer het vooraf ingestelde volume is overgepompt, dan wordt de overgang gemaakt naar de toestand 07. Delay 10 Seconds.
- 07. Delay 10 seconds, het toestandsdiagram blijft 10 seconden in deze toestand, om het systeem even tot rust te laten komen.
- 08. Pump from HLT to MLT. In deze toestand wordt nieuw vers water van 80 °C uit de warmwaterketel (HLT) naar de maischketel (MLT) gepompt. Wanneer het vooraf ingestelde volume is overgepompt, dan wordt een overgang gemaakt naar de toestand 05. Sparging Rest en wordt de spoel-index (sparging index, sp_idx) met 1 verhoogd. De cyclus van de toestanden 05 -> 06 -> 07 -> 08 herhaalt zich dus een aantal keren en is instelbaar in het PC-programma.
- 09. Empty MLT. Nadat het vooraf ingestelde aantal keren spoelen uitgevoerd is, kom je in deze toestand terecht. Alle wort uit de maischketel wordt overgepompt naar de kookketel.
- 10. Wait for Boil. Alle wort zit nu in de kookketel, maar dit is nog niet aan het koken. Pas als dit aan de kook is, wordt de overgang naar 11. Now Boiling gemaakt. Op dit moment is dit nog een handmatige actie (de brouwer moet aangeven wanneer het koken begint), maar met een temperatuursensor in de kookketel is dit ook automatisch te doen. Als het wort aan de kook is, wordt de overgang naar 11. Now Boiling gemaakt.
- 11. Now Boiling. Wanneer gestart wordt met koken, komt het toestandsdiagram in deze fase terecht. Zolang de kooktijd niet verstreken is, blijft deze toestand actief.
- 12. Boiling finished, prepare Chiller De kooktijd is verstreken en het koelen van de wort en in het gistvat pompen kan beginnen. Wanneer de warmtewisselaar klaar is (koelwater loopt er doorheen), kan de brouwer dit ook weer aangeven in het PC-programma. Hierna wordt de overgang gemaakt naar 16. Chill & Pump to Fermentor.
- 16. Chill & Pump to Fermentor. De nog kokendhete wort wordt via de warmtewisselaar het gistvat in gepompt. Nadat alle wort in het gistvat zit, kan de brouwer dit weer aangeven met een handmatige actie. Daarna wordt de volgende toestand (17. Finished!) actief.
- 17. Finished!. Einde van de brouwdag. Deze toestand kent geen overgang meer. Wil je een nieuwe brouwsessie starten, dan moet je het PC-programma afsluiten en weer opnieuw opstarten.
De tabel (rechter bovenhoek) laat zien welke kleppen in welke toestand open (1) of gesloten (0) zijn, maar ook of de pomp aan (1) of uit (1) is. Door op deze manier je ontwerp te maken kun je het gedrag van de verschillende kleppen goed definiëren. Het is altijd duidelijk in welke toestand een bepaalde klep open of gesloten is. Er zijn nog heel wat meer details te vertellen over dit toestandsdiagram, maar het bovenstaande verhaal is hopelijk voldoende om een beeld te geven van de werking. Voor de volledigheid wordt nog opgemerkt dat het toestandsdiagram 1 keer per seconde uitgevoerd wordt.
Terug naar boven5. FIRMWARE VOOR DE ARDUINO NANO / ATmega328
De firmware omvat de C code voor de ATmega328 microcontroller en staat dus qua opzet geheel los van het PC-programma dat hiervoor beschreven is. Beide programma's communiceren echter wel met elkaar, via een netwerkkabel of de virtuele COM poort van de USB verbinding. Het grote voordeel van het gebruik van een microcontroller is dat allerlei hardware gerelateerde en vaak tijdkritische zaken niet meer door PC-Windows afgehandeld hoeven te worden. Een microcontroller is hier veel beter voor geschikt. Aan de microcontroller kant wordt dankbaar gebruik gemaakt van de Arduino hardware opzet. Deze Arduino omgeving zal dan ook als eerste geïnstalleerd moeten worden. Hiermee worden de juiste drivers aan de PC kant geïnstalleerd. Aan de microcontroller kan is het een ander verhaal. Gelukkig hoeven we hier niet direct met USB routines aan de slag (complex!), maar kunnen we ook hier gebruik maken van standaard routines voor seriële communicatie. De microcontroller bevat een component die USART heet (Universal Synchronous/Asynchronous Receiver/Transmitter) en hiermee kan, met de juiste routines, seriële communicatie gerealiseerd worden. De gebruikte instellingen zijn 38400,N,8,1, dat wil zeggen: 38400 Baud,geen pariteitbit, 8 databits en 1 stopbit. Dit is uiteraard identiek aan de instellingen in het PC-programma.
Terug naar de overall opzet van de software voor de microcontroller. Ik maak geen gebruik van Arduino sketches, omdat dit te beperkt is voor mijn doeleinden. Van sommige sketches heb ik C libraries gemaakt, anderen heb ik zelf geschreven. Zoals gebruikelijk bij een C project, wordt van bijna iedere component een C file gemaakt met een bijbehorende header file (.h). Tezamen omvatten deze alle routines voor zo'n component. Voorbeeld: de I2C module (met files i2c.c en i2c.h) omvat alle routines voor de I2C communicatie, inclusief specifieke routines voor de gebruikte ICs, zoals de DS2482.
Low-level routines:Zoals in het plaatje te zien is, zijn er libraries voor I2C, SPI, ADC, PWM, One-Wire en Usart. In feite dus voor alle low-level hardware van de microcontroller zelf. Om de werking hiervan goed te begrijpen, zul je toch echt in de datasheet van de ATmega328P microcontroller moeten duiken. Zeker als je aanpassingen hierop wilt maken. Gelukkig zijn er veel goede voorbeelden op het Internet te vinden, het is namelijk ook een van de meest gebruikte microcontrollers.
Interrupt routines:De interrupt routines zijn tijd-kritische stukken code die niet kunnen wachten totdat er tijd voor ze is. Het is dus functionaliteit die direct uitgevoerd moet worden. Voor de ontwerper is het dus van belang om deze routines zo klein mogelijk te houden: je kunt niet even gaan wachten totdat er iets gaat gebeuren. Een mooi voorbeeld hiervan zijn de flowsensoren die aangesloten zitten op poortpinnen van de microcontroller. Als er een puls langs komt van zo'n flowsensor, dan wordt er nu een interrupt gegenereerd die niet veel meer doet dan een teller met 1 verhogen. Alle pulsen van de vier flowsensoren worden in zo'n interrupt afgehandeld. Hiernaast is nog een interrupt gedefinieerd voor de scheduler die iedere milliseconde aangeroepen moet worden. Als laatste zijn er nog twee interrupts actief voor de seriële communicatie. Als de USART hardware van de microcontroller een byte ontvangen heeft, dan wordt een interrupt gegenereerd. In deze interrupt wordt dat byte opgeslagen in een ringbuffer. Iets vergelijkbaars gebeurt er wanneer er data in een ringbuffer aanwezig is om verstuurd te worden.
Naast deze low-level libraries is er ook nog een gemengde library, waar enkele functies inzitten die te maken hebben met het filteren van de ingelezen signalen. Zo is er een moving-average filter (een laagdoorlaatfilter) gedefinieerd en een hellingsbegrenzer functie. Verder een ringbuffer routine voor de seriële communicatie en een RS232 command handler. Ieder commando van de seriële poort wordt door deze routine afgehandeld.
Ethernet/Wiz550io: de brouw-hardware heeft een WIZ550io Ethernet module, die via SPI aangestuurd wordt. De C-routines hiervoor zijn afgeleid van de Arduino sketches (die erg rommelig in elkaar zaten). Met deze toevoeging wordt het voor de brouw-hardware mogelijk om via UDP te werken, in plaats van via de USB verbinding. Bij opstarten van de brouwhardware wordt via de USB poort de status weergegeven, waaronder het gevonden IP-adres van de brouwhardware. Dit ziet er als volgt uit:
De scheduler van het PC-programma zien we ook hier weer terug. Mooi staaltje van hergebruik van code op verschillende platforms.
Terug naar boven