Arduino Sous Vide controller

Deze pagina moet ik nog afmaken!!! Is nog maar concept, details missen.

Sous Vide Kookplaat
Plaatje van het voorlopige resultaat:
het oude kookplaatje, de besturing, en de roermotor/temperatuursensor

Sous Vide koken is helemaal in (en is ook lekker). In een waterbad op lage temperatuur garen in een plastic zak, zo rond de 45..50 graden voor zalm, 50..70 voor vlees, 80..90 voor groenten. Hoeft niet per se heel lang; voor zalm is een half uur voldoende, voor mals vlees 1..2 uur. Maar, stoofvlees 1..2 dagen...

Ik had nog een oude 'klassieke' elektrische kookplaat liggen. Samen met een Arduino Nano en een temperatuursensor is daar prima een sous vide kookplaat van te maken. PS: de opbouw komt op veel punten overeen met mijn oven-controller. Het idee: aansturing met een optisch geïsoleerd Solid State Relais, een I2C temperatuursensor, de Arduino voor de PID regelaar, en een roermotortje.

De PID-regelaar

Wat is een PID?

Klinkt allemaal niet zo moeilijk, maar hoe houd je de temperatuur constant? In de industrie doen ze zoiets met een PID-regelaar:

  • De basis-regeling is 'proportioneel'. Je regelsignaal (hier de hoeveelheid energie naar de kookplaat) is evenredig met de afwijking (fout) 'F': het verschil in ingestelde temperatuur en gemeten temperatuur. Je aansturing van de kookplaat is dan de fout 'F' vermenigvuldigd met versterkingsfactor 'P'.
  • Nadeel van alleen 'P' is dat je de afwijking nooit nul krijgt, als de verschilwaarde te klein wordt zakt het regelsignaal in, en koel je weer af. Dus: toevoegen van een integraal-term: de som van de verschillen over een bepaalde periode (de lange-termijn afwijking): de 'I'-term.
  • Nu nog demping, zodat je niet doorschiet met het opwarmen: als de verandering te snel gaat (het verschil van de huidige fout ten opzichte van de vorige meting is te groot) moet het wat minder hard: de 'D'-term
  • Dus je foutsignaal op tijdstip i: Fi = Tset - Ti , en je regelsignaal (energietoevoer) is P * Fi + I * (som van laatste N Fi's) + D * (Fi-1 - Fi).

Voor meer uitleg is veel te vinden op internet, bijvoorbeeld op Wikipedia.

Een model

Asymmetrisch

Let op: opwarmen gaat veel sneller dan afkoelen. Toevoegen van energie is makkelijk met het kookplaatje, maar het plaatje kan niet koelen, dit moet gewoon via de lucht gebeuren. Het systeem is dus niet symmetrisch / lineair.

Dus je hebt waardes voor P, I en D nodig: de PID-regelaar. Hoe kom je daar aan? Er is natuurlijk een heleboel meet- en regel-theorie, maar daarvoor moet je ook de warmtecapaciteit van de pan en zo weten... Ik heb het wat praktischer aangepakt. Eerst het opwarm- en afkoel-tempo van de plaat met pan gemeten. De energie warmt eerst de plaat op, en deze warmt vervolgens de pan met water op: een 2e orde systeem. In een spreadsheet heb ik hier een simpel model van gemaakt met weergave in een grafiek, met dezelfde 10 seconde tijdstappen als in de meting. Vervolgens de waardes aangepast zodat het model qua opwarmen en afkoelen vergelijkbaar is met wat ik met de meting gevonden had.

<uitleg model>

Daarna heb ik in hetzelfde spreadsheet de PID-regeling toegevoegd, en het resultaat ook in de grafiek geplot. Ik kon nu makkelijk het effect van de verschillende factoren van de regeling zien; wat doen de P, I en D-waardes? Wat zijn goede waarden?

<uitleg PID toevoeging>

Ook belangrijk, hoe stabiel is het systeem? Metingen zijn niet perfect, verstoort ruis het regelgedrag (vooral de D-factor, het verschil tussen opeenvolgende foutwaardes, is erg gevoelig voor ruis)? Om dit te testen heb ik ruis toegevoegd. Ook de 'quantisatie' ven je meetsignaal (het feit dat de temperatuursensor alleen in stapjes de temperatuur kan weergeven, in het geval van de LM75BD stappen van 1/8 graad) is vergelijkbaar met een soort ruis (quantisation noise), die ik in het model heb meegenomen.

PID in de Arduino

Als je eenmaal de PID-waardes hebt is het programmeren op de Arduino niet zo moeilijk. Ik wilde niet in floating point werken (Arduino is maar een simpele 8-bit processor), dus heb gekozen voor zogeheten 'fixed-point', wat in de praktijk neerkomt op werken met (16 bits) integers met een schaalfactor. In mijn geval heb ik gekozen voor '4 bits achter de komma', dus een schaalfactor van 16: het 'fixed point 12.4 format'.

<plaatje met fixed-point format en voorbeelden>

Wel oppassen dat je getalwaardes blijven 'passen' in de 126 bit integers, de 12 bits voor de komma herbergen ook het tekenbit, en er blijven dus 11 bits voor de getalwaarde voor de komma over: je bereik is -2048 .. 2047. Bij een 'D'-waarde van 30 mag je verschilwaarde dus niet boven de 2047/30 uitkomen (zeg maar 2048/32, om in machten van twee te denken: je houd (11-5) = 6 bits over): begrens de verandering van de fout op -63..63, dus niet sneller dan 63 graden per 10 seconden opwarmen. Zo sterk is mijn kookplaat toch niet.

Sous Vide controller met de Arduino nano
Het schema (ongeveer) van de Sous Vide controller.
In rood het gedeelte dat direct aan de 230V hangt (voorzichtig)!
Niet getekend: de 5-Volt USB voeding ('+USB') voor het geheel.

De uitwerking

In de figuur hieronder is de eerste opbouw van de electronica te zien. Centraal de Arduino Nano. Links een draaiknop (10K potmeter) en het toetsenbordje, rechtsboven de aansluitpinnen voor de I2C LM75BD temperatuursensor, naar rechts de draadjes voor de SSR control en de roermotor (buiten beeld). Onder het 7-segment display met TM1637 chip. Draaiknop vind ik makkelijker in gebruik dan het instellen van de temperatuur en zo met drukknopjes. Niet zichtbaar op de foto: de SSR, de ingebouwde USB voeding voor de Arduino, de NTC voor thermische beveiliging, en de MOSFET voor de roermotor.

De blokjes en schema

Sous Vide controller: de componenten
De kern: Arduino en user interface

Het 'Solid State Relais' is een blokje waarmee je hoog-vermogen 230 Volt/25 Ampere kan schakelen (merk Kongin type KG-25 DA). Deze is optisch geïsoleerd (dus de aansturing is gescheiden van de 230 Volt), en heeft een zero-crossing circuit (DA-type), dus schakelt alleen op de nul-doorgangen van de 230 Volt. Omdat het kookplaatje zich gedraagt als weerstand (dat is het ook) schakelt dit heel mooi: geen stoorsignalen. Ik regel dan ook (net als in mijn oven-controller) door meer of minder hele 50-Hertz periodes door te laten (uit een serie van 16). Voorbeeld: bij 25% vermogen laat ik 4 van de 16 50-Hertz periodes door.

Motortje (uit speelgoed) is 1.5 Volt, geen 5 Volt: met de PWM-uitgang van de Arduino een 'geschakelde voeding' gemaakt met een BSO304SN MOSFET, en de motor als spoel. Geeft gelijk een snelheidsregeling. Wel de MOSFET nooit continue open zetten, vind de motor niet leuk... Daarom ook de 100K weerstand tussen de gate van de FET en aarde, als de ingang losschiet, of door een reset naar hoogohmig gaat, gaat de gate naar aarde en schakelt de FET uit. Met behulp van een roestvrij stalen buisje (van LED-tuinverlichting) en wat blik een mooie roerder gemaakt, met een kleine schroef op een lange as (fietsspaak) naar het motertje bovenin; werkt perfect. Ook de temperatuursensor wordt hierop vastgezet, zodat de sensor goed in de stroming van het water zit.

De twee I2C-lijnen zijn ontstoord met 1 nF, maar zijn daardoor ook wat trager: in de Arduino heb ik de I2C klok iets verlaagd (50 kHz). En de pull-ups natuurlijk niet vergeten. Die zijn overigens niet nodig op de pseudo-I2C voor het display: het display heeft deze weerstanden zelf aan boord. De draaipotmeter en NTC zijn ook ontstoord met condensatoren.

User Interface

FrontpaneelIk houd ervan de besturing simpel te houden... 3 knopjes voor keuze voor instelling van temperatuur, tijd, panmaat, en een start-knop. Plus een draaiknop voor het instellen van de eigenlijke waarde:

  • Temperatuur 30° – 95° en ‘aan’ ('aan': normale kookplaat met timer, niet geregeld)
  • Panmaat: 1.5, 2.5 en 4.0 liter
  • Verwarmingstijd 0 .. 12 uur in stappen van 10 minuten (0=continue, geen tijdslimiet)

En een display voor instellingen: temperatuur, overblijvende tijd. En dit in een retro-stijl passend bij de kookplaat ;-)

De Software

Sous Vide state machineSoftware is gebaseerd op een simpele state machine, zie rechts. Een Arduino 'C++' file:

  • 7Seg display aansturing, met als basis de TM1637Display.h library
  • Keypad debounce en event detectie
  • Sensor afhandeling (filtering): I2C LM75BD met de Wire.h library, analoog NTC en draaipotmeter. Temperatuur moet goed gefilterd worden, vanwege de gevoeligheid van de PID-regeling voor ruis.
  • Timer interrupt en tijd, met als basis de TimerOne.h library
  • PID regelaar in 12.4 fixed point format
  • State machine, zie rechts
  • Setup en main loop (Arduino style)

Display (~€3 bij dx.com) is blijkbaar toch niet echt I2C-compatible... Dus niet op de I2C-pinnen aansluiten, want daar zit de temperatuursensor. Gelukkig heeft 'avishorp' al een goede Arduino library voor de TM1637 geschreven die werkt voor 2 willekeurige pinnen: werkt in een keer, en in de zip download zit ook de English datasheet (niet alleen de Chinese versie)! Dankzij het 'character designer' spreadsheet van JosePino kan ik ook tekst makkelijk weergeven, niet alleen getallen.

Statistieken van de code: ~10K code (33%), ~850 bytes RAM (40%), ~800 regels incl. commentaar en debug-strings.

Debug

Altijd handig om te weten wat er in het programma gebeurt... Een PID-regelaar is best complex qua gedrag. Nu heeft de Arduino niet echt een debugger, maar met de snelheid van dit regelsysteem is single-stappen ook niet echt een optie. In plaats hiervan maak ik gebruik van de Arduino Nano mogelijkheid om samen met de Arduino-omgeving een 'virtuele' seriële poort te gebruiken over de USB-kabel. Handig voor debug-output (kan overigens ook met andere seriële terminals, hoeft niet per sé vanuit de Arduino omgeving).

Elke PID stap, dus elke 10 seconde, druk ik de gemeten en berekende waarde af via die seriële poort, en vang dit op op de PC. Dit kan ik dan later makkelijk in een spreadsheet inlezen en bekijken. Is er overshoot? Wat is de gemiddelde fout? Is de zaak stabiel? Hoeveel ruis op de sensor? Zie verderop bij de resultaten hoe de eerste echte meting er uit zag.

Veiligheid eerst

Een aantal maatregelen:

  • Watchdog timer op 1 seconde om in geval van crash de zaak uit te zetten (reset)
  • SSR zwaarder genomen dan nodig is (25 Ampère in plaats van 8 Ampère): Chinees spul haalt niet altijd de specs die vermeld zijn...
  • Interne temperatuursensor (NTC) op ~70..80°C die het SSR in de gaten houdt (ondanks de marge op de SSR)
  • Behoud van de oude temperatuurschakelaar op kookplaat als limiet/droogkookbeveiliging
  • Fout-checks op sensoren als op I2C protocol, zinnigheid gemeten waardes, en zo
  • En mechanisch natuurlijk zorgvuldig bouwen, komt in een soms vochtige omgeving: aarding, isolatie, ...

Zou voldoende moeten zijn.

De resultaten

Metingen Sous Vide Zalm
Metingen tijdens de Sous Vide zalm...

En daar gaat het natuurlijk om: werkt het? Geprobeerd met zalm, 30 minuten op 49°C. De zalm neutraal gehouden, wel even droog gepekeld, en met iets olie in een zip-lock zakje, het de mond vacuüm gezogen. De eerste test liet nog wat probleempjes zien, zie ook het grafiekje rechts met temperatuur T (en ook de PID-termen en de energie-waarde E).

  • De roermotor viel een keer stil; net te weinig toeren → PWM met 10% verhoogd
  • De I2C sensor ging een aantal keer op tilt (met nette foutmelding op display) → beter herstel na een fout, reset van de I2C software driver
  • Circulatie in de pan was niet optimaal → grotere pan en de zalm in een soort open mandje
  • Temperatuur schoot iets door (max 54°C in plaats van de ingestelde 49°C) en koelt dan héél langzaam af → I-factor pas in laten gaan als de temperatuur haast bereikt is (voor de eerste keer)

Maar... de zalm was prima gaar, en heel lekker! Heel kort nog even op de huid gebakken (lastig, met zo'n gare maar niet droge zalm; valt uit elkaar als je niet heel voorzichtig bent).

Een paar richtlijnen bij het koken:

Vlees Rare
Medium/rare
Well Done
Rund: biefstuk
normaal
stoof/draadjes
54°C / 1..2 uur
56°C / 7..16 uur
55°C / 24..48 uur
58°C / 1..2 uur
60°C / 6..14 uur
65°C / 16..24 uur
68°C / 1..2 uur
70°C / 5..11 uur
85°C / 8..16 uur
Varken


58°C / 1..3 uur
58°C / 3..6 uur
60°C / 8..24 uur
62°C / 1..3 uur
62°C / 3..4 uur
68°C / 8..24 uur
70°C / 1..3 uur
70°C / 3..4 uur
85°C / 8..16 uur
Zalm
43..46°C / 30 min 49°C / 30 min 53°C / 30 min
Kip
60°C / 1..3 uur 65°C / 1..3 uur 75°C / 1..3 uur
Lam (mals)

54°C / 1..2 uur

Nuttige Libraries etc