Go Down

Topic: Problem mit Datenübertragung zum PC (Read 1 time) previous topic - next topic

Se11001

Hallo,

ich stehe bei meinem Projekt derzeit vor einem Problem, das ich nicht lösen kann.

Zuerst einmal die prinzipielle Aufgabe des Arduino bei meinem Projekt:
Ich will damit Digital- und Analogwerte von einem Pult an den PC schicken, als auch Daten an das Pult schicken, um diese dort als Digital- oder Analogwert auszugeben. Dafür schicke ich 4 Byte vom Pult zum PC, und ca. 8 Byte vom PC zum Pult. Als Schnittstelle am PC dient ein VB Programm, welches die Werte für das Pult von einem TCP-Server bezieht, für das Problem aber gar nicht ausschlaggebend. Ich erstellte zu Beginn ein Programm, das die Werte nur zum Pult schickte, und zwar immer dann, wenn die Werte von der TCP Verbindung aktualisiert wurden. Das funktionierte ganz Ok, nur brachte dieses nicht genau festlegbare Intervall mit sich, dass das Programm am PC bei Übertragung in beide Richtungen nicht stabil lief, da die Werte vom Pult zum PC immer genau alle 200ms gesendet wurden (Timer im VB Programm.) Ich vermute mal dass sich aufgrund der nicht synchronisierten Intervalle der Puffer füllte.
Um dieses Problem zu umgehen, wollte ich die Kommunikation nun in beide Richtungen vom Timer bestimmt ablaufen lassen. Dazu habe ich die Werte von der TCP Verbindung als Variablen gespeichert, um sie dann wenn sie gebraucht werden, zu übertragen. Nun allerdings kann ich zwar Daten vom Arduino zum PC übertragen, das auch stabil, jedoch funktioniert die Übertragung in die andere Richtung nicht mehr - die Routine zur Verbindungsherstellung ist jedoch in beide Richtungen dieselbe.

Ich hoffe die Problematik ist grundsätzlich verständlich, hier nun der VB - und Arduino Code:



Als erstes stelle ich eine Verbindung her, welche vom Arduino auch erfolgreich mit "ready" bestätigt wird:
VB:
Code: [Select]

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If Serial.IsOpen
            Serial.WriteLine("oo")      '"oo" für "output"
            System.Threading.Thread.Sleep(50)

Arduino (in Loop):
Code: [Select]

 
   if (inputChar[0]=='o'){                    // Der PC will Werte zum Arduino ausgeben, es wird mit "ready" bestätigt
   Serial.println("ready");   
   if (inputChar[1]=='o')

Die letzte if Bedingung wird auch erfüllt, das konnte ich bereits herausfinden. Nun sollen die Daten übertragen werden, in derselben Struktur wie es schon erwähnt bei direkter Übertragung beireits funktioniert hat - nur dass sie eben nicht direkt von der TCP Verbindung aus gesendet werden, sondern vorher in Variablen gespeichert wurden.
An der Speicherung der Werte dürfte es aber auch nicht liegen, ich habe auch schon versucht anstatt der gespeicherten Werte direkt Zahlen mit CByte(<zahl>) zu übertragen, auch erfolglos.

Damit der Arduino die Bytes unterscheiden kann, schicke ich als erstes einen Buchstaben zur Identifikation, anschließend die Information selbst. Also hier der Übertragungsteil im VB Programm:
Code: [Select]

            If Serial.ReadLine() = "ready" & System.Text.Encoding.UTF8.GetString({13}) Then

                OutChar(0) = 86     'V  Der Buchstabe der Variable wird an den Arduino gesendet, damit er weiß was kommt.
                OutChar(1) = V      'Der gespeicherte Wert wird gesendet
                Serial.Write(OutChar, 0, 2)

                OutChar(0) = 80     'P
                OutChar(1) = Lm1
                Serial.Write(OutChar, 0, 2)

                OutChar(0) = 72     'H
                OutChar(1) = H
                Serial.Write(OutChar, 0, 2)

                ....

            End If

...und zum Empfang der Daten im Arduino Programm:
Code: [Select]

  {
 
  if (inputChar[0] == 'V'){                  // "V" für Geschwindigkeit
    n=2*inputChar[1];
    periode=speed[n];                        // Aus dem Array "speed" wird die entsprechende Periodendauer für die aktuelle Geschwindigkeit gewählt
  }
 
  if (inputChar[0] == 'P'){                  // "P" für PZB, stellvertretend für alle Leuchtmelder
  LmPZB(inputChar[1]);                       // Funktion siehe unten
  } 


Dasselbe noch für die Übertragung zum PC - hier funktioniert alles einwandfrei und die Daten kommen auch beim PC an:
Code: [Select]

            'Einlesen der Werte vom Arduino

            Serial.WriteLine("ii")      '"ii" für "input"
            System.Threading.Thread.Sleep(50)
            If Serial.ReadLine() = "readytosend" & System.Text.Encoding.UTF8.GetString({13}) Then

Ist eine Verbindung da, werden die 4 Bytes vom Arduino eingelesen:
Code: [Select]


                INa = Serial.ReadByte() 'Byte 0 - Digitaleingabe I
                INb = Serial.ReadByte() 'Byte 1 - Digitaleingabe II
                INc = Serial.ReadByte() 'Byte 2 - Analogwert Fahrschalter
                INd = Serial.ReadByte() 'Byte 3 - Analogwert FbV


Zusätzlich noch die Ausgbe am Bildschirm:
Code: [Select]

                Byte1.Text = INa
                Byte2.Text = INb
                Byte3.Text = INc
                Byte4.Text = INd         'Ausgabe am Bildschirm FbV



Ich hoffe es kennt sich hier jemand auch in VB aus und kann mir bei der Problematik behilflich sein - wie gesagt, ich kann mir nicht erklären, wieso keine Daten übertragen werden können.


Gruß,
Se11001

michael_x

Da du nur Schnipsel postest, liegt die Vermutung nah, dass das Problem in dem Teil ist, der fehlt ;)
--> Sicher, dass alle Zeichen in deinem inputChar array sind ?

Quote
da die Werte vom Pult zum PC immer genau alle 200ms gesendet wurden (Timer im VB Programm.) Ich vermute mal dass sich aufgrund der nicht synchronisierten Intervalle der Puffer füllte.
Um dieses Problem zu umgehen, wollte ich die Kommunikation nun in beide Richtungen vom Timer bestimmt ablaufen lassen. Dazu habe ich die Werte von der TCP Verbindung als Variablen gespeichert, um sie dann wenn sie gebraucht werden, zu übertragen. Nun allerdings kann ich zwar Daten vom Arduino zum PC übertragen, das auch stabil, jedoch funktioniert die Übertragung in die andere Richtung nicht mehr - die Routine zur Verbindungsherstellung ist jedoch in beide Richtungen dieselbe.


So ganz klar ist mir die Problembeschreibung allerdings nicht:
Was meinst du mit "Verbindung herstellen" ?
   Serial.Open in VB ?

Oder dass genau dieses If erfüllt ist ?
If Serial.ReadLine() = "ready" & System.Text.Encoding.UTF8.GetString({13}) Then

Quote

println()

Description

Prints data to the serial port as human-readable ASCII text followed by a carriage return character (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n'). This command takes the same forms as Serial.print().


Holst du auch das '\n' 10 ab ?

Warum hast du keinen Fehlerhinweis im Else zu diesem If ?

Ganz generell:
Deinen Verdacht auf Pufferüberlauf mit einem starren Timer anzugehen verstehe ich übrigens nicht.
Bei so schönen Dialogen zwischen den zweien ...

Ich versteh das so, dass der PC in beiden Richtungen als Master fungiert, und entweder Werte sendet oder eine Antwort haben will.
Wie synchronisieren sie sich eigentlich, wenn das Ganze ausser Tritt geraten ist ?

Hast du auch einen Test-Modus, der nicht alle 200ms was rausballert, und statt dessen auf dem PC anzeigt, was gesendet wurde und was empfangen wurde ?

Se11001

Hallo nochmals!

Da beide Programme relativ lang sind, habe ich mal nur ein paar Schnipsel gepostet, es sind jetzt aber beide Codes im Anhang.


Die Oberfläche des VB Programms sieht folgendermaßen aus:

Die eingelesenen Bytes werden direkt auf der rechten Seite angezeigt, und nehmen auch die Werte an, die vom Pult kommen.

Quote

Oder dass genau dieses If erfüllt ist ?
If Serial.ReadLine() = "ready" & System.Text.Encoding.UTF8.GetString({13}) Then

Das meinte ich damit, die Verbindung an sich wird ja erfolgreich hergestellt und läuft auch stabil. (in die eine Richtung)
Da die Verbindungsaufbau ja beim Einlesen der Werte und beim Verbinden des Arduinos nach dem verwendeten Prinzip ja funktioniert (lediglich mit unterschiedlichen Zeichen), glaube ich nicht dass es am println() liegt.

Quote

Warum hast du keinen Fehlerhinweis im Else zu diesem If ?

Mache ich gleich!

Quote
Deinen Verdacht auf Pufferüberlauf mit einem starren Timer anzugehen verstehe ich übrigens nicht.
Bei so schönen Dialogen zwischen den zweien ...

War nur meine Vermutung, jedenfalls fror das Programm ein nach ein paar Sekunden und ich musste die USB Verbindung neu herstellen.


Quote
Hast du auch einen Test-Modus, der nicht alle 200ms was rausballert, und statt dessen auf dem PC anzeigt, was gesendet wurde und was empfangen wurde ?

Gut, ich kann mal versuchen anstatt des Timers eine Schaltfläche zu benutzen. Was empfangen wurde, wird ja bereits angezeigt.




michael_x

Code: [Select]
void serialEvent() {                        // Es sind Daten vom PC zugespielt worden
  for (byte i=0; i<2;i++){
    inputChar[i]=Serial.read();             // inputChar[0] Ziel und inputChar[1] Wert zuweisen
    delay(2);                               // Da es seine Zeit braucht, bis der PC alles sendet, wird zwischen den Bytes etwas abgewartet
  }
  Serial.flush();                           // Falls aus irgend einem Grund nun noch Daten im Lesepuffer sind, wird dieser gelöscht
}

Soviel ich weiss, ist das keine Interrupt-Routine, sondern kommt zwischen 2 loop() dran, hab ich aber selbst keine Erfahrung mit.

Serial.flush() hat übrigens nun eine andere Funktion ( man muss die Jungs einfach mögen ) als früher, und als in deinem Kommentar steht.

Du liest also immer 2 Buchstaben. Falls da irgendein unsynchroniserter Schrott kommt (irgendwann mal gekkommen ist ), wird das ohne Kommentar ignoriert
Aber wenn der PC nichts mehr sendet, sollte alles sich beruhigen und es danach wieder gehen.

Dein Sketch kann ja eine ganze Reihe von Funktionen, gehen denn alle ausser "oo" ?  Da ist in deinem Sketch in Zeile 130 aber auch offensichtlich was verloren gegangen ...

Se11001

Quote
Soviel ich weiss, ist das keine Interrupt-Routine, sondern kommt zwischen 2 loop() dran, hab ich aber selbst keine Erfahrung mit.

Ja, das hat mit dem Interrupt auch nichts zu tun.

Quote
Du liest also immer 2 Buchstaben. Falls da irgendein unsynchroniserter Schrott kommt (irgendwann mal gekkommen ist ), wird das ohne Kommentar ignoriert
Aber wenn der PC nichts mehr sendet, sollte alles sich beruhigen und es danach wieder gehen.

Naja, aber ich lese ja nur, wenn die Verbindung beidseitig bestätigt wurde und übernommen wird der Wert auch nur wenn als erstes Byte ein definierter Buchstabe kommt.


Quote
Dein Sketch kann ja eine ganze Reihe von Funktionen, gehen denn alle ausser "oo" ?

Ansonsten funktioniert eigentlich alles, es bedarf lediglich noch einer Anpassung; wenn denn einmal Daten übertragen würden.  :~


Quote
Da ist in deinem Sketch in Zeile 130 aber auch offensichtlich was verloren gegangen ...

Stimmt, im alten Sketch waren hier 2 Befehle vertauscht. War nicht die neueste Version, die ich vorhin angehängt habe.

Go Up