Schrijven van macro’s in USB-CNC


Description: Basiskennis voor het schrijven van macro’s in USB-CNC

Author: create
Date: 06 mar 2018 20:00
Weergaves: 225
Category: Edingcnc

Link to article (bb-code [URL]): Copy

[url=http://cnczone.nl/knowledgebase/article?k=1]Schrijven van macro’s in USB-CNC[/url]

Direct link: Copy

http://cnczone.nl/knowledgebase/article?k=1

Basiskennis voor het schrijven van macro’s in USB-CNC
Door Arie Kabaalstra

Introductie
In het topic: http://www.cnczone.nl/viewtopic.php?f=39&t=2968 schreef ik al:
eigenlijk is programmeren ( in welke taal dan ook ) niets anders dan een reeks voorwaarden en instructies en wat controles of aan die voorwaarden wordt , of is voldaan..


een poosje geleden heeft Bert Eding het bestand MACRO.CNC in het leven geroepen.
MACRO.CNC bevat standaard al een paar SUBROUTINES die in USBCNC worden gebruikt voor een aantal taken, zoals het wisselen van gereedschappen, en het oproepen van de lengte-offset, het HOMEN van de machine, en het meten van je werkstukhoogte en gereedschaplengte.

Zelf kun je daar nog van alles en nog wat aan toevoegen, Bewerkingen die je vaak uitvoert kun je als SUBROUTINE in MACRO.CNC zetten zodat je ze makkelijk op kan roepen, ook vanuit andere programma's, hiermee kun je als het ware, net als in "hogere programmeertalen" zoals C++ en Visual Basic "Object georienteerd programmeren" (wat dat inhoudt, daar kom ik later in dit topic op terug)

MACRO.CNC kun je zien als een BIBLIOTHEEK-BESTAND, een soort "Class "of "DLL" als bij C++ of Visual Basic

en ik begrijp dat dit nog enige uitleg vereist voor diegenen die nog niet veel ervaring hebben in het programmeren (in welke taal dan ook )
Waarom ik die opmerking "in welke taal dan ook" gebruik zal ik even uitleggen..
Er zijn een aantal commando's die in ELKE programmeer taal gebruikt worden, of dat nu Basic, MSX, DOS, Pascal, Epoc, Symbian of Heidenhain is.
't enige verschil is de "Syntaxis", de manier waarop het geschreven wordt (zeg maar de "Grammatica van die taal" )

deze commando's zijn de zogenaamde "Conditional statements (in het engels wordt de term Commando aangeduid als statement )
een conditional statement laat zich dus vertalen als "Voorwaardelijk commando", dat wil zeggen dat deze commando's actief zijn onder bepaalde voorwaarden, welke?.. dat bepaal je lekker zelf, en daarom zijn ze zo veelzijdig.



In USBCNC ( want daar gaat het tenslotte om) hebben we de beschikking over:
IF (ELSE)
ENDIFWHILE
ENDWHILE

Verder kun je in USBCNC met Parameters programmeren, een parameter is eigenlijk een "geheugenplekkie" met een "Label" ze worden in USBCNC aangeduid met een # gevolgd door een nummer, het label
de Parameters die je "Vrij" kunt gebruiken zijn de labels 1 t/m4999, waarbij ik even aanteken dat 4996 t/m4999 worden gebruikt in de toolmeetmacro's die ik samen met Bert Eding geschreven heb voor de releases vanaf 3.49

#4000 tm #4999 worden tevens bij het afsluiten van USBCNC opgeslagen, en hebben de volgende keer dat je USBCNC Start nog steeds dezelfde waarde, #1 t/m #3999 worden elke keer na afsluiten gewist, en zijn dus 0 als je USBCNC opnieuw start

Hier: http://www.edingcnc.com/upload/files/us ... _v3.49.pdf
vind je op pagina 50 een keurig overzicht van alle labels de Labels boven 5000 kun je ook gebruiken in macro's je moet wel als je bijvoorbeeld wilt gaan rekenen met de afmetingen van het gereedschap, die waarden haal je dan "uit de tabel"

Programma's kun je ook nog indelen in SUBROUTINES
Macro's schijf je als SUBROUTINES in MACRO.CNC zodat je ze "vanuit elke hoek in USBCNC" Kunt oproepen

SUB (naam)


ENDSUB

een sub(routine) is een stukje programma dat je aan kunt roepen met GOSUB
als je met GOSUB FREZEN verwijst naar SUB FREZEN, dan gaat USBCNC vanaf die regel verder in SUB FREZEN, om bij ENDSUB terug te keren naar de regel ONDER GOSUB FREZEN, USBCNC maakt dan eigenlijk een "Zijsprongetje"

de voorwaardelijke commando's, Parameters en SUB's zijn de "Bouwstenen" waar je een Macro mee bouwt.


Dialogen:
Wat hebben we aan een programma met parameters, als die parameters (nog) geen waarde hebben?, NIETS.. en daarom zijn er een aantal manieren om ze een waarde te geven:

ten eerste:
aan het begin van het programma de parameters een waarde geven:
Code:
#1=100 ; voeding horizontaal
#2=30 ; voeding verticaal


Maar da's een beetje een "Starre methode", mooier is het om met DLGMSG te werken.
DLGMSG staat voor Dialog Message, een dialoog in je macro, die je vraagt om bepaalde waarden in te voeren die dan aan parameters worden toegekend
DLGMSG werkt als volgt":
DLGMSG "koptekst" "tekst voor uitleg invoer" label "tekst voor uitleg invoer" label.
Voorbeeld:
Code:
DLGMSG "invoeren waarden" "waarde 1" 1 "waarde 2" 2


hier worden de ingevulde waarden toegekend aan #1 en #2
of het moet weet ik niet, maar ik zet altijd overal een spatie tussen, dat houdt je code een beetje leesbaar.

Voorwaarden: IF (ELSE)

het if-then commando is als het ware opvoeden.. we hebben het als Kind al zo vaak van onze ouders gehoord:
"als je je kamer opruimt (IF) krijg je wat lekkers, en anders zwaait er wat(ELSE)

diegenen die kinderen hebben, zullen met dit commando weinig moeite hebben..

de Syntaxis:

IF[voorwaarde]
actie
(ELSE)
( actie )
ENDIF (hiermee geven we 't einde van dit commando aan)
Code:

IF [#1==100]
G0 x#1
ENDIF


Bovenstaand voorbeeld kijkt of #1 de waarde 100 heeft (in dit geval moet er == staan, dat is geen typefout, maar de syntaxis van USBCNC )
Alleen dan gaat de machine naar X100 ( de waarde van #1 ), als je een andere waarde ingeeft doet USBCNC hier in dit stukje Code niets mee, USBCNC kijkt of aan de voorwaarde wordt voldaan, zoja, voert ie de regels uit onder het IF Commando tot ie ENDIF tegenkomt, daar is het Commando mee afgesloten,als #1 niet gelijk is aan 100, dan slaat USBCNC het stuk tussen IF en ENDIF over.
Code:
IF [#1==100]
G0 X#1
ELSE
G0 Y#1
ENDIF


In dit voorbeeld gaat de machine naar X#1 als #1 gelijk is aan 100, in elk ander geval gaat ie naar Y#1
Hier hebben we dus al iets meer mogelijkheden..

als je een hele reeks mogelijkheden wilt "Toetsen" kun je het volgende trucje toepassen:
Code:
IF [#1==100]
G0 X#1
ENDIF
IF [#1==110]
G0 X#1
ENDIF
IF [#1==120]
G0 X#1
ELSE
G0 Y#1
ENDIF


hier gaat USBCNC naar X100, X110 of X120 als #1 100,110 of 120 is, anders gaat ie naar Y#1


SUBROUTINES: GOSUB

Vaak is het handig in een Macro om een bepaald stukje "apart" af te lopen, dit is dan een "onderliggend stukje programma", een SUBROUTINE, alsof je in een bak onderdelen graait naar bepaalde onderdelen, en daar iedere keer dezelfde handeling mee uitvoert.

de macro's die we schrijven en opslaan in MACRO.CNC zijn allemaal SUBROUTINES, we kunnen ze op elk gewenst moment aanroepen en uitvoeren, vanuit MDI, met het intikken van GOSUB FREZEN, roepen we de SUB FREZEN op, en als je die start voert USBCNC uit wat er in die SUB staat, en keert dan terug naar zijn "uitgangspositie"

Vanuit een PROGRAMMA, in mijn MACRO.CNC staat bijvoorbeeld een SUB TOOL, die een gereedschapslengte meting uitvoert.

als ik een programma maak met meerdere gereedschappen, is het wel handig als de machine em even inmeet voor me.. dus na elke M6 T.. staat bij mij in de Code GOSUB TOOL, na elke wisseling gaat ie dus even meten hoelang mijn tool is, zodat ik mijn Z-hoogte niet aan hoef te passen.. ( moet je ook eigenlijk niet doen.. je werkstuk wordt niet hoger als je frees korter is )

Sinds USBCNC 3.49 is er een "User-Menu", met 11 F-toetsen die verwijzen naar SUB USER_1 tot en met SUB USER_11

Aan de eerste 2 zijn al Gereedschapmeet macrootjes gekoppeld. de resterende 9 kun je naar eigen goeddunken en hartelust vullen met je eigen macro's die je veel gebruikt en snel wilt kunnen vinden..

vanuit een SUBROUTINE kun je ook andere SUBROUTINES aanroepen, dit kun je doen na een IF commando: als aan een bepaalde voorwaarde wordt voldaan ga je naar een bepaalde SUB.

Hier zien dit ook mooi terug:
Code:
sub cirkel
DlgMsg "Voer ...
...
DlgMsg "Coordinaten o.k.? Toets 0 of 1" Jaofnee 57
If [#57 == 0]
gosub cirkel
endif


als je 0 invult bij de tweede DLGMSG, waar gevraagd wordt of de positie juist is, dan springt USBCNC terug naar het begin van SUB CIRKEL, en vraag je nogmaals om de Coordinaten juist in te vullen

en..
Code:
sub cirkel
DlgMsg "Voer ...
...
gosub uit
endsub

sub uit
msg "Bewerkingen klaar"
M5
M2
endsub


als de SUB CIRKEL klaar is met zijn bewerkingen, dan stapt ie naar SUB UIT waar USBCNC een MSG ( Message ) geeft dat de bewerking klaar is.

MSG overigens, is't kleine broertje van DLGMSG, MSG toont geen Dialoog, maar geeft alleen een tekst weer in het Message venster in USBCNC

Voorwaarden: WHILE- ENDWHILE

Het While Commando is het tweede voorwaardelijke commando, waar IF kijkt of iets aan de voorwaarde voldoet, is een WHILE actief ZOLANG er aan de voorwaarde wordt voldaan.

dit is erg handig als je bijvoorbeeld een macrootje wilt maken om iets in meerdere sneden uit te frezen
Code:
while [#60 >= #64]
G01 X[#59] Y[#51] F[#56]
G01 Z[#60] F20
msg "Frezen van cirkel"
G2 X[#61] Y[#51] I[#63] F[#56]
G2 X[#59] Y[#51] I[#65] F[#56]
#60 = [#60 - #55]
endwhile


hier staat in normaal nederlands: "Zolang #60 Groter of gelijk is aan #64 ( je z-hoogte ) ga je het stukje tot ENDWHILE uitvoeren..
Vlak voor de Endwhile zien we dat er iets gebeurd met #60, daar wordt #55 van afgetrokken ( de dieptestap ), deze "lus" blijft actief tot niet meer aan de voorwaarde wordt voldaan, dus als #60 kleiner is dan #64

Het moge duidelijk zijn dat WHILE 't grote broertje is van IF, 't grote verschil is dat IF "Expliciet" controleert op een voorwaarde, en dat die voorwaarde de enige vereiste is voor het uitvoeren van de code tussen IF en ENDIF.

WHILE daarentegen is veel minder Star, je stelt een Grens aan, en zolang er niet voldaan is aan die grensvoorwaarde wordt de lus uitgevoerd tussen WHILE en ENDWHILE, daardoor is WHILE veelzijdiger, de voorwaarde beslaat een "bereik", en zolang de parameters binnen dit bereik vallen, wordt de functie uitgevoerd.

VOORWAARDEN: DEFINITIE

in de IF en WHILE-"lussen" moeten we een voorwaarde definiëren, dat doen we met dingen die we in de Wiskundeles op school al geleerd hebben, met FUNCTIES.

een Functie kan een vergelijking zijn of een ongelijkheid, bijvoorbeeld:
vergelijkingen:

#1=100
#2=#1x2

Ongelijkheden
#1<100
#2>= #1+4

dit zijn nog de eenvoudigere vormen, je kunt het zo gek maken als je wilt, maar dit zijn de basisvormen.

in een IF-lus kun je dus als voorwaarden stellen:
Code:
IF[#1=100]
GOSUB ZOOI
ENDIF


OF
Code:
IF[#1>=#2+3]
GOSUB ZOOI
ENDIF


En in een WHILE-lus geldt hetzelfde: dus
Code:
WHILE[#1=100]
GOSUB ZOOI
ENDWHILE


OF
Code:
WHILE[#1>=#2+3]
GOSUB ZOOI
ENDWHILE


Waarbij valt aan te tekenen dat een WHILE vaak met een ongelijkheid als voorwaarde wordt gebruikt, hiermee wordt echter niet gezegd dat een IF dan vaker met een Vergelijking wordt gebruikt.

bij het gebruik van WHILE wordt vaak naar een bepaalde situatie toegewerkt ( het in stapjes naar een eindpositie toewerken ), zoals in Eriks voorbeeld macro.

een IF met een Ongelijkheid als voorwaarde gebruik ik zelf bijvoorbeeld bij "FOUTCONTROLE" , stel je hebt een macro voor het frezen van een rond kamertje, maar je wilt vantevoren wel even "Controleren" of de frees die in de machine staat wel in't gaatje past.
#1 is de parameter voor de radius van het te frezen gat
#5009 is de actuele gereedschapsradius.
Code:
IF [#1<#5009]
ERRMSG"FREES IS TE GROOT VOOR HET GAT"
ENDIF


#5009 is een "Systeem parameter" bij een toolchange wordt deze waarde uit de tabel gelezen, je moet er dus wel voor zorgen dat je tabel klopt..

OPERATIONS:

Operations zijn de bouwstenen van onze vergelijkingen en ongelijkheden, ik heb tot nu toe eigenlijk alleen + en < > = gebruikt in mijn voorbeelden, maar er zijn er nog een paar..

[#1=#2+3] telt 3 op bij de waarde van #2, en wijst deze toe aan #1
[#1=#2-3] trekt 3af van de waarde van #2, en wijst deze toe aan #1
[#1=#2x3]vermenigvuldigt de waarde van #2 met 3, en wijst deze toe aan #1
[#1=#2/3] deelt de waarde van #2 door 3, en wijst deze toe aan #1

dit zijn de meest eenvoudige

[#1=[sqrt[#2]] geeft de vierkantswortel van #2, en wijst deze toe aan #1
[#1=[#2**3] verheft de waarde van #2 tot de derde macht, en wijst deze toe aan #1

en dan hebben we nog een handjevol Goniometrische trucs:

[#1=sin#2], geeft de sinus van #2 en wijst deze toe aan #1
[#1=cos#2], geeft de cosinus van #2 en wijst deze toe aan #1
[#1=tan#2], geeft de tangens van #2 en wijst deze toe aan #1

in de Manual van USBCNC staan nog meer voorbeelden.


NESTEN

je kunt SUBROUTINES ook "NESTEN", in elkaar verweven, als je een macro schrijft waar de machine in meerdere stappen moet werken, dan kun je de SUBROUTINES in "lagen" indelen.

Bijvoorbeeld: als je een macro maakt dat in laagjes een ronde kamer freest, en op elke laag wil je vanuit het midden in steeds grotere cirkels naar buiten frezen, dan kun je dat in meerdere SUBROUTINES indelen.

één subroutine die een WHILE bevat die controleert of de frees al op einddiepte is, en één die controleert of de frees al op zijn eindradius is.

ALGORITMEN

ZO!.. Gooit die Kabaalstra er even een Moeilijk woord door.. Algoritme..klinkt erg geleerd.. maar't stelt niet zo heel veel voor.. een algoritme is niet meer dan een reeks voorwaarden die bepalen hoe je macrootje zich dient te gedragen..

Gooi ik er meteen even een andere kreet door: PSEUDO CODE, pseudo code is niets anders dan programma code in "leesbare taal": je kunt in plaats van de parameters de betekenis van die parameters opschrijven, bijvoorbeeld:
Code:
WHILE [#1>=#2]
GOSUB FREZEN
ENDWHILE

Code:
WHILE [FREESDIEPTE GROTER OF GELIJK EINDDIEPTE]
GOSUB FREZEN
ENDWHILE


Zo kun je makkelijker een algoritme opstellen, het is makkelijker een algoritme vantevoren op papier uit te schrijven, dan botweg op je toetsenklavier te gaan zitten hameren.

voor bijvoorbeeld het Algoritme van een rondkamer zoals hierboven al beschreven kun je iets schrijven als:
Code:
WHILE[FREESDIEPTE GROTER OF GELIJK AAN EINDDIEPTE]
GOSUB LAAGJES UITFREZEN
ENDWHILE

SUB LAAGJES FREZEN
WHILE [WERKRADIUS KLEINER OF GELIJK AAN EINDRADIUS]
FREES RONDJE
VERGROOT WERKRADIUS
ENDWHILE
VERKLEIN FREESDIEPTE ( WE GAAN TENSLOTTE STEEDS LAGER)
ENDSUB


Dit is een basis algoritme, je kunt de boel verder verfijnen met foutcontroles, je kunt de diepte verrekenen om elke stap even groot te maken, er zijn plenty mogelijkheden.. de enige limiet is je eigen kunde en fantasie

Succes!

NB:
Hier is een ZIPJE te vinden met 2 XML Files:

http://www.cnczone.nl/download/file.php?id=514

Het installeren van deze bestanden:

start Notepad++
druk op F5 (of klik op "RUN" in de bovenste menubalk)
Type in:
Code:
%APPDATA%\Notepad++

en druk op Run

er wordt nu een mapje geopend met de Application Data van Notepad++

Pak het Zip bestand uit en plaats de 2 files naar deze map.
vervang eventueel de bestanden Stylers.XML en UserDefineLang.XM
als ze er al staan.

Zouden degenen die de XML's voor Notepad++ hebben gedownload hun bevindingen ook kenbaar willen maken?.. als er nog op-en aanmerkingen zijn, dan hoor ik dat graag, Bij voorkeur via PB naar Arie Kabaalstra








Valkuilen
welkom bij het 2de deel uit de educatieve reeks Het "Bouwen" van Macro's voor USBCNC.

de Valkuilen.. wat bedoel ik daarmee?.. welnu.. een Algoritme moet waterdicht zijn.. er moet geen speld tussen te krijgen zijn, anders ga je gekke dingen krijgen.. Voorbeeldje voor de eerste valkuil:

sub cirkel
DlgMsg "Voer gegevens in bovenkant werkstuk = Z0" Xhartcirkel 50 Yhartcirkel 51 Cirkelradius 52 Freesdiameter 53 Diepte 54 Zstap 55 Feed 56
msg "Beweeg naar veilige hoogte"
G17
G61
G01 Z1
msg "Beweeg naar hart cirkel"
G01 x[#50] Y[#51] F[#56]
DlgMsg "Coordinaten o.k.? Toets 0 of 1" Jaofnee 57
If [#57 == 0]
gosub cirkel
endif
msg "Beweeg naar indaalpunt"
#58 = [#53 / 2]
#59 = [#50 + #52 - #58]
#60 = [0 - #55]
#61 = [#50 - #52 + #58]
#62 = [0 - #61]
#63 = [0 - #52 + #58]
#64 = [0 - #54]
#65 = [#52 - #58]
while [#60 >= #64]
G01 X[#59] Y[#51] F[#56]
G01 Z[#60] F20
msg "Frezen van cirkel"
G2 X[#61] Y[#51] I[#63] F[#56]
G2 X[#59] Y[#51] I[#65] F[#56]
#60 = [#60 - #55]
endwhile
G01 Z1
G01 x[#50] Y[#51] F[#56]
gosub uit
endsub

sub uit
msg "Bewerkingen klaar"
M5
M2
endsub

Erik's Macrootje voor het frezen van ronde kamertjes, Niet om Eriks programmeerwerk ondersteboven te schoffelen, integendeel zelfs, maar dit voorbeeld geeft aan hoe makkelijk het is om een "Foutje" te maken...

Wat gaat hier mis dan?.. het volgende:
while [#60 >= #64]

we vullen in de dialoog voor de diepte in: 10 mm, en voor de diepte stap 3 mm... en nu komt het.. Het While statement stelt: zolang de einddiepte Groter of gelijk is, ga je verder.. dus.. we beginnen op 3 mm diep.. geen probleem.. 10 > 3 tenslotte.. 6mm?.. Nee.. ook prima want ook 10 > 6, dus naar 9 mm diep en ook hier.. 10 > 9.. volgende laag.. 12.. hee... wat nu want 10 > 12?.. dachetnie... dus dan stopt ie keurig.. de frees gaat omhoog.. en terug naar het midden.. maar... JUIST!!!.. het kamertje is MAAR 9 mm DIEP!!..

Hoe dit nu op te lossen?.. "Iesse siempel no?..".. heel simpel..

while [#60 >= #64]
ROEP HIER EEN SUBROUTINE AAN
endwhile

en dan?..
#60=#64
ROEP HIER NOG EEN KEER DE SUBROUTINE AAN

Zolang de waarde voor de Z-Waarde nog hoger ligt dan de eindwaarde, gaat ie dieper, en voert ie de routine uit, is ie gelijk, dan gaat ie naar zijn einddiepte en voert ie de routine uit.. , wordt ie "dieper", dan springt ie uit zijn routine, en daar staat dan.. Maak de waarden gelijk, en loop de routine nog een keertje af.. zo gaat ie in het voorbeeld dus IN de While loop naar 3,6 en 9 mm diep, dan wil ie naar 12 diep, dat past niet meer in de voorwaarde voor de While, dus maakt ie de parameter voor de diepte gelijk aan de ingegeven einddiepte, en voert em dan nogmaals uit..

de bewegingen die nu nog in de While-loop staan, moet je dus WEL even in een aparte Sub gooien.. dus je krijgt dan DIT:

sub cirkel
DlgMsg "Voer gegevens in bovenkant werkstuk = Z0" Xhartcirkel 50 Yhartcirkel 51 Cirkelradius 52 Freesdiameter 53 Diepte 54 Zstap 55 Feed 56
msg "Beweeg naar veilige hoogte"
G17
G61
G01 Z1
msg "Beweeg naar hart cirkel"
G01 x[#50] Y[#51] F[#56]
DlgMsg "Coordinaten o.k.? Toets 0 of 1" Jaofnee 57
If [#57 == 0]
gosub cirkel
endif
msg "Beweeg naar indaalpunt"
#58 = [#53 / 2]
#59 = [#50 + #52 - #58]
#60 = [0 - #55]
#61 = [#50 - #52 + #58]
#62 = [0 - #61]
#63 = [0 - #52 + #58]
#64 = [0 - #54]
#65 = [#52 - #58]
while [#60 >= #64]
goSub rondje
#60 = [#60 - #55]
endwhile
#60 = #64
GOSUB rondje
G01 Z1
G01 x[#50] Y[#51] F[#56]
gosub uit
endsub

sub rondje
G01 X[#59] Y[#51] F[#56]
G01 Z[#60] F20
msg "Frezen van cirkel"
G2 X[#61] Y[#51] I[#63] F[#56]
G2 X[#59] Y[#51] I[#65] F[#56]
endSub
sub uit
msg "Bewerkingen klaar"
M5
M2
endsub
Ik heb de veranderde delen een stukje uit laten steken.. de "While is gestript van alle bewegingen", die zitten nu in Sub Rondje, 't enige wat we in de While nog doen is de controle van de waarden, en het aanroepen van de Sub, waarna de waarde wordt "geactualiseerd".. als de While niet meer voldoet aan zijn voorwaarde, dan stapt ie eruit, en struikelt ie welhaast over de regel dat ie de diepte gelijk moet maken met de eindwaarde, en dan Sub Rondje NOG een keertje uitvoeren..

Nog een leuke.. in het dialoogje wordt gevraagd naar de diameter van het gereedschap en die wordt opgelsagen in #53.. en dan in de Code staat:
#58 = [#53 / 2]
zal ik je eens een geheimpje verklappen?.. in de Tooltabel staat toch ook de diameter van je gereedschap?.. dat wil zeggen.. als je de moeite neemt om dat in te vullen.. en dat moet je eigenlijk wel doen...

#5009 is de parameter waar de toolradius in staat van het actuele gereedschap.. dus.. overal waar #58 staat in Eriks Macrootje, kunnen we ook invullen #5009, en dan kunnen we #53 uit de dialoog halen, en gewoon vergeten.. de machine "Weet" al wat voor "Frees" ie in de kuip heeft..