Skip to main content.

Software

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).

Welke programmeertaal moet er gebruikt worden? Ik ben niet echt een voorstander van moderne programmeertalen zoals Java en C#/.Net (ik heb nog nooit MS programmeeromgevingen gebruikt en dat was ik nu ook maar niet van plan!).
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.
En als je nu ook nog eens Borland's meer dan uitstekende C++ Builder gebruikt, dan is het programmeren hiervan echt een feest om te doen!

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 e-brew! gedoopt heb, hetgeen staat voor elektronisch brouwen).
Deze pagina bestaat dan ook uit de volgende paragrafen:

1. Overview / Architectuur


Dit plaatje laat de software architectuur zien. Ik heb geprobeerd om de software zo modulair mogelijk te ontwerpen, zodat als ik ook hardware ga wijzigen, of overstap op andere / nieuwere ICs, ik relatief makkelijk de software kan wijzigen.

Terug naar boven

2. Main Interrupt Loop

De e-brew! applicatie vraagt strakke timingseisen, omdat er verschillende AD conversies gedaan moeten worden. Om ruis en andere onregelmatigheden zoveel mogelijk te minimaliseren, moeten die AD conversies op vaste momenten in de tijd gebeuren. Het zou heel mooi zijn om de beschikking te hebben over een real-time embedded operating systeem, maar Windows komt bij zoiets nog niet eens in de buurt. Om de 50 milliseconden iets uitvoeren, wordt al erg lastig. Gelukkig is er een klein C++ object, dat Animation Timer (TAnimTimer) heet, die zorg draagt voor een nauwkeurige timing, tot op milliseconde niveau (0.001 seconde). En dit is afdoende voor onze doeleinden.

Door dit object op het Main Form te plaatsen van de e-brew! applicatie, en door gebruik te maken van de OnTimer() event ervan, kan een nauwkeurige timer interrupt verkregen worden. Wat er ook gebeurt in de e-brew! applicatie of in Windows (behalve een complete systeemcrash), de timer interrupt treedt iedere 50 milliseconden op (dit is 20 keer per seconde). Deze timer interrupt is dan ook de belangrijkste tijdbasis voor de e-brew! applicatie. Alles wat binnen het programma gedaan wordt, is gerelateerd aan deze 50 msec. interrupt!


Deze figuur laat een zogeheten structure chart zien van die timer interrupt (die hier t50msec2timer() genoemd is). Het laat zien wanneer en welke functies aangeroepen worden vanuit deze timer interrupt.
Deze timer interrupt wordt dus iedere 50 msec. aangeroepen. Maar het is niet erg zinvol en economisch om alle functies in diezelfde 50 msec. interrupt aan te roepen. Als voorbeeld hiervan de PID regelaar routine. Als deze 1 keer per 5 seconden aangeroepen wordt, dan is dat snel genoeg. Hetzelfde geldt voor de LED displays: als deze iedere seconde bijgewerkt worden met een nieuwe waarde, dan is dat meer dan snel genoeg.
Dit houdt dus in dat we deze timer interrupt routine kunnen verdelen in zogeheten timeslices. In iedere timeslice kan dan een bepaalde functie aangeroepen worden. Op deze manier wordt de werklast dus netjes verdeeld in de tijd.

Omdat we 20 interrupts aanroepen per seconde hebben, is het logisch om 20 timeslices te maken. In de structure chart zijn ze dan ook genummerd van TS1 tot en met TS12 (TS13 tot en met TS20 worden nog niet gebruikt). In timeslice TS1, wordt de functie get_analog_input() aangeroepen. Deze leest de waarde van het HLT volume van de AD-converter. In timeslice TS2 wordt dezelfde functie nog eens aangeroepen, maar dan om het MLT volume in te lezen. Enzovoorts.

Alleen de functie Generate_IO_Signals() wordt iedere keer aangeroepen. Deze functie verstuurt de binaire IO signalen naar de elektronica (bijv. het knipperen van de Alive LED, die 500 msec. aangezet wordt en dan weer 500 msec. uitgezet wordt).

Terug naar boven

3. 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'). Wanneer een overgang naar een andere toestand uitgevoerd wordt, dan kan er ook een bijbehorende actie uitgevoerd worden. (bijv. 'zet pomp aan').

Samengevat: er zijn toestanden, overgangen tussen die toestanden, condities en acties. Deze zaken moeten gedefinieerd gaan worden voor de e-brew! applicatie.

Het eerste dat we moeten doen is een analyse maken van het brouwproces, om hieruit de unieke toestanden af te leiden. Voor het brouwprogramma kom ik uiteindelijk op de volgende toestanden uit:
De rode teksten in de figuur stellen de condities voor. Wanneer zo'n conditie WAAR wordt, dan wordt die overgang uitgevoerd. Tijdens deze overgang, wordt de bijbehorende actie (de groene tekst) uitgevoerd.
De tabel (rechter bovenhoek) laat zien welke kleppen in welke toestand open (1) of gesloten (0) zijn. 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 (wordt aangeroepen vanuit de timer interrupt).

Terug naar boven

4. Grafische User Interface (GUI)

De timer interrupt en het toestandsdiagram vormen het hart en ziel van het brouwprogramma. Maar om dit flexibel aan te kunnen sturen en te controleren, is het van belang om een goede gebruikersinterface (Graphical User Interface of GUI) te realiseren. Dat is inmiddels gebeurd en deze paragraaf laat een aantal zaken daarvan zien. Zo zie je hier een screenshot van het hoofdscherm van de e-brew! applicatie:

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:

4.1 De menu-balk van het e-brew! programma

De menu-balk van het brouwprogramma bevat de volgende menu items:

Terug naar boven