HowTo: Ardunio – Usar el puerto serie

Über die serielle Schnittstelle wird normalerweise jedes Arduino Board programmiert.
Darüber lässt sich aber nicht nur der Programmcode auf den Arduino übertragen. Es lassen sich auch Steuerbefehle an den Arduino senden oder Werte vom Arduino empfangen.

Wie das geht und welche Möglichkeiten Ihr dabei habt beschreibe ich im folgenden Artikel.


Instrucciones de seguridad

Sé que las siguientes notas siempre son un poco molestas y parecen innecesarias. Desafortunadamente, muchas personas que sabían "mejor" han perdido ojos, dedos u otras cosas debido a un descuido o se lesionaron. La pérdida de datos es casi insignificante en comparación, pero incluso estos pueden ser realmente molestos. Por lo tanto, tómese cinco minutos para leer las instrucciones de seguridad. Porque incluso el proyecto más genial no vale la pena lesionarse u otros problemas.
https://www.nerdiy.de/sicherheitshinweise/

Enlaces afiliados / enlaces publicitarios

Los enlaces a las tiendas en línea enumerados aquí son los llamados enlaces de afiliados. Si hace clic en dicho enlace de afiliado y realiza una compra a través de este enlace, Nerdiy.de recibirá una comisión de la tienda en línea o el proveedor correspondiente. El precio no cambia para usted. Si realiza sus compras a través de estos enlaces, ayuda a Nerdiy.de a poder ofrecer otros proyectos útiles en el futuro. 🙂 


Preparar interfaz serial

Um die serielle Schnittstelle in Eurem Programm zu nutzen müsst Ihr diese initialisieren.
Dies geschieht indem Ihr in der “setup()”-Funktion die Funktion

Serial.begin(115200);

aufruft. Die Zahl “115200” steht dabei für die Baudrate – also die Geschwindigkeit – mit der die Symbole Nicht Bits oder Bytes) über die serielle Schnittstelle übertragen werden. Diese Geschwindigkeit solltet ihr von der “Qualität” der Verbindungsleitung abhängig machen.

Por ejemplo, si tiene un cable blindado y muy corto, la velocidad se puede establecer muy alta.
Bei nicht abgeschirmten und/oder sehr langen Kabeln sollte diese Geschwindigkeit nicht so hoch gewählt werden.

Gängige Baudraten sind zum Beispiel die folgenden Werte:

50
110
150
300
1200
2400
4800
9600
19200
38400
57600
115200
230400
460800
500000

Egal welche Geschwindigkeit Ihr einstellt, dieser Wert muss auch im “Seriellen Monitor” – also dem anderen Kommunikationspartner der seriellen Kommunikation – eingestellt werden. Nur dann werden die Zeichen korrekt empfangen und gesendet. Mehr dazu erfahrt Ihr im Laufe des Textes.

Falls Ihr Euch unsicher seid, welche Baudrate Ihr verwenden sollt empfehle ich Werte zwischen 9600 baud und 115200 baud. Diese und die dazwischen liegenden Werte sind auch bei vielen fertigen produkten wie Sensoren und Aktoren die gängigen Werte.


Enviar datos desde la placa Arduino a la computadora conectada

Damit Ihr Daten von eurem Arduino Board an den verbundenen Computer senden könnt müsst ihr folgende Funktion aufrufen.

Diese sendet den Text “Hallo Welt!” inklusive Zeilenumbruch an den Computer.

Serial.println("¡Hola mundo!");

Als Beispiel könnt Ihr dazu folgenden Code ausprobieren.

configuración vacía () { Serial.begin (115200); } void loop() { Serial.println("¡Hola mundo!"); retraso (1000); }
Dadurch erhaltet Ihr die abgebildete Ausgabe. Nach jedem “Hallo Welt!” wird automatisch ein Wechsel in die nächste Zeile vorgenommen.

In der folgenden Kombination sendet die Funktion den Text “Hallo Welt!” ohne Zeilenumbruch an den Computer.

Serial.print("¡Hola mundo!");

Hay otro ejemplo de esto.

configuración vacía () { Serial.begin (115200); } void loop() { Serial.print("¡Hola mundo!"); retraso (1000); }
Da nun nach dem “Hallo Welt!” kein Zeilenumbruch vorgenommen wird entsteht eine Lange Zeile aus mehreren “Hallo Welt!”-Abschnitten.

Wollt Ihr Variabel-Werte – in diesem Fall den Wert der Variable “lustige_variable” –  senden könnt Ihr dies wie folgt tun:

uint8_t variable_divertida=5; Serial.println(String(funny_variable));

Como ejemplo, todo se ve así de nuevo.

configuración vacía () { Serial.begin (115200); } void loop() { uint8_t variable_divertida=5; Serial.println(String(funny_variable)); retraso (1000); }
El valor (5) de la variable se emite con un salto de línea.

Senden eines Zeilenumbruchs bedeutet, dass zusätzlich zu dem eigentlichen Nachrichteninhalt noch ein Steuerzeichen mitgesendet wird, dass dem Empfänger signalisiert in die nächste Zeile zu wechseln.


Usar monitor serie

Der Serielle Monitor ist das Gegenstück zum Arduino-Board. Es ist das Programm welches am Computer die Daten empfängt und für euch lesbar macht.
Ihr findet es als Teil der Arduino-IDE unter dem Menüpunkt “Werkzeuge/Serieller Monitor”. Tools wie dieser “Serielle Monitor” werden auch Terminalprogramme genannt. Eine gute Alternative zu dem “Seriellen Monitor” der Arduino-IDE ist auch das Programm HTERM.

Im Fenster des Seriellen Monitors lassen sich das Zeilenabschlusszeichen und die Baudrate einstellen. Durch einen Klick auf “Ausgabe löschen” lässt sich außerdem der Inhalt des Ausgabefensters löschen.

In dem Fenster des Seriellen Monitors lässt sich die Baudrate einstellen. Hier muss der gleiche Wert eingestellt werden den ihr zuvor im Programmcode eingestellt habt.
¿Ustedes con el comando

Serial.begin(115200);

also eine Baudrate von 115200 baud eingestellt so müsst Ihr auch im seriellen Monitor eine Baudrate von 115200 baud einstellen.

Neben der Baudrate lässt sich außerdem noch das Zeilenabschlusszeichen einstellen. Diese Einstellung benötigt Ihr aber nur, wenn Ihr Daten vom Computer an den Arduino senden wollt.

Hier lässt sich nämlich das Zeichen einstellen, welches nach jedem Absenden eines Wertes automatisch angehängt und mitgesendet wird.

Dies könnt Ihr in Eurem Code zum Beispiel sehr gut dazu nutzen um auf dem Arduino zu erkennen ob die Übertragung eines Befehls oder Werts abgeschlossen ist.

Im Bereich “Befehle und Parameter an den Arduino senden” wird dies ausführlich erklärt.


Usar plotter en serie

Der Serielle-Plotter ist ein Tool mit dem Ihr Zahlenwerte (z.B. Messwerte) direkt auf dem Computer als zeitlichen Verlauf darstellen könnt. Dazu müsst ihr den Arduino so programmieren, dass er die Zahlenwerte an den Computer sendet.
Esto se puede hacer, por ejemplo, con el comando:

Serial.println(VariableConUnaLectura);

Die Variable “VariableMitEinemMesswert” sollte natürlich euren Messwert als Zahl enthalten.
Auf dem Computer müsst ihr dann den Seriellen Plotter starten. Diesen findet ihr unter “Werkzeuge/Serieller Plotter”.

Ein simples Beispiel das auf dem seriellen Plotter eine Sinus-Kurve ausgibt ist das folgende. Probiert den Code einfach aus. Er sollte sich auf jedem Arduino ausführen lassen. Denkt daran Euren “Seriellen Plotter” auf 115200 baud einzustellen.

/*                                _   _                 _  _               _
                                 |  | |               | |(_)             | |
  __      ____      ____      __ |  | |  ___  _ __  __| | _  _   _     __| |  ___
    / / /  / / /  / / / | . ` | / _ | '__|/ _` || || | | |   / _` | / _ 
    V  V /   V  V /   V  V /_ | |  ||  __/| |  | (_| || || |_| | _| (_| ||  __/
    \_/\_/    \_/\_/    \_/\_/(_)|_| \_| \___||_|   \__,_||_| \__, |(_)\__,_| \___|
                                                               __/ |
                                                              |___/
     sinusTest by Fabian Steppat
     Infos on https://www.nerdiy.de/ardunio-die-serielle-schnittstelle/

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     You will find additional information to this project at the following address:
     
HowTo: Ardunio – Usar el puerto serie
Este codenippet imprime una onda sinusoidal a través de una consola serial o un plotter serial */ //variables y constantes float gradeAngle = 0; flotar sinusValue = 0; constante flotante pi = 3.1415; float radianAngle = 0; const uint8_t sinusFactor = 50; configuración vacía () { Serial.begin (115200); } bucle vacío () { ángulo radiante = ángulo de grado * pi / 180; //haciendo grados en radianes sinusValue = sin(radiantAngle); //calcular el seno a partir del ángulo radiante gradeAngle += 1.0; //aumenta el retraso del ángulo(5); //hace que la salida sea un poco más lenta si (ángulo de grado > 360) //si se alcanza el límite de grados, reinícielo a cero { ángulodegrado = 0; } Serial.println(sinusFactor * sinusValue); //salida al monitor/trazador serie}
El ejemplo anterior debería mostrar la onda sinusoidal que se muestra en el plóter en serie.

Der Plotter funktioniert natürlich nicht nur mit Sinus- sondern auch mit allen anderen Zahlen-werten.


Envía comandos y parámetros al Arduino

Ahora ya sabe cómo enviar varios mensajes de estado o valores desde el Arduino a la computadora.
Es geht aber auch andersherum. Dies ist besonders dann sinnvoll oder praktisch, wenn ihr den Arduino von außen steuern und keine Eingabegeräte wie Taster und Co. an den Arduino anschließen wollt (oder mangels GPIOs könnt).

So könnt Ihr zum Beispiel die Helligkeit oder Farbe einer LED oder auch eine Motordrehzahl eines angeschlossenen Motors alleine über die serielle Schnittstelle einstellen.

Zur Kommunikation über die serielle Schnittstelle stell die Arduino-IDE dazu ein paar nützliche Funktionen bereit. (Die Dokumentation mit mehr Details dazu findet Ihr hier: https://www.arduino.cc/reference/en/language/functions/communication/serial/)

Damit der Empfang und die Auswertung von Befeheln klappt gibt es nun drei Aufgaben zu lösen:
1. ¿Cómo reconoce Arduino los caracteres recibidos?
2. ¿Cómo se componen los comandos completos de los caracteres recibidos?
3. Wie können diese empfangenen Befehle ausgewertet werden?

1. ¿Cómo reconoce Arduino los caracteres recibidos?

Para reaccionar a los caracteres entrantes existe la función

Serial.disponible()

Diese prüft ob neue Zeichen im Empfangspuffer des Arduino enthalten sind. Der Empfangspuffer ist dabei eine Art zwischenspeicher in dem empfangene Zeichen solange gespeichert werden bis der Mikrocontroller des Arduinos Zeit hat sich um die empfangegenen Zeichen zu “kümmern”.

In dem Fall, dass neue Zeichen empfangen, aber noch nicht aus dem Empfangspuffer gelesen wurden gibt die Funktion “Serial.available()” “true” zurück ansonsten “false”.

Diese Funktion eignet sich also perfekt dazu um zu überprüfen ob aktuell Zeichen emfpangen wurden, welche nun ausgewertet werden müssen. Dabei sagt uns der Befehl nicht wieviele Zeichen empfangen wurden. Er sagt nur, dass mindestens ein Zeichen im Empfangspuffer ist.

2. Cómo convertir los caracteres recibidos en comandos completos

Gut, nun haben wir dank der vorherigen Funktion erkannt, dass mindestens ein Zeichen im Empfangspuffer verfügbar ist. Aber wie kommen wir nun an die empfangenen Zeichen?

Los caracteres del búfer de recepción se pueden leer con el comando

Serie.leer()

leer. La función genera el primer carácter contenido en el búfer de recepción y lo elimina automáticamente del búfer de recepción.
Para ahora leer todos los caracteres y escribirlos en una variable, ahora leemos del búfer de recepción hasta que esté vacío y observamos cada carácter leído.
Puedes hacer esto con un bucle, por ejemplo:

void check_seriellen_empfang() 
{ 
   String seriellerPuffer; 
   while (Serial.available()) 
   {
      char aktuellesZeichen = (char)Serial.read(); 
      if (aktuellesZeichen == 13)   //prüfen ob das eingelesen Zeichen das Zeilenabschlusszeichen ist
      { 
         empfangene_zeichen_auswerten(seriellerPuffer); 
      } else 
      { 
         seriellerPuffer += aktuellesZeichen; 
      } 
   }
}

Wie Ihr sehen könnt besteht der Code aus einer while-schleife die solange läuft bis der Empfangspuffer leer ist (dann ist Serial.available()==false).
Innerhalb der while-Schleife werden währenddessen zeichenweise die auf dem Emfpangspuffer enthaltenen Zeichen ausgelesen (Serial.read()), der Variable “aktuellesZeichen” zugewiesen und an den String “seriellerPuffer” angehängt.

Hier kommt nun auch das im Abschnitt “Serieller Monitor” erwähnte Zeilenabschlusszeichen ins Spiel. In diesem (und jedem anderen Terminalprogramm) lässt sich nämlich ein Zeichen einstellen, welches nach jedem Absenden eines Zeichens oder einer Zeichenkette automatisch angehängt und mitgesendet wird.

Dieses Zeilenabschlusszeichen lässt sich nun nutzen um zu erkennen ob die zuvor eingelesene Zeichenkette abgeschlossen ist und somit ausgewertet werden kann.
Dies bedeutet, dass jedes empfangene Zeichen darauf geprüft werden muss ob es das Zeilenabschlusszeichen ist. Im oben gezeigten Code geschieht dies durch

si (carácter actual == 13)...

Lasst euch von der 13 nicht verwirren. Das Problem bei Zeilenabschlusszeichen ist nämlich, dass diese auf einer Tastatur nicht aufgeführt sind. Man kann sie also nicht als Vergleichszeichen in den Code “eintippen”.
Um das empfangene Zeichen trotzdem auf das Zeichenabschlusszeichen zu prüfen bedienen wir uns hier eines Tricks.

Gracias a tabla ASCII wissen wir nämlich, dass jedes Zeichen im Computer einem Byte-Wert(also einem Zahlenwert zwischen 0 und 255) entspricht.
Wenn ihr im Arduino also zum Beispiel ein “A” speichert, so speichert dieser eigentlich den Zahlenwert “65”.
Würde man nun prüfen wollen ob ein empfangenes Zeichen einem “A” entspricht könnte man entweder

if (personaje actual == "A")

o también

if (carácter actual == 65)

schreiben. Beide Vergleiche würden zum gleichen Ergebnis führen.

Diesen Trick machen wir uns nun zu Nutze. Um zu prüfen, ob das aktuell empfangene Zeichen ein Zeilenabschlusszeichen wie zum Beispiel das CR (=CarriageReturn) ist, prüfen wir nicht auf das Zeichen selber sondern auf den Wert des Zeichens in der Ascii-Tabelle: Also 13.

Sobald dieses Zeichen empfangen wurde wissen wir also, dass alle zuvor abgesendeten Zeichen einen Befehl darstellen sollen und nun ausgewertet werden müssen.

3. Wie können diese empfangenen Befehle ausgewertet werden

Wir bzw. der Arduino hat nun also einen Befehl empfangen. Dieser ist in der String-Variable “seriellerPuffer” gespeichert und wird als Funktionsparameter an die Funktion “empfangene_zeichen_auswerten()” übergeben.

Diese Funktion könnte zum Beispiel so aussehen:

void empfangene_zeichen_auswerten(String seriellerPuffer)
{
   Serial.println(""" + String(seriellerPuffer) + "" empfangen.");   //ausgabe des soeben empfangenen Befehls
   
   if (seriellerPuffer == "simplerBefehlDerWasTut")
   {
      simpler_befehl_der_was_tut();
   } else if (seriellerPuffer.indexOf('=') != -1)
   {
      uint16_t empfangenerWert = seriellerPuffer.substring(seriellerPuffer.indexOf('=') + 1).toInt();
      String empfangenerParameter = seriellerPuffer.substring(0, seriellerPuffer.indexOf('='));
      
      if (empfangenerParameter == "befehlDerEinenWertSetzt")
      {
         if (empfangenerWert <= 23 && empfangenerWert >= 0)
         {
            befehl_der_einen_wert_setzt(empfangenerWert );
         } else
         {
            Serial.println(F("Wert ausserhalb des erlaubten Wertebereichs."));
         }
      } else
      {
         Serial.print(F("Der Befehl ""));
         Serial.print(seriellerPuffer);
         Serial.print(F("" wurde nicht erkannt."));
      }
   } else
   {
      Serial.print(F("Der Befehl ""));
      Serial.print(seriellerPuffer);
      Serial.print(F("" wurde nicht erkannt."));
   }
}

Nach dem Empfang eines Befehls wird dieser nochmal ausgegeben, dies ist gerade für Debugging-Zwecke sehr praktisch. So könnt Ihr überprüfen welche Zeichenkette denn letztendlich im Arduino angekommen ist.

Danach kann mit einer einfachen IF-Abfrage geprüft werden welcher Zeichenkette der empfangene Befehl entspricht. Hier wird zum Beispiel geprüft ob der Befehl der Zeichenkette “simplerBefehlDerWasTut” entspricht.
Ist dies der Fall wird die Funktion “simpler_befehl_der_was_tut();” ausgeführt.

Mithilfe dieser “absoluten” Befehle könntet ihr nun einfache Befehle absetzen. Zum Beispiel um ein Licht ein- oder auszuschalten.

Um nun aber auch Werte übergeben zu können müssen auch Befehle der Form “helligkeitSetzenAuf=20” ausgewertet werden können.
Es muss also der Befehlsname (in diesem Fall “helligkeitSetzenAuf”) und der Wert (in diesem Fall “20”) erkannt werden.

Esto se hace en la parte posterior del código que se muestra arriba.
Sollte nämlich keiner der “absoluten” Befehle zu der empfangenen Zeichenkette passen wird geprüft ob in der empfangenen Zeichenkette ein “=”-Zeichen Vorhanden ist.

Solltet Ihr also zum Beispiel den Befehl “setzeHelligkeit=100” an den Arduino gesendet haben wird er die gesamte Zeichenkette “setzeHelligkeit=100” keinem “absoluten” Befehl zuordnen können.

En este caso, la cadena de caracteres recibida se comprueba en busca de un signo igual y también se encuentra.

La cadena de caracteres recibida se divide en la parte anterior y posterior al signo igual con los siguientes comandos.

uint16_t ReceiveValue = serialbuffer.substring(serialbuffer.indexOf('=') + 1).toInt(); Cadena de parámetros recibidos = serialbuffer.substring(0, serialbuffer.indexOf('='));

Nun ist in der Variable “empfangenerWert” die “100” und in der Variable “empfangenerParameter” der Befehl “setzeHelligkeit” gespeichert.

Einmal aus der empfangenen Zeichenkette extrahiert, können die beiden Werte dann weiterverarbeitet und darauf reagiert werden.

Probiert es einfach aus. 🙂
Puede encontrar el código completo para volver a intentarlo aquí:

/*                                _   _                 _  _               _
                                 |  | |               | |(_)             | |
  __      ____      ____      __ |  | |  ___  _ __  __| | _  _   _     __| |  ___
    / / /  / / /  / / / | . ` | / _ | '__|/ _` || || | | |   / _` | / _ 
    V  V /   V  V /   V  V /_ | |  ||  __/| |  | (_| || || |_| | _| (_| ||  __/
    \_/\_/    \_/\_/    \_/\_/(_)|_| \_| \___||_|   \__,_||_| \__, |(_)\__,_| \___|
                                                               __/ |
                                                              |___/
     serialTest by Fabian Steppat
     Infos on https://www.nerdiy.de/ardunio-die-serielle-schnittstelle/

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     You will find additional information to this project at the following address:
     
HowTo: Ardunio – Usar el puerto serie
This codesnippet is a basic conept of a serial communication to control an arduino via serial commands */ { Serial.begin(115200); } void loop() { check_seriellen_empfang(); } void check_seriellen_empfang() { String seriellerPuffer; while (Serial.available()) { char aktuellesZeichen = (char)Serial.read(); if (aktuellesZeichen == 13) { empfangene_zeichen_auswerten(seriellerPuffer); } else { seriellerPuffer += aktuellesZeichen; } } } void empfangene_zeichen_auswerten(String seriellerPuffer) { Serial.println(""" + String(seriellerPuffer) + "" empfangen."); if (seriellerPuffer == "simplerBefehlDerWasTut") { simpler_befehl_der_was_tut(); } else if (seriellerPuffer.indexOf('=') != -1) { uint16_t empfangenerWert = seriellerPuffer.substring(seriellerPuffer.indexOf('=') + 1).toInt(); String empfangenerParameter = seriellerPuffer.substring(0, seriellerPuffer.indexOf('=')); if (empfangenerParameter == "befehlDerEinenWertSetzt") { if (empfangenerWert & lt; = 23 & amp; & empfangenerWert & gt; = 0) { befehl_der_einen_wert_setzt(empfangenerWert ); } else { Serial.println(F("Wert ausserhalb des erlaubten Wertebereichs.")); } } else { Serial.print(F("Der Befehl "")); Serial.print(seriellerPuffer); Serial.print(F("" wurde nicht erkannt.")); } } else { Serial.print(F("Der Befehl "")); Serial.print(seriellerPuffer); Serial.print(F("" wurde nicht erkannt.")); } }

Diviértete con el proyecto.

Espero que todo te haya funcionado como se describe. Si no es así, o si tiene alguna pregunta o sugerencia, hágamelo saber en los comentarios. Si es necesario, lo añadiré al artículo.
Las ideas para nuevos proyectos siempre son bienvenidas. 🙂

PS Muchos de estos proyectos, especialmente los proyectos de hardware, cuestan mucho tiempo y dinero. Por supuesto que hago esto porque lo disfruto, pero si crees que es genial que comparta la información contigo, me encantaría hacer una pequeña donación al fondo del café. 🙂

Cómprame un café en ko-fi.com       

Kommentar hinterlassen

Tu dirección de correo electrónico no será publicada. Erforderliche Felder sind mit * markiert


El periodo de verificación de reCAPTCHA ha caducado. Por favor, recarga la página.