Arduino - Communiceren met de PC
In dit project laten we de Arduino berichten sturen naar de PC en zorgen we ervoor dat we die berichten kunnen lezen.
Lessen:
- Introductie van het Serial object
- Gebruik van de Serial monitor
- Het programma resetten (= opnieuw laten starten)
Contents
Bits, bytes en bussen
Zoals je waarschijnlijk wel weet werkt een computer van binnen alleen met eentjes en nulletjes. Een "een" staat dan voor een signaal van 5 volt, en een nul staat voor een signaal van 0 Volt. Een signaal dat ofwel één ofwel nul is heet een bit. Acht van dergelijke bits vormen samen een byte. Bytes zijn dus groepjes van 8 bits. Een byte is genoeg om alle letters van het alfabet in op te slaan, zowel in hoofd- als in kleine letters, alle cijfers, en nog een heleboel extra tekens, zoals de spatie en andere leestekens, en bijzondere tekens zoals het dollar teken. Binnenin de computer worden gegevens overgestuurd over verbindingen die bus worden genoemd. Een bus is een verbinding tussen digitale elementen. Binnen een computer bestaan die vaak uit meerdere draadjes: voor elk bit een. Een moderne computer kan zelfs 64 bits tegelijk versturen als de bus bestaat uit 64 draadjes. Al die bits kunnen tegelijk worden verstuurd en ontvangen dankzij het feit dat die 64 draadjes allemaal parallel lopen. Dit heet paralelle communicatie. Het is erg snel maar heeft natuurlijk ook veel draadjes nodig.
Seriële communicatie
Verreweg de meeste communicatie, zeker over langere lijnen, verloopt serieel. In seriele communicatie worden de bits niet tegelijk, maar na elkaar verstuurd als een reeks enen en nullen. Via allerlei technische truukjes wordt ervoor gezorgd dat de bytes onderscheiden worden en wordt daarnaast continu gecontroleerd of de communicatie goed is verlopen. Mocht er een probleem zijn, dan wordt dat automatisch opgelost. We merken er niks van; hooguit zien we de communicatiesnelheid wat teruglopen. Glasvezel verbindingen zijn bijvoorbeeld vrijwel altijd serieel. Seriele communicatie lijkt misschien wat onhandig in vergelijking met paralelle communicatie, maar het kan toch behoorlijk snel verlopen. De USB bus, waarmee de Arduino aan de computer hangt, is ook een voorbeeld van een seriele communicatie. De letters USB betekenen Universal Serial Bus. Het is een veelgebruikte standaard.
Ook de Arduino UNO heeft een USB aansluiting. Om zonder al te veel kennis gebruik te kunnen maken van seriele communicatie over deze USB lijn hebben de mensen achter het Arduino project een object gedefinieerd waarmee seriele communicatie met de computer heel gemakkelijk wordt. Zo'n object is een stukje programma dat zich op een speciale manier laat gebruiken. Dit object heet Serial. De volgende functies zijn het belangrijkste:
- Serial.begin()
- Serial.print()
- Serial.println()
- Serial.read()
Meer, en ook meer gedetailleerde informatie kun je vinden bij Arduino Serial object.
De functie Serial.begin() moet aangeroepen worden om de seriele communicatie te starten. Dit gebeurt daarom bijna altijd in setup(), dan weet je zeker dat het is gedaan. Er is overigens ook een Serial.end() functie, maar die wordt zelden aangeroepen omdat vrijwel nooit nodig is om de communicatie te stoppen. Tussen de haakjes van de aanroep komt de snelheid van de communicatie. Je mag hier niet zomaar alles kiezen; die snelheid moet een van de volgende getallen zijn: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, of 115200. Het gaat hier om de baud-rate: het aantal bits per seconde. Hoewel de USB bus gemakkelijk sneller kan dan 115200 bits per seconde, moeten we ook rekening houden met de Arduino: dat is maar een klein dingetje met beperkte capaciteiten. Vandaar dat de maximale snelheid 115200 is. In de meeste programma's uit deze cursus kan de snelheid beperkt blijven en gebruiken we iets in de middenmoot: 9600 baud. Dit is een soort standaard; het is niet beter of slechter dan andere waarden, alleen langzamer of sneller. En 9600 is echt niet traag: er worden nog altijd gemakkelijk 1000 letters per seconde afgeleverd (elke letter bestaat uit 8 bits).
In tegenstelling tot wat je misschien denkt, stuurt Serial.print() dingen naar de computer, niet naar de printer. Als de Arduino "print" gaat dat dus zeker niet naar de printer (in elk geval niet zomaar). Tussen de haakjes bij een print() aanroep komt de variabele die moet worden verstuurd. Dat kan een tekst zijn, met quotjes omgeven, of een variabele. Soms geef je in de code nog een specifcatie van het format, bijvoorbeeld het aantal cijfers achter de komma voor een komma-getal.
De functie Serial.println() lijkt in alles erg op Serial.print(), maar voegt aan het eind een byte toe die betekent dat de regel ten einde is. Een volgende print() zal dan op een nieuwe regel beginnen.
De functie Serial.read() leest een letter die vanuit de PC naar de Arduino gestuurd moet worden. Bij de Serial.read() opdracht wacht het programma tot je via de Serial Monitor een letter hebt opgestuurd aan het programma. Als er niks komt, blijft de Arduino staan wachten en gebeurt er verder niks.
Er zijn ook andere opdrachten voor het Serial object. Zo kun je vragen of er wel een letter klaarstaat om te lezen. Als er niks klaar staat hoef je niet te lezen en kan je Arduino andere taakjes gaan uitvoeren. Ook kun je in een keer een reeks letters inlezen. Kijk voor meer informatie bij Arduino Serial object.
Waarom communiceren met de PC
Als een programma een keer in de Arduino zit, kan een Arduino prima zelfstandig werken. Dat wil zeggenm, als het programma correct is. Er zijn twee soorten fouten in de software. De eerste soort is zodanig dat het programma niet naar de Arduino geupload kan worden. Je krijgt een foutmelding in oranje letters. Of het nu gemakkelijk is of lastig, zo'n foutmelding geeft een hint van waar het probleem zit. De tweede soort fout is vaak een stuk lastiger om op te lossen: het programma is technisch correct en kan worden geupload naar de Arduino, maar de Arduino doet niet wat je had gehoopt en wellicht gedacht. Het is soms vrij lastig om de oorzaak van dit type fouten te ontdekken. In dergelijke gevallen kun je het programma opdracht geven om informatie naar de computer te sturen. Je maakt zo je eigen hints die kunnen helpen om de fout op te sporen.
Het programma uploaden
We hoeven dit keer niets te doen met andere onderdelen en/of het breadboard. Kopieer gewoon onderstaand programma en upload het naar de Arduino.
char val; // variabele val is een letter
int ledpin=13; // pin 13 heeft een LED (dit is standaard op het Arduino bordje)
void setup()
{
pinMode(ledpin,OUTPUT); // stel pin 13 in OUTPUT mode
Serial.begin(9600); // start de seriele communicatie met een baud rate van 9600
Serial.println("setup() voltooid. Ik wacht nu op 'R'"); // stuur een boodschap naar de gebruiker
}
void loop()
{
// lees een letter van de Seriele interface van de PC - gebruik de Serial Monitor hiervoor
val = Serial.read(); // deze procedure wacht net zo lang tot er een letter binnenkomt
// reageer op de letter R (hoofdletter gevoelig!)
if (val=='R')
{
digitalWrite(ledpin,HIGH); // zet de LED aan
delay(500); // wacht een halve seconde
Serial.println("R ontvangen!"); // stuur een boodschap naar de computer - te zien met de Serial Monitor
digitalWrite(ledpin,LOW); // zet de LED weer uit
}
}
Uitleg van de werking
Het programma heeft weer drie onderdelen. Eerst worden er variabelen gedefinieerd. Het gaat hier om een variabele val van het type char. Char betekent dat de variabele een letter (character in het Engels) kan bevatten. Daarna wordt de variabele ledpin gedefinieerd. Deze is van het type int en kan dus gehele getallen bevatten. Hij krijgt meteen een waarde mee: ledpin=13.
Het tweede deel bestaat uit de setup() functie. Eerst wordt daarin de pin van de LED als OUTPUT ingesteld. De Arduino kan de LED nu aan en uitzetten. Daarna komt de opdracht aan het Serial object om de communicatie te beginnen en wel met een baud rate van 9600. Als je de Serial Monitor wilt gebruiken, moet je daar de baud rate ook op 9600 instellen, anders krijg je gekke resultaten. De setup() stuurt ook nog een boodschap aan de PC en geeft aan klaar te zijn en te wachten op input.
Het derde deel is de loop() functie. Allereerst wacht de loop() op input van de PC via de Serial.read() functie. Pas nadat er een letter is ontvangen gaat het verder. De letter is opgeslagen in de variabele val. Het programma komt dan bij:
if (val=='R')
{
opdrachten
}
Hiermee test het programma of de letter die nu in val zit gelijk is aan de hoofdletter 'R'. Let op: hier staat een dubbele "==" en dat stelt een vraag voor: is het een gelijk aan het ander? Als die vraag met ja wordt beantwoord, worden de opdrachten die tussen de accolades staan uitgevoerd, anders niet en eindigt de loop. Zo'n if statement is een belangrijke structuur die je nog veel zult tegenkomen.
De Serial monitor
In het Tools menu van de Arduino software zit een item met de naam Serial monitor. Als je hier op klikt opent de Arduino software een nieuw scherm dat luistert naar de COM poort van de Arduino. Je kunt dit scherm ook openen met de toetscombinatie Crtl+shift+m. De Serial monitor wordt overigens alleen geopend als er ook echt een Arduino aan de USB poort hangt. In het scherm van de Serial monitor moet rechts onderin de juiste baud rate worden ingesteld. In ons geval is dat dus 9600 baud. Elke andere waarde geeft vreemde resultaten waaruit blijkt dat de tekens dan niet meer correct overkomen. Je mag het best eens proberen hoor.
Program reset
Het programma op de Arduino draait eenmalig setup() en blijft daarna continu de loop() functie herhalen. Soms, en vooral bij het testen van nieuwe programmaatjes, wil je dat het programma weer vanaf het begin begint. Daarvoor heeft het Arduino bordje een klein rood knopje. Misschien moet je er even naar zoeken, maar het is er echt. Als je erop drukt, wordt de Arduino opnieuw opgestart. In bovenstaand programma kun je dat zien doordat het in setup() een bericht stuurt aan de PC wat in de Serial Monitor is te zien. Druk er maar eens op, maar zorg ervoor dat de Serial Monitor open staat.
Beetje spelen
- Kun je het programma zo veranderen dat het zowel op een hoofdletter 'R' als op een kleine letter 'r' reageert?
- Kun je het programma zo aanpassen dat het LEDje kort aangaat bij de letter 'I' (en langer bij een 'R')?