Normaal wordt elk Arduino-bord geprogrammeerd via de seriële interface.
Maar niet alleen de programmacode kan worden overgebracht naar de Arduino. Er kunnen ook besturingscommando's naar de Arduino worden gestuurd of waarden van de Arduino worden ontvangen.
In het volgende artikel beschrijf ik hoe je dit kunt doen en welke opties je hebt.
Veiligheidsinstructies
Ik weet dat de volgende opmerkingen altijd een beetje vervelend zijn en onnodig lijken. Helaas hebben veel mensen die "beter" wisten door onvoorzichtigheid ogen, vingers of andere dingen verloren of zichzelf verwond. Gegevensverlies is in vergelijking bijna te verwaarlozen, maar zelfs dit kan erg vervelend zijn. Neem daarom vijf minuten de tijd om de veiligheidsinstructies te lezen. Omdat zelfs het coolste project geen blessure of andere problemen waard is.
https://www.nerdiy.de/sicherheitshinweise/
Affiliate links / reclame links
De hier vermelde links naar online winkels zijn zogenaamde affiliate-links. Als u op zo'n affiliate-link klikt en via deze link een aankoop doet, ontvangt Nerdiy.de een commissie van de betreffende onlineshop of aanbieder. De prijs verandert voor jou niet. Als u via deze links uw aankopen doet, steunt u Nerdiy.de om in de toekomst andere nuttige projecten aan te kunnen bieden. 🙂
Bereid seriële interface voor
Om de seriële interface in uw programma te gebruiken, moet u deze initialiseren.
Dit wordt gedaan door de functie in de functie “setup()” te gebruiken
Serieel.begin(115200);
oproepen. Het getal “115200” staat voor de baudrate – d.w.z. de snelheid – waarmee de symbolen (geen bits of bytes) via de seriële interface worden verzonden. Deze snelheid dient u afhankelijk te maken van de “kwaliteit” van de verbindingslijn.
Als je bijvoorbeeld een afgeschermde en erg korte kabel hebt, kan de snelheid erg hoog worden ingesteld.
Voor onafgeschermde en/of erg lange kabels moet deze snelheid niet zo hoog worden ingesteld.
Gangbare baudrates zijn bijvoorbeeld de volgende waarden:
50 110 150 300 1200 2400 4800 9600 19200 38400 57600 115200 230400 460800 500000
Welke snelheid u ook instelt, deze waarde moet ook worden ingesteld in de “seriële monitor” – d.w.z. de andere communicatiepartner voor seriële communicatie. Alleen dan worden de karakters correct ontvangen en verzonden. Meer hierover leest u in de loop van de tekst.
Als je niet zeker weet welke baudrate je moet gebruiken, raad ik waarden aan tussen 9600 baud en 115200 baud. Deze en de tussenliggende waarden zijn ook de gebruikelijke waarden voor veel eindproducten zoals sensoren en actuatoren.
Stuur gegevens van het Arduino-bord naar de aangesloten computer
Om gegevens van je Arduino-bord naar de aangesloten computer te sturen, moet je de volgende functie oproepen.
Hierdoor wordt de tekst "Hallo wereld!" inclusief regeleinden naar de computer.
Serial.println ("Hallo wereld!");
Als voorbeeld kun je de volgende code proberen.
ongeldige setup() { Serial.begin(115200); } void loop() { Serial.println("Hallo wereld!"); vertraging(1000); }
In de volgende combinatie verzendt de functie de tekst “Hallo wereld!” naar de computer zonder regeleinden.
Serial.print ("Hallo wereld!");
Hier is nog een voorbeeld van.
ongeldige setup() { Serial.begin(115200); } void loop() { Serial.print("Hallo wereld!"); vertraging(1000); }
Als je variabele waarden wilt versturen – in dit geval de waarde van de variabele ‘funny_variable’ – kun je dit als volgt doen:
uint8_t grappige_variabele=5; Serial.println(String(grappige_variabele));
Als voorbeeld ziet het geheel er weer zo uit.
ongeldige setup() { Serial.begin(115200); } lege lus() { uint8_t grappige_variabele=5; Serial.println(String(grappige_variabele)); vertraging(1000); }
Een regeleinde verzenden betekent dat er naast de eigenlijke berichtinhoud ook een controleteken wordt verzonden dat de ontvanger het signaal geeft om naar de volgende regel te gaan.
Gebruik een seriële monitor
De seriële monitor is de tegenhanger van het Arduino-bord. Het is het programma dat de gegevens van de computer ontvangt en voor jou leesbaar maakt.
Je vindt het als onderdeel van de Arduino IDE onder het menu-item “Tools/Serial Monitor”. Hulpmiddelen zoals deze “Seriële Monitor” worden ook wel terminalprogramma’s genoemd. Het programma is ook een goed alternatief voor de “Serial Monitor” van de Arduino IDE HTERM.
De baudrate kan worden ingesteld in het venster van de seriële monitor. Hier moet je dezelfde waarde instellen die je eerder in de programmacode hebt ingesteld.
Hebben jullie met het commando
Serieel.begin(115200);
Als u een baudrate van 115200 baud hebt ingesteld, moet u ook een baudrate van 115200 baud instellen in de seriële monitor.
Naast de baudrate kun je ook het line termination karakter instellen. Je hebt deze instelling alleen nodig als je gegevens van de computer naar de Arduino wilt sturen.
Hier kun je het teken instellen dat automatisch wordt toegevoegd en verzonden telkens wanneer een waarde wordt verzonden.
Je kunt dit heel goed gebruiken in je code, bijvoorbeeld om op de Arduino te herkennen of de verzending van een commando of waarde is voltooid.
Dit wordt gedetailleerd uitgelegd in de sectie “Commando’s en parameters naar de Arduino verzenden”.
Gebruik seriële plotter
De seriële plotter is een hulpmiddel waarmee je numerieke waarden (bijvoorbeeld meetwaarden) rechtstreeks op de computer kunt weergeven als een chronologische volgorde. Hiervoor moet je de Arduino zo programmeren dat hij de numerieke waarden naar de computer stuurt.
Dit kan bijvoorbeeld met het commando:
Serial.println(VariableWithAReading);
De variabele “VariableWithAMeasured Value” moet uiteraard uw gemeten waarde als getal bevatten.
Vervolgens moet u de seriële plotter op de computer starten. Deze vindt u onder “Extra/Seriële Plotter”.
Een eenvoudig voorbeeld waarbij een sinuscurve op de seriële plotter wordt weergegeven, is het volgende. Probeer de code gewoon uit. Het zou op elke Arduino moeten draaien. Vergeet niet om uw “seriële plotter” in te stellen op 115200 baud.
/* _ _ _ _ _ | | | | |(_) | | __ ____ ____ __ | | | ___ _ __ __| | _ _ _ __| | ___ / / / / / / / / / | . ` | / _ | '__|/ _` || || | | | / _` | / _ V V / V V / V /_ | | | __/| | (_| | | |_| | _| (_| | __/ \_/\_/ \_/\_/ \_/\_/(_)|_| \_| \___||_| \__,_||_| \__, |(_)\__,_| \___| __/ | |___/ sinusTest door Fabian Steppat Info op https://www.nerdiy.de/ardunio-die-serielle-schnittstelle/ Dit programma is vrije software: je mag het verspreiden en/of wijzigen onder de voorwaarden van de GNU General Public License zoals gepubliceerd door de Free Software Foundation, ofwel versie 3 van de Licentie, of (naar keuze) een latere versie. Dit programma wordt verspreid in de hoop dat het nuttig zal zijn, maar ZONDER ENIGE GARANTIE; zelfs zonder de impliciete garantie van VERKOOPBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL. Zie de GNU General Public License voor meer details. Je zou een kopie van de GNU Algemene Gebruikerslicentie moeten hebben ontvangen samen met dit programma ontvangen. Zo niet, zie . Aanvullende informatie over dit project vind je op het volgende adres:HowTo: Ardunio – Gebruik de seriële poortDeze codesnippet print een sinusgolf via seriële console of seriële plotter */ //variabelen en constanten float degreeAngle = 0; float sinusWaarde = 0; const vlotter pi = 3,1415; zweef radiaalhoek = 0; const uint8_t sinusFactor = 50; ongeldige setup() { Serial.begin(115200); } lege lus() { radiantAngle = gradenHoek * pi / 180; //graden maken in radialen sinusValue = sin(radiantAngle); // bereken sinus vanuit stralingshoek degreeAngle += 1.0; // verhoog de hoekvertraging (5); // maak de uitvoer een beetje langzamer als (degreeAngle> 360) // als de graadgrens is bereikt, reset deze dan naar nul { degreeAngle = 0; } Serieel.println(sinusFactor * sinusWaarde); // uitvoer naar seriële monitor/plotter}
Natuurlijk werkt de plotter niet alleen met sinuswaarden, maar ook met alle andere numerieke waarden.
Stuur commando's en parameters naar de Arduino
Je weet nu dus hoe je verschillende statusmeldingen of waarden van de Arduino naar de computer kunt sturen.
Maar het werkt ook andersom. Dit is vooral handig of praktisch als je de Arduino van buitenaf wilt bedienen en geen invoerapparaten zoals knoppen en dergelijke op de Arduino wilt aansluiten (of niet kunt door het ontbreken van GPIO's).
Je kunt bijvoorbeeld de helderheid of kleur van een LED of de motorsnelheid van een aangesloten motor alleen via de seriële interface instellen.
De Arduino IDE biedt een aantal handige functies voor communicatie via de seriële interface. (Je kunt de documentatie met meer details hier vinden: https://www.arduino.cc/reference/en/language/functions/communication/serial/)
Er moeten nu drie taken worden opgelost om ervoor te zorgen dat de ontvangst en evaluatie van commando's werkt:
1. Hoe herkent de Arduino ontvangen karakters?
2. Hoe zijn complete commando's samengesteld uit de ontvangen karakters?
3. hoe kunnen deze ontvangen commando's worden geëvalueerd?
1. Hoe herkent de Arduino ontvangen karakters
Om te reageren op inkomende karakters is er de functie
Serieel.beschikbaar()
Hiermee wordt gecontroleerd of er nieuwe tekens in de ontvangstbuffer van de Arduino aanwezig zijn. De ontvangstbuffer is een soort buffer waarin ontvangen karakters worden opgeslagen totdat de microcontroller van de Arduino tijd heeft om de ontvangen karakters te “verzorgen”.
In het geval dat er nieuwe tekens zijn ontvangen maar nog niet uit de ontvangstbuffer zijn gelezen, retourneert de functie “Serial.available()” “true”, anders “false”.
Deze functie is perfect om te controleren of er tekens zijn ontvangen die nu moeten worden geëvalueerd. Het commando vertelt ons niet hoeveel karakters er zijn ontvangen. Het zegt alleen dat er minstens één karakter in de ontvangstbuffer zit.
2. Hoe de ontvangen karakters om te zetten in volledige commando's
Goed, nu hebben we dankzij de vorige functie herkend dat er ten minste één karakter beschikbaar is in de ontvangstbuffer. Maar hoe krijgen we nu de ontvangen tekens?
Met het commando kunnen tekens uit de ontvangstbuffer worden gelezen
Serieel.lezen()
uitlezen. De functie voert het eerste teken in de ontvangstbuffer uit en verwijdert het automatisch uit de ontvangstbuffer.
Om nu alle tekens uit te lezen en in een variabele te schrijven, lezen we nu uit de ontvangstbuffer tot deze leeg is en noteren we elk uitgelezen teken.
U kunt dit doen met een lus, bijvoorbeeld:
void check_serial_receipt() { String serialBuffer; while (Serial.available()) { char currentchar = (char)Serial.read(); if (currentcharacter == 13) //controleer of het gelezen teken het regeleinde teken is { receive_char_evaluate(serialBuffer); } anders { serialBuffer += huidig teken; } } }
Zoals je kunt zien, bestaat de code uit een while-lus die loopt totdat de ontvangstbuffer leeg is (dan is Serial.available()==false).
Binnen de while-lus worden de karakters in de ontvangstbuffer karakter voor karakter gelezen (Serial.read()), toegewezen aan de “current character” variabele en toegevoegd aan de “serial buffer” string.
Dit is waar de lijnterminator die wordt genoemd in het gedeelte "Seriële monitor" in het spel komt. In dit (en elk ander terminalprogramma) kunt u een teken instellen dat automatisch wordt toegevoegd en verzonden telkens wanneer een teken of tekenreeks wordt verzonden.
Deze regeleinden kunnen nu worden gebruikt om te herkennen of de eerder gelezen string compleet is en dus kan worden geëvalueerd.
Dit betekent dat elk ontvangen karakter gecontroleerd moet worden om te zien of het de regeleinde is. In de bovenstaande code wordt dit gedaan door
als (currentChar == 13)...
Laat je niet verwarren door de 13. Het probleem met lijnterminators is dat ze niet op een toetsenbord worden weergegeven. U kunt ze dus niet als vergelijkingstekens in de code 'typen'.
Om het ontvangen teken toch te controleren op de tekenafsluiting, gebruiken we hier een truc.
dankzij de ASCII-tabel weten we dat elk teken in de computer overeenkomt met een bytewaarde (d.w.z. een numerieke waarde tussen 0 en 255).
Als u bijvoorbeeld een “A” in de Arduino opslaat, slaat deze feitelijk de numerieke waarde “65” op.
Als u nu wilt controleren of een ontvangen teken overeenkomt met een “A”, kunt u dat ook doen
als (huidigekarakter == "A")
of ook
als (huidigeteken == 65)
schrijven. Beide vergelijkingen zouden tot hetzelfde resultaat leiden.
We zullen nu gebruik maken van deze truc. Om te controleren of het huidige ontvangen teken een regeleinde is, zoals de CR (=CarriageReturn), controleren we niet het teken zelf, maar de waarde van het teken in de ascii-tabel: dus 13.
Zodra dit teken is ontvangen, weten we dat alle eerder verzonden tekens een commando moeten voorstellen en nu moeten worden geëvalueerd.
3. hoe deze ontvangen commando's kunnen worden geëvalueerd
Dus wij of de Arduino hebben nu een commando ontvangen. Dit wordt opgeslagen in de stringvariabele “seriële buffer” en wordt als functieparameter doorgegeven aan de functie “receive_character_evaluate()”.
Deze functie zou er bijvoorbeeld zo uit kunnen zien:
void received_characters_evaluate(String serialBuffer) { Serial.println("" + String(serialBuffer) + "" ontvangen."); //uitvoer van de zojuist ontvangen opdracht. if (serialBuffer == "simpleCommandDerWasTut") { simpler_command_the_what_does(); } anders als (serialBuffer.indexOf('=') != -1) { uint16_t receivedValue = serialBuffer.substring(serialBuffer.indexOf('=') + 1).toInt(); String ontvangenParameter = serialBuffer.substring(0, serialBuffer.indexOf('=')); if (receivedParameter == "commandSetOneValue") { als (receivedValue = 0) { command_the_one_value_sets(receivedvalue ); } anders { Serial.println(F("Waarde buiten het toegestane waardenbereik."); } } anders { Serial.print(F("De opdracht "")); Serial.print(serialBuffer); Serial.print(F("" werd niet herkend."); } } anders { Serial.print(F("Het commando ""); Serial.print(serialBuffer); Serial.print(F("" werd niet herkend."); } }
Nadat een commando is ontvangen, wordt het opnieuw uitgevoerd, wat erg praktisch is voor debugging-doeleinden. Op deze manier kun je controleren welke tekenreeks uiteindelijk in de Arduino is aangekomen.
Vervolgens kunt u met een eenvoudige IF-query controleren welke tekenreeks overeenkomt met het ontvangen commando. Hier wordt bijvoorbeeld gecontroleerd of het commando overeenkomt met de string “simplerCommandDerWasTut”.
Als dit het geval is, wordt de functie “simpler_command_that_does_();” uitgevoerd.
Met behulp van deze ‘absolute’ commando’s kon je nu eenvoudige commando’s geven. Bijvoorbeeld om een lamp aan of uit te doen.
Om waarden te kunnen overdragen, moeten ook commando's in de vorm “brightnessSetUp=20” kunnen worden geëvalueerd.
Dus de opdrachtnaam (in dit geval “brightnessSetOn”) en de waarde (in dit geval “20”) moeten worden herkend.
Dit wordt gedaan in het verdere deel van de hierboven getoonde code.
Als geen van de “absolute” commando’s overeenkomt met de ontvangen tekenreeks, wordt gecontroleerd of er een “=”-teken in de ontvangen tekenreeks voorkomt.
Als u bijvoorbeeld het commando “setBrightness=100” naar de Arduino hebt verzonden, kan deze niet de hele reeks “setBrightness=100” aan een “absoluut” commando toewijzen.
In dit geval wordt de ontvangen tekenreeks gecontroleerd op een gelijkteken en deze wordt ook gevonden.
De ontvangen tekenreeks wordt vervolgens opgesplitst in het gedeelte voor en na het gelijkteken met de volgende opdrachten.
uint16_t ontvangenWaarde = seriëlebuffer.substring(seriëlebuffer.indexOf('=') + 1).toInt(); String van ontvangen parameters = serialbuffer.substring(0, serialbuffer.indexOf('='));
Nu wordt de “100” opgeslagen in de variabele “receivedValue” en de opdracht “setBrightness” wordt opgeslagen in de variabele “receivedParameter”.
Nadat de twee waarden uit de ontvangen string zijn gehaald, kunnen ze verder worden verwerkt en gebruikt.
Probeer het gewoon 🙂
Je kunt de volledige code om het opnieuw te proberen hier vinden:
/* _ _ _ _ _ | | | | |(_) | | __ ____ ____ __ | | | ___ _ __ __| | _ _ _ __| | ___ / / / / / / / / / | . ` | / _ | '__|/ _` || || | | | / _` | / _ V V / V V / V /_ | | | __/| | (_| | | |_| | _| (_| | __/ \_/\_/ \_/\_/ \_/\_/(_)|_| \_| \___||_| \__,_||_| \__, |(_)\__,_| \___| __/ | |___/ serialTest door Fabian Steppat Info op https://www.nerdiy.de/ardunio-die-serielle-schnittstelle/ Dit programma is vrije software: u mag het verspreiden en/of wijzigen onder de voorwaarden van de GNU General Public License zoals gepubliceerd door de Free Software Foundation, ofwel versie 3 van de Licentie, of (naar keuze) een latere versie. Dit programma wordt verspreid in de hoop dat het nuttig zal zijn, maar ZONDER ENIGE GARANTIE; zelfs zonder de impliciete garantie van VERKOOPBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL. Zie de GNU General Public License voor meer details. Je zou een kopie van de GNU Algemene Gebruikerslicentie moeten hebben ontvangen samen met dit programma ontvangen. Zo niet, zie . Aanvullende informatie over dit project vind je op het volgende adres:HowTo: Ardunio – Gebruik de seriële poortDeze codesnippet is een basisconcept van seriële communicatie om een arduino te besturen via seriële commando's */ { Serial.begin(115200); } void loop() { check_serial_receive(); } void check_serial_receive() { String serialBuffer; while (Serial.available()) { char currentcharacter = (char)Serial.read(); if (currentcharacter == 13) { receive_char_evaluate(serialBuffer); } anders { serialBuffer += huidig teken; } } } void received_character_evaluate(String serialBuffer) { Serial.println("" + String(serialBuffer) + "" ontvangen."); Als (serialBuffer == "simplerCommandTheWhatDoes") { simpler_command_the_what_does(); } anders als (serialBuffer.indexOf('=') != -1) { uint16_t receivedValue = serialBuffer.substring(serialBuffer.indexOf('=') + 1).toInt(); String ontvangenParameter = serialBuffer.substring(0, serialBuffer.indexOf('=')); if (receivedParameter == "commandSetOneValue") { if (receivedValue & lt; = 23 & amp; & receivedValue & gt; = 0) { command_the_one_value_sets(receivedvalue ); } anders { Serial.println(F("Waarde buiten het toegestane waardenbereik."); } } anders { Serial.print(F("De opdracht "")); Serial.print(serialBuffer); Serial.print(F("" werd niet herkend."); } } anders { Serial.print(F("Het commando ""); Serial.print(serialBuffer); Serial.print(F("" werd niet herkend."); } }
Veel plezier met het project
Ik hoop dat alles werkte zoals beschreven. Zo niet, of als je vragen of suggesties hebt, laat het me weten in de commentaren. Ik zal dit dan zo nodig aan het artikel toevoegen.
Ideeën voor nieuwe projecten zijn altijd welkom. 🙂
PS Veel van deze projecten - vooral de hardwareprojecten - kosten veel tijd en geld. Natuurlijk doe ik dit omdat ik het leuk vind, maar als je het cool vindt dat ik de informatie met je deel, dan zou ik blij zijn met een kleine donatie aan het koffiefonds. 🙂