Benutzer-Werkzeuge

Webseiten-Werkzeuge


techniken:datenaustausch:serialchars

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
techniken:datenaustausch:serialchars [2015/01/14 15:30]
fbonowski [Erweiterung auf mehrere Befehle mit switch/case]
techniken:datenaustausch:serialchars [2016/01/21 12:45] (aktuell)
Zeile 1: Zeile 1:
-====== ​Kommandos in Form von einzelnen Zeichen an den Arduino ​senden ​======+====== ​Übermittlung ​von Kommandos und Daten vom PC zum Arduino ====== 
 +In diesem Artikel ist beschrieben,​ wie ihr 
 +  * Arduino-Programme mittels einfacher Kommandos vom PC aus '​fernsteuern'​ könnt. 
 +  * Zahlen vom PC an den Arduino übermitteln könnt.
  
 +Beide Mögglichkeiten können problemlos mit dem [[techniken:​datenaustausch:​processingserialread|Senden von Daten vom Arduino zum PC]] kombiniert werden.
 +
 +Dazu verwenden wir die Serielle Schnittstelle des Arduinos, die ihr bereits aus dem '​Serial Monitor'​ kennt. Ihr könnt also einfach den Serial-Monitor nutzen, um manuell Daten an den Arduino zu schicken - z.B. um zu testen, ob er auf Kommandos so reagiert wie ihr es erwartet. Wirklich spannend wird es aber, wenn ihr ein eigenes Programm (z.B. ein Processing-Sketch) schreibt, welches die Serielle Schnittstelle verwendet, um dem Arduino vollautomatisch Befehle zu übermitteln.
 +
 +In allen Fällen muss der Arduino mit einem Kabel mit dem PC verbunden sein - denn über dieses Kabel werden die Daten in Form von Elektrischen Impulsen übertragen...
 +===== Kommandos in Form von einzelnen Zeichen an den Arduino senden =====
 Die einfachste Art und Weise, einen Befehl vom PC an den Arduino zu übermitteln,​ ist, ihm einzelne Zeichen über die Serielle Schnittstelle zu schicken, die ein Programm auf dem Arduino auswertet. ​ Die einfachste Art und Weise, einen Befehl vom PC an den Arduino zu übermitteln,​ ist, ihm einzelne Zeichen über die Serielle Schnittstelle zu schicken, die ein Programm auf dem Arduino auswertet. ​
  
Zeile 11: Zeile 20:
   * Eine Funktion aufrufen, die das erledigt, was dem Befehl entspricht (im Befehlsblock (geschweifte Klammern) von ''​if''​ oder ''​switch case''​)   * Eine Funktion aufrufen, die das erledigt, was dem Befehl entspricht (im Befehlsblock (geschweifte Klammern) von ''​if''​ oder ''​switch case''​)
  
-===== Ein Bespielprogramm ​mit 2 alternativen Befehlen (LED an/​aus) ​=====+==== Ein Beispielprogramm ​mit 2 alternativen Befehlen (LED an/aus) ====
 Das Beispiel ''​libraries/​Serial/​SimpleWrite''​ in Processing enthält sowohl den Processing, als auch den Arduino Code, um mit der Maus eine LED auf dem Arduino ein- und ausschalten zu können. Hier ein kleiner Ausschnitt mit den wichtigsten Teilen auf Arduinoseite:​ Das Beispiel ''​libraries/​Serial/​SimpleWrite''​ in Processing enthält sowohl den Processing, als auch den Arduino Code, um mit der Maus eine LED auf dem Arduino ein- und ausschalten zu können. Hier ein kleiner Ausschnitt mit den wichtigsten Teilen auf Arduinoseite:​
  
Zeile 58: Zeile 67:
     }      } 
 </​code>​ </​code>​
-===== Erweiterung auf Kommandos mit dazugehörigen ​Zahlenwerten =====+===== Übertragen von Zahlenwerten ​(als menschenlesbarer ASCII-Text) ​=====
 In vielen Fällen wollen wir nicht nur ein Kommando übertragen ("​fahre geradeaus"​),​ sondern auch dazugehörige Zahlenwerte ("wie lange?"​ , "wie schnell?",​ "wie weit?"​). ​ In vielen Fällen wollen wir nicht nur ein Kommando übertragen ("​fahre geradeaus"​),​ sondern auch dazugehörige Zahlenwerte ("wie lange?"​ , "wie schnell?",​ "wie weit?"​). ​
  
-Das geht ganz einfach mit den beiden Befehlen ​''​Serial.parseInt()'' ​(für Ganzzahlen) oder ''​Serial.parseFloat()''​+Das geht ganz einfach mit den beiden Befehlen ​[[http://​arduino.cc/​en/​Serial/​ParseInt|Serial.parseInt()]] (für Ganzzahlen) oder [[http://​arduino.cc/​de/​Reference/​StreamParseFloat|Serial.parseFloat()]] (Für Kommazahlen)
-Beide Befehle lesen solange Daten aus der seriellen Schnittstelle,​ bis entweder längere Zeit nichts mehr gekommen ist ("​timeout"​) oder das nächste Zeichen nicht mehr Teil einer Zahl sein kann (also irgendetwas ausser 0...9 oder '​.'​ ist).+Beide Befehle lesen solange Daten aus der seriellen Schnittstelle,​ bis entweder längere Zeit nichts mehr gekommen ist ("​timeout"​) oder das nächste Zeichen nicht mehr Teil einer Zahl sein kann (also irgendetwas ausser 0...9, '​+',​ '​-' ​oder '​.'​ ist).
  
-Zum Steuern eines Motors ​könnten wir z.B. die Kommandos 'f' für vorwärts ​'b' für rückwärts ​verwenden, die jeweils von einer Zahl gefolgt sind, die angibt, wieviel Gas in die entsprechende ​Richtung gegeben werden ​soll. Ein kompletter Befehl, der so in den Serial-Monitor eingegeben oder von Processing verschickt werden kann wäre also z.B. 'f100' oder 'b20'.+//​**Achtung**//:​ Als Dezimaltrennzeichen wird (wie eigentlich immer beim Programmieren) der **Punkt** (anstelle des **Kommas**) verwendet. 
 + 
 +Zum Steuern eines Roboters ​könnten wir z.B. die Kommandos 'l' für "​links"​ und 'r' für "​rechts" ​verwenden, die jeweils von einer Zahl gefolgt sind, die angibt, wieviel Gas der entsprechende ​Motor geben soll. Ein kompletter Befehl, der so in den Serial-Monitor eingegeben oder von Processing verschickt werden kann wäre also z.B. 'l100' oder 'r-20'.
  
 Der Arduino Code dafür könnte z.B. so aussehen: Der Arduino Code dafür könnte z.B. so aussehen:
Zeile 71: Zeile 82:
     int inByte = Serial.read();​ // ...dann lies das erste Byte und speichere es in der Variable inByte     int inByte = Serial.read();​ // ...dann lies das erste Byte und speichere es in der Variable inByte
     switch (inByte) {           // und nimm den Wert, der übertragen wurde, genauer unter die Lupe.     switch (inByte) {           // und nimm den Wert, der übertragen wurde, genauer unter die Lupe.
-    case 'f': ​                  // wenn dieser das Zeichen 'f' für 'vorwärts' ist...+    case 'r': ​                  // wenn dieser das Zeichen 'r' für 'rechts' ist...
       {       {
-      int inValue=Serial.parseInt(); ​       // dann lies erstmal eine Zahl ein (wenn irgendetwas anders kam, ist das Ergebnis 0 ) +      int inValue=Serial.parseInt(); ​            ​// dann lies erstmal eine Zahl ein (wenn irgendetwas anders kam, ist das Ergebnis 0 ) 
-      digitalWrite(directionPin,HIGH);      // stelle den Motor auf '​vorwärts'​ +      digitalWrite(directionPinRight,inValue>​0); // stelle den Motor auf '​vorwärts'​, wenn der wert größer 0 ist, sonst auf rückwärts 
-      analogWrite(throttlePin, inValue); ​   // ... gib genau so viel Gas, wie gewünscht.+      analogWrite(throttlePinRight, inValue); ​   // ... gib genau so viel Gas, wie gewünscht.
       break; ​                   // höre hier auf.       break; ​                   // höre hier auf.
       }       }
-    case 'b': ​                  // ..rückwärts ​genauso:+    case 'l': ​                  // ..links genauso:
       {       {
-      int inValue=Serial.parseInt(); ​       // dann lies erstmal eine Zahl ein (wenn irgendetwas anders kam, ist das Ergebnis 0 ) +      int inValue=Serial.parseInt(); ​            ​// dann lies erstmal eine Zahl ein (wenn irgendetwas anders kam, ist das Ergebnis 0 ) 
-      digitalWrite(directionPin,LOW);       ​// stelle den Motor auf 'rückwärts+      digitalWrite(directionPinLeft,inValue>​0);  // stelle den Motor auf 'vorwärts', wenn der wert größer 0 ist, sonst auf rückwärts 
-      analogWrite(throttlePin, inValue); ​   // ... gib genau so viel Gas, wie gewünscht.+      analogWrite(throttlePinLeft, inValue); ​    ​// ... gib genau so viel Gas, wie gewünscht.
       break; ​                   // höre hier auf.       break; ​                   // höre hier auf.
       }       }
-     ​case ​default: // bei uns unbekannten Kommandos machen wir einfach garnichts...+    ​default: // bei uns unbekannten Kommandos machen wir einfach garnichts...
       break; ​       break; ​
    }    }
 </​code>​ </​code>​
  
 +Hier der passende Processing Code dazu:
 +
 +<code Java>
 +/**
 + * SendSomeInt
 + ​* ​
 + * Send numbers to a Serial Port
 + * This example is in the public domain.
 + */
 +import processing.serial.*; ​  //​verwende die '​Serial'​ Library
 +
 +Serial myPort; ​  // Deklariere ein Object vom Typ '​Serial',​ mit dem Namen '​myPort'​
 +
 +void setup() {
 +  // Um den Namen der Schnittstelle herauszufinden,​ lassen wir uns von der Serial-Klasse zunächst
 +  // eine Liste der Namen der am PC vorhandenen Ports geben ('​Serial.list()'​)
 +  // Den x'ten Eintrag aus dieser Liste bekommen wir mit '​Serial.list()[x-1]'​ (die indices fangen mit 0 an)
 +  ​
 +  // Bei den meisten PCs ist der Arduino der letzte Port in der Liste.
 +  // Deshalb ermitteln wir zunächst die Länge der Liste (Serial.list().length) ​
 +  // und nehmen uns den letzten Namen aus der Liste heraus (Serial.list()[Serial.list().length-1]) ​
 +  ​
 +  String portName = Serial.list()[Serial.list().length-1];​ // finde den Namen des letzten Serialports heraus.
 +  int baudrate=115200; ​      // Diese Baudrate muss mit der in eurem Arduinoprogramm übereinstimmen.
 +  //   ​String portName = "​COM1";​ // alternativ: verwende stattdessen einen bekannten Portnamen
 +  myPort = new Serial(this,​ portName, baudrate); // Erzeuge ein Serial Objekt und stelle eine Verbindung her
 +  ​
 +  size(300, 300); // mache das Fenster etwas größer
 +}
 +
 +void draw() {
 +  int forwardSpeed= (int)map(mouseY,​height,​ 0 , -127, 127); //rechne die y-Position des Mauszeigers in einen Schubwert zwischen -127 und 127 um.
 +  // das (int) sorgt für die Umwandlung der Kommazahl in einen Ganzzahligen (integer) Wert.
 +  int turnSpeed= (int) map(mouseX, 0, height, -127, 127);   //​rechne die x-Position des Mauszeigers in ein Drehgeschwindigkeit zwischen -127 und 127 um.
 +  int leftSpeed=forwardSpeed+turnSpeed; ​ //Zum Vorwärtsfahren drehen sich beide Motoren in die gleiche Richung, zum Drehen in Unterschiedliche
 +  int rightSpeed=forwardSpeed-turnSpeed;​
 +  myPort.write('​l'​+str(leftSpeed)+"​\n"​); ​ //Sende erst '​l',​ dann die mit str() in eine Zeichenkette umgewandelte Zahl, dann einen Zeilenabschluss ("​\n"​)
 +  myPort.write('​r'​+str(rightSpeed)+"​\n"​);​ //Sende erst '​r',​ dann die mit str() in eine Zeichenkette umgewandelte Zahl, dann einen Zeilenabschluss ("​\n"​)
 +  println("​vor :"​+forwardSpeed+"​\tdreh:​ "​+turnSpeed+"​\t-->​ links:"​+leftSpeed+ "​\trechts:​ "​+rightSpeed);​
 +}
 +
 +</​code>​
  
techniken/datenaustausch/serialchars.1421245843.txt.gz · Zuletzt geändert: 2016/01/21 12:45 (Externe Bearbeitung)