2016-04-15 32 views
0

Ich habe versucht, einen Arduino Servo mit der Geschwindigkeit des Autos aus dem Spiel "Assetto Corsa" zu aktivieren. Ich habe es geschafft, die Live-Daten aus dem Spiel mit Shared Memory zu extrahieren und versuche, es über den seriellen Port zum Arduino zu senden.Extrahieren von Informationen aus einer Zeichenfolge

Ich habe es noch nicht geschafft, die tatsächliche Geschwindigkeit des Autos auf dem Servo darzustellen, und ich frage mich warum. Ich bin ziemlich sicher, dass das Problem von dem Arduino Code kommt, ich kann die Geschwindigkeit des Autos extrahieren, aber ich bin unsicher, wie man es richtig benutzt. Vielleicht könntest du helfen?

Dies ist der Arduino Code-Extrakt:

char inData[8];  
char inChar; // Where to store the character read 
byte index = 0; // Index into array; where to store the character 
int angle = 0; 
int newAngle = 0; 
int MaxChars = sizeof(inData); 
char ch; 


     while (Serial.available()) 
     { 
     char ch = Serial.read(); 
     Serial.write(ch); 
     if (index < MaxChars && isDigit(ch)) 
     { 
      inData[index++] = ch; 
     } 
     else 
     { 
      inData[index] = 0; 
      newAngle = atoi(inData); 
      Serial.write(newAngle); 
      if (newAngle > 0 && newAngle < 180) 
      { 
      if (newAngle < angle) 
       for (; angle > newAngle; angle -= 1) 
       { 
       myServo.write(angle); 
       } 
      else 
       for (; angle < newAngle; angle += 1) 
       { 
       myServo.write(angle); 
       } 
      } 
      index = 0; 
      angle = newAngle; 
      delay(1000); 
     } 
     } 

Und das ist der Code, den ich Informationen aus dem Spiel zu extrahieren bin mit und an den Arduino senden:

while (true) 
{ 

    snprintf(Data, sizeof(Data)-1, "%3.3f", pf->speedKmh); 

    SP->WriteData(Data, sizeof(Data));    

    std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 

    int readResult = SP->ReadData(inData, sizeof(inData)); 

     printf("\t Bytes read: %i\n",readResult); 

     for (int i = 0; i < sizeof(inData); i++) 
     { 
      printf("%i", inData[i]); 
      inData[i] = 0; 
     } 
} 

Output screenshot: 1

Dies ist ein Screenshot des Echos von

Serial.write(NewAngle); 

Ich habe in gelb die Geschwindigkeit des Autos umrissen. Meine Frage ist: Wie extrahiere ich diese Geschwindigkeit von den Daten, die ich erhalte, um sie mit dem Arduino Servo zu benutzen?

Vielen Dank!

---------- ---------- UPDATE

Es funktioniert! Vielen Dank, das ist, was ich geändert:

snprintf(Data, sizeof(Data)-1, "%3.3f", (int)(pf->speedKmh)*1.0); 

Casted die Geschwindigkeit in einen int und multipliziert mit 1,0. Das scheint den Trick geschafft zu haben! Es ist ein weiterer Fall von "Weiß nicht, warum es nicht funktioniert, etwas ändern, weiß nicht, warum es funktioniert!"

+0

Was ist der Inhalt von 'inData'? Was ist Art und Wert von newAngle? Was ist die erwartete Ausgabe (und können Sie die tatsächliche Ausgabe stattdessen als Text kopieren und stattdessen als Bild einfügen)? –

+0

@JoachimPileborg 'inData' empfängt was ' WriteData' Sendet dazu. Die dafür verwendete Bibliothek finden Sie [hier] (http://playground.arduino.cc/Interfacing/CPPWindows). Ich habe den Beitrag bearbeitet, um die Variablendeklarationen des Arduino-Codes aufzunehmen. Ich bin nicht sicher, wie man die Textausgabe erhält, deshalb habe ich einen Screenshot gemacht:/ – Frazic

+0

Die Shared Memory Library, die ich verwendet habe, um die Daten zu extrahieren, kann [hier] gefunden werden (http://www.assettocorsa.net/forum /index.php?threads/shared-memory-reference-31-03-2016.3352/) – Frazic

Antwort

2

Das Hauptproblem ist, dass diese kurzen "Nachrichten" (nur eine Nummer) keine Rahmen haben. Eine Verzögerung oder ein Schlaf zählt nicht als Framing, weil die Zeiten des Systems nicht synchronisiert sind.

Ich würde vorschlagen, eine neue Zeile zwischen Zahlen, so dass Sie sagen können, wo eine Nummer endet und die nächste beginnt. Und achten Sie auf Unterschiede in '\ n' auf den beiden Systemen ... Sie könnten explizit eine (char)10 oder (char)13 senden und auf das gleiche Byte im Empfänger achten. Wenn ein Zeichen gelöscht wird, ermöglicht das Framing die Synchronisierung der Nachrichtengrenzen. Dadurch können Sie auch die delay auf der Arduino-Seite beseitigen, eine sehr gute Sache.

Ein mögliches Problem ist hier:

if (index < MaxChars&& isDigit(ch)) 
{ 
    inData[index++] = ch; 
} 
else 
{ 
    inData[index] = 0; 

Der Test index < MaxChars-1 sein sollte, weil Sie ein weiteres Zeichen für NUL Beendigung hinzuzufügen.

Beim Drucken der empfangenen Bytes auf der xbox, sollten Sie ein Trennzeichen zwischen Array-Elementen setzen: printf("%i,",inData[i]) Die Zahlen Sie freuen konnte eine 2 und eine 3 oder eine 23 oder ein 238 sein.

I kleine Änderung Ich würde vorschlagen: Sie senden einen Gleitkommawert, aber dann konvertieren Sie die empfangene Zeichenfolge (nach dem Anhalten bei Nicht-Ziffern) in eine Ganzzahl mit atoi. Beim nächsten Durchlauf erhalten Sie die Zeichen, die Sie noch nicht gelesen haben. Sie können den Wert auch als Ganzzahl senden: (int)(speed*100.0). Dies vermeidet auch zwei andere Probleme:% f3.3 wird mit Leerzeichen aufgefüllt, wenn die Geschwindigkeit < 100.0 (der Arduino sucht nicht nach diesen); und Bruchteile der Geschwindigkeit werden abgeschnitten.

+0

index

+0

In Bezug auf die Gestaltung haben Sie Recht. Ich würde sogar noch weiter gehen und die Zahl zwischen "<' and '>" -Zeichen setzen und alles ignorieren, was nicht so eingerahmt ist. –

+0

Hallo! Danke für die Antwort! Obwohl ich nicht alles verstanden habe hilft es ein bisschen ^^. Hättest du irgendwelche Tipps, wie man die Zeichenkette "zerlegen" kann, sobald sie auf dem Arduino ankommt, um nur die Zahl zu behalten, die die Geschwindigkeit darstellt? – Frazic

Verwandte Themen