Misschien leuk als in in hapklare brokjes vanaf 0 begin?
De functies setup() en loop()
Een lege sketch (want zo heet zo'n Arduino programmaatje) ziet er zó uit:
C:
1
2
3
4
5
6
7
| void setup()
{
}
void loop()
{
} |
setup wordt maar één keer aangeroepen door de Arduino,
loop wordt daarentegen elke keer aangeroepen. Achter de schermen zit namelijk de standaard
main functie van C:
C:
1
2
3
4
5
6
7
8
| void main()
{
setup();
for(;;)
{
loop();
}
} |
Ik denk dat de heren ontwerpers dit gedaan hebben zodat ze het
for statement niet gelijk uit te hoeven leggen. Hoe dan ook, het is belangrijk om te weten dat er 2 functies zijn, en dat wanneer de
loop functie is afgelopen, hij direct weer overnieuw begint.
variabelen en scope
Ik houd het voor de introductie even bij een type variabele die alleen getallen kan bevatten: de
int. De int kan op een 16-bit processor een getal bevatten van in ieder geval -32767 tot 32768 (ongeveer). Dit is voor de meeste doeleinden voldoende. (*disclaimer: dit kan verschillen op systemen, maar voor dit doel goed genoeg)
In C kun je variabelen niet gewoon gebruiken, je zult ze moeten declareren:
Hiermee geeft je aan dat je een ding hebt gemaakt dat 'teller' heet en dat hij een getal kan bevatten. Meestal geven we zo'n ding gelijk een waarde.
Binnen de
loop kunnen we de teller mooi gebruiken:
C:
1
2
3
4
5
6
7
8
9
10
| void loop()
{
int teller;
teller = teller + 1;
if(teller > 100)
{
//doe iets met lampjes of zo.
}
} |
Helaas, waarom werkt dit niet? Dit werkt niet, omdat de teller BINNEN de loop functie is gedefinieerd. Wanneer de IF is uitgevoerd (en het einde van loop() is bereikt) begint de functie opnieuw en wordt OPNIEUW een 'teller' gedefinieerd. Deze begint vrolijk vanuit zijn startwaarde 0.
Er zijn meerdere manieren om dit op te lossen:
- door de teller BUITEN de functie te definiëren, of
- door de variabele static te maken.
Als je hem buiten een functie definieert, blijft hij zijn waarde behouden en kan de variabele in iedere functie gebruikt worden. Dit noemen we een
globale variabele. De andere manier,
static, heeft als voordeel dat de 'teller' alleen te gebruiken is binnen de functie waar je hem definieert (is meestal iets netter).
haakjes eehm accolades 'curly braces'
Binnen C, C++, Java, C# en alle varianten worden opdrachten gegroepeerd met behulp van braces:
C:
1
2
3
4
5
6
7
8
9
10
11
12
| void loop()
{
if(....)
{
//doe dit
//doe dat
}
else
{
//doe wat anders
}
} |
Zorg er altijd voor dat je braces netjes gebalanceerd zijn (dus voor elke haak-open ook een haak-sluiten), en spring je code in bij elke haak-open. De compiler interesseert het geen reet maar wij mensen vinden dit bijzonder prettig. Het maakt overigens niet uit of je een haakje-open op dezelfde regel of op een nieuwe regel plaatst. Dit is een kwestie van voorkeur en conventie (wees wel altijd consequent dat scheelt fouten).
Tweede tip: hoewel voor een groep met één statement de haakjes overbodig zijn, adviseer ik je ze toch te gebruiken om potentiele bugs te vermijden:
C:
1
2
3
4
5
6
7
8
9
10
| //niet zo:
if(teller > 100)
start_de_motor();
...
//maar zo:
if(teller > 100)
{
start_de_motor();
} |
Het risico is namelijk dat je een 2e ding wilt doen naast het starten van de motor en dan krijg je deze situatie:
C:
1
2
3
4
| //niet zo:
if(teller > 100)
start_de_motor();
bak_een_taart(); |
In bovenstaand geval bak je namelijk ALTIJD een taart, onafhankelijk van de if. De
if eindig namelijk na het starten van de motor omdat er geen braces omheen staan.
Nog een instinker:
variabelen vergelijk je met ==, variabelen geef je een waarde met =
C:
1
2
3
4
5
6
| //fout fout fout
if(x = 4)
{
}
// x heeft nu altijd de waarde 4. |
Ik sluit deze tutorial af met een laatste instinker:
Achter if, while, for hoort géén punt-komma
C:
1
2
3
4
5
6
| //fout fout fout
if(teller > 100); // hier hoort geen puntcomma
{
bak_een_pizza();
}
//fout fout fout |
De uitleg? Een punt-comma zonder code is een soort NULL-statement en sluit daarmee het if-statement af. Ik noem deze expliciet omdat beginner heel vaak zitten de puzzelen waarom hun sketch niet werkt. Als je deze 2 instinkers (genoemd 'ongewenste assignatie' en 'empty statement') snel herkent scheelt dat een hoop tijd.
Succes!