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 [2014/10/16 12:18]
fbonowski
techniken:datenaustausch:serialchars [2016/01/21 12:45] (aktuell)
Zeile 1: Zeile 1:
-==== Einfach nur Kommandos==== +====== Übermittlung von Kommandos ​und Daten vom PC zum Arduino ====== 
-Wenn ihr "​einfach nur" ein Kommando an den Arduino ​übermitteln wollt (also keine Zahlen oder komplexeren Informationen), ​könnt ​ihr es durch einen einzelnen Buchstaben darstellen, den ihr über die Serielle Schnittstelle ​an den Arduino ​schickt.+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.
  
-Das Beispiel ​ ''​libraries/​Serial/​SimpleWrite''​ in Processing enthält sowohl den Processing, als auch den Arduino ​Code dafür.+Beide Mögglichkeiten können problemlos mit dem [[techniken:​datenaustausch:​processingserialread|Senden von Daten vom Arduino ​zum PC]] kombiniert werden.
  
-Eine schöne ​Erweiterung auf mehrere verschiedene ​Kommandos ist durch Verwendung von switch/​case ​möglich: +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. 
-[[http://​www.arduino.cc/​en/​Tutorial/​SwitchCase2|Beispielprogramm ''​control/​switchCase2''​ aus dem Arduino IDE]]+ 
 +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.  
 + 
 +Dabei kann z.B. der Buchstabe ''​f''​ für "fahre los" und der Buchstabe ''​s''​ für "​stop"​ stehen.  
 + 
 +Das Arduino Programm muss zum Empfang der Befehle nur: 
 +  * Überprüfen,​ ob neue Daten angekommen sind (mit ''​Serial.available()''​) 
 +  * Das erste Zeichen aus den angekommenen Daten lesen (mit ''​Serial.read()''​) 
 +  * Das erhaltene Zeichen untersuchen,​ um zu erkennen, ob es ein bekannter Befehl ist. (im Bedingungsteil (Runde 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 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:​ 
 + 
 +<code Java> 
 +... 
 +if (Serial.available()) { // Wenn Daten empfangen wurden und zum Lesen bereitstehen 
 +  int val = Serial.read();​ // lese das erste Zeichen in der Warteschlange und speichere es in der Variable '​val'​ zwischen 
 +  if (val == '​H'​) { // Wenn das Zeichen den Wert '​H'​ hat... 
 +    digitalWrite(ledPin,​ HIGH); // schalte eine LED an 
 +  }  
 +  else { 
 +    digitalWrite(ledPin,​ LOW); // wenn es irgendein anderes Zeichen ist, schalte die LED aus. 
 +  } 
 +
 +... 
 +</​code>​ 
 +===== Erweiterung auf mehrere ​Befehle mit switch/case (verschiedene ​LEDs anschalten) ===== 
 +Sollen mehr als zwei unterschiedliche Befehle erkann werden können, so geht das am einfachsten mit dem ''​switch/case''​. Die Sendeseite funktioniert ganz genau so wie in ''​libraries/​Serial/​SimpleWrite'',​ nur dass eben mehrere unterschiedliche Zeichen gesendet werden können. 
 + 
 +Für die Arduino/ Empfängerseite gibt es ein gutes [[http://​www.arduino.cc/​en/​Tutorial/​SwitchCase2|Beispielprogramm ''​control/​switchCase2''​ aus dem Arduino IDE]], aus dem ich hier (mit deutschen Kommentaren) zitiere: 
 + 
 +<code Java> 
 +  if (Serial.available() > 0) { // Wenn Daten angekommen sind... 
 +    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. 
 +    case '​a': ​                  // wenn dieser das Zeichen '​a'​ ist... 
 +      digitalWrite(2,​ HIGH); ​   // ... dann schalte den pin 2 auf 5V   
 +      break; ​                   // Ohne '​break'​ würde das Programm auch den nächsten Teil ausführen, obwohl kein '​b'​ kam. (beliebter Fehler) 
 +    case '​b': ​                  // alle anderen Buchstaben funktionieren genauso wie '​a',​ nur passiert eben als Reaktion etwas anderes. 
 +      digitalWrite(3,​ HIGH); 
 +      break; 
 +    case '​c': ​    
 +      digitalWrite(4,​ HIGH); 
 +      break; 
 +    case '​d': ​    
 +      digitalWrite(5,​ HIGH); 
 +      break; 
 +    case '​e': ​    
 +      digitalWrite(6,​ HIGH); 
 +      break; 
 +    default: ​              //​wenn das Zeichen keinem der oben überprüften entspricht, passiert das Folgende: 
 +      // Schalte die Spannung an allen Pins aus. 
 +      for (int thisPin = 2; thisPin < 7; thisPin++) { 
 +        digitalWrite(thisPin,​ LOW); 
 +      } 
 +    }  
 +</​code>​ 
 +===== Ü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?"​).  
 + 
 +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). 
 + 
 +//​**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: 
 +<code C++> 
 +  if (Serial.available() > 0) { // Wenn Daten da sind... 
 +    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. 
 +    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 ) 
 +      digitalWrite(directionPinRight,​inValue>​0);​ // stelle den Motor auf '​vorwärts',​ wenn der wert größer 0 ist, sonst auf rückwärts 
 +      analogWrite(throttlePinRight,​ inValue); ​   // ... gib genau so viel Gas, wie gewünscht. 
 +      break; ​                   // höre hier auf. 
 +      } 
 +    case '​l': ​                  // ..links genauso: 
 +      { 
 +      int inValue=Serial.parseInt(); ​            // dann lies erstmal eine Zahl ein (wenn irgendetwas anders kam, ist das Ergebnis 0 ) 
 +      digitalWrite(directionPinLeft,​inValue>​0); ​ // stelle den Motor auf '​vorwärts',​ wenn der wert größer 0 ist, sonst auf rückwärts 
 +      analogWrite(throttlePinLeft,​ inValue); ​    // ... gib genau so viel Gas, wie gewünscht. 
 +      break; ​                   // höre hier auf. 
 +      } 
 +    default: // bei uns unbekannten Kommandos machen wir einfach garnichts... 
 +      break;  
 +   } 
 +</​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.1413454705.txt.gz · Zuletzt geändert: 2016/01/21 12:45 (Externe Bearbeitung)