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).
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 (inmiddels gebruikelijke) USB verbinding. En dan wordt toch een ontwerp m.b.v. een microcontroller weer interessant. 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 een USB kabel 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.
Welke programmeertaal moet er gebruikt worden voor beide systemen? Voor de firmware is dat duidelijk: ik maak gebruik van een Arduino Nano, die ik via Atmel Studio in de programmeertaal C aanstuur. In Embedded land is C de standaard en zijn zelfs vrijwel geen andere talen voorhanden. Voor het PC-programma is dat minder duidelijk door het grote aanbod op PC gebied. Ik ben niet echt een voorstander van moderne programmeertalen zoals Java en C#/.Net (ik heb nog nooit MS programmeer omgevingen 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 / Software-Architectuur
- 2. De Scheduler
- 3. Het toestandsdiagram
- 4. Grafische User Interface (GUI)
- 5. Firmware voor de Arduino Nano / ATmega328
1. Overview / 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 tegen te komen. Daarnaast zijn er echter ook een aantal componenten die in de taal C geschreven zijn. Maar deze kunnen relatief gemakkelijk vanuit een C++ object worden aangeroepen. De belangrijkste componenten zijn:
- Een Scheduler met diverse taken die op vaste momenten uitgevoerd moeten worden.
- Een toestandsdiagram die voor de overall besturing van het programma zorgt.
- Diverse grafische objecten die de verschillende schermen van het PC-programma omvatten. Per scherm is er 1 grafisch object.
- Diverse routines die de lees- en schrijf-operaties naar een COM-poort verzorgen. De COM poort is niet fysiek aanwezig, maar wordt via de USB-poort gerealiseerd. Dit wordt een 'virtuele COM poort' genoemd.
- Een achtergrondproces (ebrew_idle_handler()) die alle grafische objecten op het scherm regelmatig bijwerkt.
- Een PID-regelaar functie. Voor de implementatie hiervan, zie Implementatie PID regelaar
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 TMAinForm()) bevat al ongeveer 1600 Lines of Code (LOC). De totale PC-applicatie omvat ongeveer 4400 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.28 waren dit ongeveer 3400 regels C code. Alles bij elkaar dus ruim 7700 regels code!
Een volledig functionele versie van het PC-programma kun je hier downloaden (.zip file, v1.83). Voor een goede werking heb je uiteraard ook nog de hardware met de juiste firmware nodig.
Terug naar boven2. 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
//-----------------------------------------
add_task(task_alive_led , "alive_led" , 0, 500); /* 0, 500, 1000, 1500 */
add_task(task_read_temps , "read_temps" , 100, 2000);
add_task(task_pid_ctrl , "pid_control" , 300, (uint16_t)(pid_pars_hlt.ts * 1000));
add_task(task_update_std , "update_std" , 400, 1000); /* 400, 1400 */
add_task(task_hw_debug , "hw_debug" , 600, 2000);
add_task(task_read_flows , "read_flows" ,1100, 2000);
add_task(task_log_file , "wr_log_file" ,1600, 5000);
add_task(task_write_pars , "write_pars" ,1700, 5000);
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(ms) M(ms)
-------------------------------------
alive_led 500 0x02 0.4 0.5
read_temps 2000 0x02 51.3 51.6
pid_control 20000 0x02 0.0 0.0
update_std 1000 0x02 1.2 1.3
hw_debug 2000 0x03 0.0 0.0
read_flows 2000 0x02 49.9 49.9
wr_log_file 5000 0x02 0.9 1.0
write_pars 5000 0x02 0.0 0.0
Uit dit overzicht blijkt dat task_update_std() maximaal 1.3 msec. 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 OnTimer() routine van een timer 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 boven3. 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 ROOD 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 GROEN 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.
- 14. Pump Pre-Fill: 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.
- 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. Na afloop kan de brouwer aangeven dat dit gebeurd is. Deze toestand wordt maar 1 keer uitgevoerd.
- 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_xSec.
- 07. Delay_xSec., 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 boven4. Grafische User Interface (GUI)
De scheduler met alle taken 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 het PC programma:

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 MLT temperatuur zien van 24.59 °C. De gewenste (referentie) temperatuur voor de MLT is hier 63 °C en voor de HLT is dat 36 °C (dit screenshot is genomen tijdens een debugsessie, het zijn dus geen echte waarden uit de praktijk).
- PID regelaar schakelpaneel: De PID regelaar kan met dit schakelpaneel aan- (knop is groen) en uitgezet (knop is rood) worden. Wanneer de PID regelaar uitgezet wordt, dan is de output altijd gelijk aan 0 %. Dit is de regelaar voor de HLT, de regelaar voor de kookketel wordt automatisch aan gezet.
- Huidige toestand: Dit label geeft de actuele toestand weer van het toestandsdiagram. De huidige toestand in het screenshot is "00. Initialisation". Door met de rechtermuisknop hierop te klikken, komt er een menu tevoorschijn waarmee de brouwer diverse handmatige instellingen kan verzorgen (zoals: 'mout is toegevoegd').
- Temperatuur van de elektronica: dit is de actuele temperatuur van de koelplaat van de vermogenselektronica (de triac). De thermometer kleurt rood wanneer de temperatuur te hoog wordt (de output van de PID regelaar wordt dan 0 %). De huidige temperatuur is hier 0.0 °C (geen sensor aangesloten).
- Vermogensbalk: dit is de rode balk met de tekst "HLT Power" en "Boil Power". Het geeft de output van de PID regelaars aan. Hier is dat voor beide regelaars 0 %.
- De actuele volumes in de ketels: in het screenshot is het volume voor de warmwaterketel (HLT) 197.1 L, voor de maischketel (MLT) 2.9 L en de kookketel nog 0 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 drie 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 en de derde flowsensor is op de uitgang van de tegenstroomkoeler gemonteerd. Deze waarden geven het totaal aantal liters weer dat door de sensoren gestroomd is. In dit geval staan de eerste sensor op 2.9 L, de andere sensoren staan nog op 0.0 L.
- 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 dit nu op Automatisch.
- De status van iedere elektrische klep: wederom zijn, voor iedere klep, drie opties mogelijk: "Auto", "Off (M)" en "On (M)". In het screenshot staan alle kleppen op automatische besturing en staan ze allemaal uit.
- Links onderin kan nog specifieke debug informatie aangegeven worden voor de PID regelaars. Met de weergegeven getallen kan de correcte werking van de PID regelaar nagegaan worden. In het screenshot is dit niet zichtbaar (optie staat nog uit).
- De status balk: de status balk geeft wat algemene informatie weer, zoals bijv. het huidige versienummer van het brouwprogramma (R1.83) en van de brouw-hardware (R1.28).
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 wordt de MLT temperatuur en de waarden van de beide flowsensoren correct ingelezen.
4.1 De menu-balk van het e-brew! programma
De menu-balk van het brouwprogramma bevat de volgende menu items:
- File -> Read Log File...: wanneer er een fout opgetreden is in de hardware of de software, dan kan met behulp van deze functie het systeem weer terug gebracht worden in de toestand net voor de crash.
- File -> Exit: afsluiten van het brouwprogramma, alle elektronica wordt uitgezet en de USB communicatie wordt afgesloten.
- Edit -> Mash Scheme...: met deze optie kunnen tot 10 temperatuur-tijd paren ingevoerd worden. Hiermee kunnen specifieke tijden en temperaturen voor een maischschema ingevoerd worden.
- Edit -> Fix Parameters...: 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.
- View -> Mash/Sparge Progress: 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.
- Help -> Contents...
- Help -> How to Use Help
- Help -> About...: laat het versienummer zien van het brouwprogramma.
- Options -> EBrew Hardware Settings...: hiermee kunnen verschillende parameters ingesteld worden die te maken hebben met de hardware.
- Options -> PID Controller Settings...: hiermee kunnen verschillende parameters ingesteld worden die te maken hebben met de PID regelaar.
- Options -> Sparge & Mash Settings...: hiermee kunnen verschillende parameters ingesteld worden die te maken hebben met het maischproces, het spoelproces en het toestandsdiagram.
- Options -> Measurements Settings...: hiermee kunnen verschillende parameters ingesteld worden die te maken hebben met het meten van temperaturen en volumes.







5. 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 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 PCA9544, de MCP23017 en de DS2482. De totale opzet (architectuur) ziet er hiermee als volgt uit:

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 is al voorbereid op de toevoeging van een WIZ550io Ethernet module. 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. Dit is echter nog geen standaard onderdeel van de huidige firmware, maar work-in-progress. Het toevoegen van zo'n library legt namelijk een flinke claim op de resources van de microcontroller (met name Flash geheugen en RAM geheugen).
De scheduler van het PC-programma zien we ook hier weer terug. Mooi staaltje van hergebruik van code op verschillende platforms.
Terug naar boven