#define is een macro. Tijdens het compileer proces wordt iedere keer als het woord redPin wordt tegen gekomen dit vervangen door 12. Dat is het in simpele termen; als je een uitgebreidere uitleg wilt moet je het maar laten weten.
int redPin creeert een variabele genaamd redPin.
Nu veranderen pin nummers meestal niet dus is het beter ze constant te maken; const int redPin = 12;. De compiler kan je dan waarschuwen als je per ongeluk probeert deze in je programma te veranderen. Verder is er geen Arduino met meer dan 256 pinnen en om die reden kun je beter een byte gebruiken voor het type van de variable; const byte redPin = 12;. Op systemen met beperkt geheugen moet je ieder dubbeltje omdraaien
Het gebruik van #define voor constanten wordt in het algemeen afgeraden omdat de compiler bepaalde checks niet kan uitvoeren; ik kan zo niet op een voorbeeld geven.
Uiteraard zijn er zaken die erfenissen van vroeger zijn en / of die in onbruik zijn geraakt.
Maar #define heeft wel degelijk zijn eigen nut.
Zo kun je bijvoorbeeld ook een Nederlands woord gebruiken in plaats van het bestaande Engelse woord, bijvoorbeeld Aan in plaats van HIGH.
Het is weer een ander ding of dat slim is (ik vind van niet), maar het kan.
De Arduino IDE heeft ook wat van die defines vast ingebouwd, zoals HIGH en LOW.
Je kunt er dus wel wat mee, bijvoorbeeld een overzichtelijker code creƫren, maar persoonlijk vind ik dat je dan beter kunt leren om te gaan met wat de IDE beschikbaar voor je heeft.
Hangt ervan af; soms is het juist heel handig. Een define hoeft niet per se een getalswaarde te zijn; in feite kun je elke tekenreeks vervangen door iets anders met een 'define'.
Zie bv. deze toepassing:
#define DEBUG
#ifdef DEBUG
#define deb(x) Serial.print(x)
#else
#define deb(x)
#endif
void setup () {
//Hier gebeurt van alles
deb("setup klaar");
}
void loop () {
//Allerlei spannende dingen, misschien iets met een variabele 'x'
//waarvan je tijdens testen wilt weten welke waarde die aanneemt
deb("x = ");
deb(x);
}
In bovenstaande voorbeeld wordt "deb" vervangen door "Serial.print", maar alleen als "DEBUG" ook is 'ge-#defined'. Zo niet, dan wordt "deb" door de compiler vervangen door niets - m.a.w., het wordt gewoon genegeerd.
Wat is het nut hiervan? Door alleen die ene regel '#define DEBUG' te verwijderen (door bv. // ervoor te zetten), kun je de debug-print's in het hele programma aan- of uitzetten, zonder dat je de hele code hoeft door te akkeren en handmatig alle Serial.print's uit te commenten.
En zo zijn er meer mogelijkheden; soms zie je het ook wel eens gebruikt worden om compatibiliteit tussen verschillende versies van software te garanderen; als bv. een functie een andere naam heeft gekregen in een latere versie, maar je wilt dat de oude naam ook blijft werken.
Laat niet onverlet dat #define niet zaligmakend is. Zoals @sterretje aangaf, is bv een "static const byte" soms efficiƫnter dan een #define - en in elk geval weet je bij een "const byte/uint8_t/uint16_t/enz." zeker met welk datatype je aan het werken bent, doordat je specificiteit forceert.
Hier zijn wat andere zinvolle macros die ik vaak gebruik.
1 Gelezen waarde van een knop. Over het algemeen dien je een knop aan te sluiten tussen pin en GND voorbeelden zijn vaak anders). Als de knop is ingedrukt zul je een waarde LOW krijgen, anders HIGH.
#define ISPRESSED LOW
...
...
// als de knop is ingedrukt
if(digitalRead(somePin) == ISPRESSED)
{
...
...
}
2 Aantal elementen in een array van enig type
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
float fArray[] = {2.71, 3.14};
char cArray[] = {'H', 'a', 'l', 'l', 'o'};
...
...
Serial.prin(F("Aantal bytes gebruikt door fArray: "));
Serial.println(sizeof(fArray));
Serial.prin(F("Aantal elementen in fArray: "));
Serial.println(NUMELEMENTS(fArray));
Serial.prin(F("Aantal bytes gebruikt door cArray: "));
Serial.println(sizeof(cArray));
Serial.prin(F("Aantal elementen in cArray: "));
Serial.println(NUMELEMENTS(cArray));
Niet getest maar je zou het idee moeten krijgen. Het werkt op enig type array (char, byte, int, float, struct, class, ...).
In alle eerlijkheid, ik heb ooit 2 boeken over programmeren open gehad en 1 cursus. 1 boek was over assembler toen ik een jaar of 15 was. Nooit helemaal uitgelezen; wel dingen geprobeerd en dat ging best OK. Het tweede boek hoorde bij de cursus en dat was op de universiteit; Java. Dat was nuttig, maar eigenlijk vooral/alleen omdat het uiteindelijk meer ging over object-georienteerd denken/ontwerpen dan over programmeren als zodanig. Er zijn zat websites, tutorials enz. te vinden over die thematiek.
De rest van het programmeren is net als rekenen/wiskunde: je leert het alleen door het te doen.
Zeker; gelukkig staat GitHub bomvol met voorbeelden, in uiteenlopende mate van elegantie. Als je je de basis eigen weet te maken met een paar tutorials en wat uitproberen, dan lukt het steeds beter om te leren van andere voorbeelden. Wat je niet begrijpt, zoek je op; vooral C++ is enorm goed gedocumenteerd op allerlei plekken.
Niks mis met een goede cursus, uiteraard, maar ook zonder kom je een heel eind.
Wees je ervan bewust dat dit voor PCs is en een aantal zaken niet "bestaan" in de Arduino wereld.
printf() of cout moet je vervangen door Serial.print en Serial.print() heeft beperking ten opzichte van printf().
Hoewel de main() functie wel bestaat in de Arduino wereld is deze voor je verborgen. Wat je voor nu moet weten is dat de main() functie setup() eenmalig aanroept en dat loop() vanuit een for-loop in main() continue wordt aangeroepen.
Er worden geen Arduino specifieke zaken behandeld (digitalRead etc).
Nu de links over en weer vliegen, nog een link die ik wel eens wil gebruiken om even snel te spieken:
De Arduino reference page, die helpt je verder met de IDE en wat je daar mee kunt doen en is daarmee specifiek op Arduino gericht.
Ik vind 'm bruikbaar.