Wanneer je het Arduino IDE start zie je reeds enkele coderegels. Om je programma succesvol te compileren moeten de setup() en loop() functie altijd aanwezig zijn, ook al zijn ze leeg. Als een van deze functies ontbreekt dan compileert je programma niet.
De setup-functie wordt opgeroepen wanneer het programma start. De functie zal maar 1 keer uitgevoerd worden nadat de microcontroller wordt opgestart of gereset.
Deze functie wordt gebruikt om:
Na de setup-functie wordt de loop gestart. Deze wordt telkens opnieuw uitgevoerd wanneer de laatste regel code is uitgevoerd. De setupfunctie wordt hierbij niet opnieuw doorlopen.
Deze functie bezit het eigenlijke programma.
void setup(){ //Hier initialiseren we de variabelen //stellen we pinnen in //en starten we bibliotheken //Deze functie wordt maar 1 keer uitgevoerd } void loop(){ //Deze functie bevat je programma //Deze zal telkens opnieuw uitgevoerd worden } |
Elk arduino programma moet een minimale hoeveelheid code bevatten om gecompileerd te kunnen worden. De setup() en loop() functies moeten altijd aanwezig zijn.
Benodigdheden:
Alternatief kan je de ingebouwde led op je Arduino gebruiken die is aangesloten op pin 13.
Het programma bestaat uit 2 delen. In de eerste plaats gebruiken we een digitale pin als uitgang. Dit zullen we in de setup moeten instellen. Het 2e deel van het programma verzorgt het knippergedrag.
Om het ons gemakkelijker te maken slaan we de pin met de led op als een globale variabele door de volgende regel code bovenaan het programma te plaatsen. Als we dan ergens in onze code ledPin schrijven dan leest onze arduino dat als het getal 13.
int ledPin = 13; //Globale variabele die de pinnummer bijhoudt
Om aan te geven of een pin data leest of uitstuurt moet de pin in de setup geconfigureerd worden. Om de pin als uitgang in te stellen wordt volgende regel toegevoegd in de setup-functie.
pinMode(ledPin,OUTPUT); //Stelt een bepaalde pin in als uitgangspin
Nu zijn we bij het eigenlijke programma aanbeland waar we het gedrag van de led in programmeren, de loop-functie. De werking van deze code kunnen we beschrijven met een blokdiagram.
Om een pin die gedefinieerd is als uitgang LOW of HIGH te zetten kan men gebruik maken van de volgende functies:
digitalWrite(ledPin,HIGH); //Om een hoge waarde op de pin te zetten
digitalWrite(ledPin,LOW); //Om een lage waarde op de pin te zetten
Indien we enkel deze 2 functies zouden toevoegen dan zou de led zeer snel aan en uit schakelen. Hierdoor ziet men de led niet aan en uit schakelen maar lijkt het alsof de led maar half zo sterk brandt dan de bedoeling is. Dit lossen we op door een vertraging in te bouwen met volgende functie:
delay(1000); //Wachttijd van een bepaald aantal milliseconden
Voeg deze functie aan je programma toe zodat je volgend resultaat krijgt:
digitalWrite(ledPin,HIGH); //Om een hoge waarde op de pin te zetten
delay(1000); //Wachttijd van een bepaald aantal milliseconden
digitalWrite(ledPin,LOW); //Om een lage waarde op de pin te zetten
delay(1000); //Wachttijd van een bepaald aantal milliseconden
Nu kan je het programma compileren en uploaden.
Je kan de timing van het knipperen veranderen door een ander getal in te geven in de delay-functie. Om meer controle te krijgen over deze vertraging is het interessant om een extra globale variabele toe te voegen bovenaan je programma.
int vertraging = 1000; //Globale variabele die de vertraging bijhoudt
Je delay-functies kan je dan vervangen door:
delay(vertraging);
Indien je nu een andere waarde aan de variabele “vertraging” geeft dan verandert deze in je hele programma.
De digitale pin 13 op je Arduino bord bevat reeds een interne led met weerstand. Deze led kan je op je Arduino zien knipperen synchroon met je bijgeplaatste led. Dit is handig als je geen led op voorraad hebt of snel wil werken. Als je alleen met de interne led wil werken dan kan je de externe gewoon verwijderen.
int ledPin = 13;
int vertraging = 1000;
void setup(){
pinMode(ledPin,OUTPUT);
}
void loop(){
digitalWrite(ledPin,HIGH);
delay(vertraging);
digitalWrite(ledPin,LOW);
delay(vertraging);
}
Benodigdheden:
In vorige oefening werd aangehaald dat het toch wel heel gemakkelijk is als we op voorhand onze pinnen een naam geven. In dit geval hebben we naast een ledPin ook een knopPin. Deze geven we voor de duidelijkheid ook die naam.
Bovenaan je programma schrijf je dus:
int knopPin = 2;
int ledPin = 13;
De uitgangspin configureren we zoals in oef1. Met de gebruikte pinMode-functie kunnen we pinnen ook als ingang configureren door als 2e parameter het woord INPUT te gebruiken.
pinMode(knopPin,INPUT);
pinMode(ledPin,OUTPUT);
Wanneer we een digitale pin inlezen krijgen we een waarde terug die overeen komt met de lading op die pin. Deze waarde zullen we weer opslaan in een variabele. In tegenstelling tot de globale variabelen (bovenaan de code) gebruiken we hier een lokale variabele. Deze variabele bestaat enkel tussen de 2 accolades {} waarin hij is aangemaakt. Door gebruik te maken van zo een lokale variabele zal het programma minder geheugen gebruiken.
De lading meten we met de volgende functie:
int waarde = digitalRead(knopPin);
Hierbij slaan we de waarde van de pin op als een variabele waarde met een getal 0 of 1.
Hierna zullen we iets met die waarde doen zoals bv een led laten aangaan. Weet je nog met welke functie we een led aan of uitzetten?
digitalWrite(ledpin,waarde);
int ledPin = 13;
int knopPin = 2;
void setup(){
pinMode(ledPin,OUTPUT);
pinMode(knopPin,INPUT);
}
void loop(){
int waarde = digitalRead(knopPin);
digitalWrite(ledPin,waarde);
}
De meeste onder jullie zullen nu het idee hebben van “Nou, dat is leuk. Ik kan een led aan zetten maar daar heb ik toch geen microcontroller voor nodig.” Dat is volledig correct!
Bij microcontrollers bekijken we het aanzetten van de led en het inlezen van de knop als 2 aparte gebeurtenissen. Je zou namelijk terwijl je de led aanzet ook een geluidssignaal kunnen laten afgaan of een bericht naar een computer sturen dat je collega vertelt dat je de led hebt aangezet. Je hebt dus meer mogelijkheden!
Het verschil met de vorige oefening is dat je weerstand nu een pull-up weerstand is in plaats van pull down. Let op, want de aansluitingen zijn dus anders dan bij oefening 3.
Voor het opstellen van de code kan je vertrekken van oef3. Door deze aan te passen wordt het verschil duidelijk tussen de logica van een pull-up (positieve logica) en pull-down (negatieve logica) weerstand.
Voeg bovenaan je programma 2 globale variabelen toe om de pinnen van de knop en de led op te slaan. Configureer de pinnen dan in je setup zoals je in oef 2 en oef 3 gedaan hebt.
In de loop slaan we de waarde van de knop op in een lokale variabele. Nu willen we een handeling verrichten die afhangt van de waarde van de knop. We willen dus een beslissing maken die afhangt van de een waarde. Om zulke beslissingen te nemen kan je in je code gebruikt maken van een if-statement.
If-statements laten toe om een booleaanse vergelijking te evalueren en een bepaalde actie te ondernemen. Booleaanse vergelijkingen zijn eigenlijk JA/NEE-vragen. Dit maakt het mogelijk om een bepaalde handeling te doen indien al dan niet aan een voorwaarde voldaan is. De schrijfwijze van deze statement is:
if(voorwaarde){
//doe iets indien “voorwaarde”==TRUE
}
Probeer deze statement zelf te implementeren in je code om een led aan te zetten. Als voorwaarde kan je kijken of de opgeslagen waarde van je knop HIGH of LOW is.
Wat valt je hierbij op?
Wat je sowieso zou moeten opgevallen zijn is dat de led aangaat als je niet op de knop drukt. Een pull-up weerstand werkt namelijk met negatieve logica. Dat wil zeggen dat je een 1 krijgt als je niet op de knop drukt en een 0 als je wel drukt. Het werkt dus omgekeerd dan je gewoon bent met de pull-down weerstand.
Indien je programma werkt en correct is opgesteld dan gaat je led wel aan maar kan je hem niet uitzetten. Dit is omdat er geen code aanwezig is die de led terug uit zet. Door aan je statement een alternatieve optie toe te voegen (dus als niet aan de voorwaarde voldaan is) met een if/else-functie kan je de led uitzetten. De schrijfwijze wordt dan:
if(voorwaarde){
//doe iets indien “voorwaarde”==true
} else{
//de iets indien “voorwaarde”==false
}
Indien je code nu werkt dan kunnen we het nut van de schakeling met de pull-up weerstand bespreken. De ATMEGA microcontroller die op het Arduino bord aanwezig is bezit namelijk interne pull-up weerstanden. Deze weerstanden kunnen geactiveerd worden in de setup-functie met pinMode:
pinMode(pinNr, INPUT_PULLUP);
Wanneer de interne weerstand op deze manier geactiveerd is dan kan de externe weerstand verwijderd worden. Dit maakt de schakeling nog simpeler, de drukknop is nu aangesloten tussen de aarding en de digitale pin. Het resulterende circuit ziet er dan als volgt uit:
int ledPin = 13;
int knopPin = 2;
void setup(){
pinMode(ledPin,OUTPUT);
pinMode(knopPin,INPUT_PULLUP);
}
void loop(){
int knopWaarde = digitalRead(knopPin);
if(knopWaarde == 0){
digitalWrite(ledPin,HIGH);
}
else{
digitalWrite(ledPin,LOW);
}
}
PWM staat voor pulse breedte modulatie (Pulse Width Modulation). Dit is een periodiek digitaal signaal dat in het geval van Arduino een frequentie van 500Hz heeft. De verhouding tussen de tijd die het signaal hoog is en laag is noemen we de Duty Cycle. Door deze te veranderen kan een analoog signaal gesimuleerd worden.
De Arduino bevat maar een aantal pinnen waarop hij een PWM signaal kan sturen. Deze zijn op de Arduino UNO aangeduid met een tilde (~). Op de Arduino Nano zijn ze aangeduid met een witte rand rond de pin maar die is vaak moeilijk zichtbaar. Daarom worden de PWM-pinnen hieronder nog even opgesomd. Let op, PWM is een digitaal signaal en vindt je dus tussen de digitale pinnen.
PWM pinnen: 3, 5, 6, 9, 10, 11
Dit kan variëren van bord tot bord dus kijk dit zeker na op http://www.Arduino.cc
Maak een globale variabele aan waarin je de ledPin opslaat.
Om de led te dimmen moeten we 3 extra globale variabelen aanmaken, de intensiteit, de stijgWaarde en de vertraging. Voeg deze bovenaan bij in je code.
De intensiteit houdt bij hoe hard je led moet branden. De stijgWaarde bepaalt hoeveel de intensiteit verandert bij het doorlopen van de loop. De vertraging stelt de duur van de delay in.
In de setup-functie moet je een digitale pin instellen als uitgangspin. Dit hebben we in de vorige oefeningen behandeld. Voor herhaling verwijzen we naar Oefening 2.
Met de analogWrite functie is het mogelijk om een PWM signaal naar een bepaalde pin te schrijven die als uitgang geconfigureerd is. De waarde van dit PWM signaal is een getal tussen 0 en 255, dus 256 waarden. Dit aantal komt voort uit de 8bit resolutie van het PWM signaal maar daar gaan we tijdens de theorie zitting dieper op is. De functie wordt als volgt gebruikt:
analogWrite(int,waarde);
Om de intensiteit te veranderen kunnen we de stijgWaarde erbij optellen of aftrekken. In dit geval opteren we om enkel op te tellen.
intensiteit = intensiteit + stijgWaarde;
We hebben net vermeld dat de PWM waarde enkel een getal tussen 0 en 255 mag bevatten. Dit kunnen we controleren met een if-statement. Door als voorwaarde te stellen dat de intensiteit<=0 OF intensiteit>=255 moet zijn, kunnen we hiervoor een gepaste beslissing nemen.
if(intensiteit>=255 || intensiteit <=0){
//Doe iets als de intensiteit buiten de grenzen valt
}
De stijgWaarde kan dan positief of negatief gemaakt worden met:
stijgWaarde = !stijgWaarde;
Gebruik een delay om het dimmen zichtbaar te maken.
delay(50);
//bijhouden van de ledPin
int ledPin = 9;
//bijhouden van de intensiteit van de led
int intensiteit = 0;
//bijhouden hoeveel de intensiteit verandert per cyclus
int stijgWaarde = 5;
//vertraging die de snelheid van het dimmen bepaalt
int vertraging = 100;
void setup(){
pinMode(ledPin,OUTPUT);
}
void loop(){
//if-statement
//indien de intensiteit buiten de grenzen valt dan wordt de stijgWaarde geïnverteerd.
//optellen wordt dan aftrekken en omgekeerd
if(intensiteit>=255 || intensiteit <=0){
stijgWaarde = -stijgWaarde;
}
//tel de stijgWaarde bij de intensiteit op
intensiteit = intensiteit + stijgWaarde;
//Schrijf de waarde naar de led
analogWrite(ledPin,intensiteit);
//ingebouwde vertraging
delay(vertraging);
}
Een potentiometer is een regelbare weerstand. Deze wordt met de buitenste aansluitingen met de Spanning en GND verbonden. Door de draaiknop te bewegen zal de wiper over de resistieve strip bewegen waardoor de spanning op de middelste pin zal veranderen.
Deze component kan worden voorgesteld als een spanningsdeler.
De buitenste contacten van de potentiometer worden aan de voedingsspanning (5V) en de GND aangesloten. De middelste pin geeft dan een spanning afhankelijk van zijn stand. Deze zal altijd tussen de voedingsspanning en de GND liggen.
Maak een globale variabele aan die de pin bijhoudt waar de potentiometer op aangesloten is.
Om data naar de computer te kunnen sturen maken we gebruik van de seriële poort. Deze poort stuurt informatie bit per bit door, vandaar de benaming serieel. Voor we deze poort kunnen gebruiken moeten we deze in de loop starten met de functie:
Serial.begin(BAUDRATE);
Het baudrate is de snelheid waarmee de poort data verstuurd en is uitgedrukt in het aantal bits per seconde. Als standaardwaarde kan je hiervoor een snelheid van 9600 gebruiken.
De analoge pin hoeft niet als ingang te worden geconfigureerd. Analoge pinnen worden in Arduino standaard als ingang gebruikt.
De waarde van de analoge spanning zal opgeslagen worden in een variabele. Hiervoor maken we een lokale variabele aan. Deze bestaat enkel tussen de 2 haakjes {} waartussen hij is aangemaakt. Hierbuiten bestaat deze variabele niet! Maak een lokale variabele aan met de volgende regel:
int potWaarde;
De ATMEGA is een digitale component. Om een analoge waarde in te lezen zal deze dus eerst naar een digitaal equivalent moeten geconverteerd worden. De ATMEGA heeft hiervoor 10 bit analoog naar digitaal convertors (ADC) ingebouwd. Een 10 bit waarde kan getallen bevatten van 0 tot en met 1023. Deze waarde slaan we op in de lokale variabele. Om de analoge spanning in te lezen maken we gebruik van de functie:
potWaarde = analogRead(int);
Nu de spanning van de middelste pin van de potentiometer gekend is kunnen we hem uitsturen via de seriële poort. Om aan te geven welke data dat we gaan afbeelden schrijven we een regel tekst naar de seriële poort. Gebruik van Serial.print() begint geen nieuwe regel indien de tekst is afgedrukt. Doe dit met de volgende functie:
Serial.print(“De gemeten waarde is: ”);
Nu we duidelijk gezegd hebben aan de gebruiker (in dit geval onszelf) welke info we afdrukken, voegen we nu de data er bij. Door gebruik te maken van Serial.println() zal de tekst die we volgende keer willen afdrukken steeds beginnen op een nieuwe regel. Gebruik deze functie zo:
Serial.println(“potWaarde”);
//Bijhouden van de aansluiting van de potentiometer
int potentioMeter = A0;
void setup(){
//starten van de serïele poort
Serial.begin(9600)
}
void loop(){
//aanmaken van een lokale variabele
int potWaarde;
//inlezen van de potentiometer
potWaarde = analogRead(potentioMeter);
//tekst schrijven naar de seriële poort
Serial.print(de gemeten ADC waarde is: );
//Waarde schrijven naar de Seriële poort
Serial.println(potWaarde);
}
Deze oefening kan je ook terugvinden op de Arduino-website via deze link.