www.mikrocontroller.net

Forum: PC-Programmierung [Visual Basic] Komischer Fehler beim empfangen eines Strings über COM


Autor: Benji Bone (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Ich habe ein ein problem mit folgenden Programmteil:

Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As 
System.IO.Ports.SerialDataReceivedEventArgs) Handles 
SerialPort1.DataReceived

        Control.CheckForIllegalCrossThreadCalls = False
        Dim data, zwischen As String
        data = SerialPort1.ReadExisting()
        SerialPort1.DiscardInBuffer()

        'Empfangene Daten auswerten:
        If data.Contains("L1Value") Then
            data = data.Remove(0, 7)
            data = CInt(data)
            zwischen = data   'nur zum debuggen
            TrackBarL1.Value = data
            Label1.Text = data * 10 & " %"
        End If
     End Sub

Ich werte einen String aus der über die serielle SChnittstelle empfangen 
wird. Und zwar erstmal nur für ein Objekt, d.h. die If-Anweisung könnte 
man auch erstmal weglassen.

Das Problem ist nun folgendes:
Der String der empfangen wird lautet "L1Value" direkt gefolgt von einer 
Zahl 0 bis 10. Also z.B. L1Value9 oder L1Value10
Ich scheide dann L1Value vom String ab und weise die Zahl einem Label 
und Trackbar zu. Das klappt eigentlich ganz gut nur funktioniert es 
nicht richtig mit dem String "L1Value10"! data hat nach dem Scneiden den 
Wert 1!
Es funktioniert nur einmal wenn der erste String der nach dem 
programmstart gesendet wird "L1Value10" ist. Nur dann übernimmt das 
Programm die 10.

???

Ich verstehe das nicht. Bin auch noch Anfänger mit Visual Basic (2005)

Autor: juppi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was passiert bei z.B. 11-21

"L1Value11"-"L1Value21"

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schalte mal in den Projektoptionen "Option Strict" auf "On", korrigiere 
alle Fehler und poste den Code noch mal. Möglicherweise funktioniert es 
dann bereits.
Zeilen à la "data = CInt(data)" sind jedenfalls relativ sinnfrei. Damit 
wandelst du den Inhalt des Strings "data" erstmals explizit in einen 
Integer um und gleich anschliessend implizit wieder in einen String.

Autor: Mario Richter (mario001) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du machst da einen "threadübergreifenden Zugriff", das bedeutet, diese 
Verarbeitungsroutine für die serielle Schnittstelle ist in einem anderen 
Thread beheimatet als das Steuerelement, auf das du die Werte zuweist.

Das klingt erstmal komisch, aber ich hatte ein ähnliches Problem auch 
schon mal und das generierte die verrücktesten Fehler. Setze mal 
"Control.CheckForIllegalCrossThreadCalls" auf True (oder kommentier die 
Zeile aus), und du wirst sehen dass VB bei der Ausführung da eine 
Exception wirft !!

Eine Lösung fand ich im MSDN, die sollte dir auch weiterhelfen:
-> http://msdn.microsoft.com/de-de/library/ms171728.aspx

Hth, Mario

Autor: Benji Bone (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@juppi
>Was passiert bei z.B. 11-21

>"L1Value11"-"L1Value21"

Weiss nicht, kommt doch gar nicht vor dass ich was subtrahiere. ???

@Philipp
>Zeilen à la "data = CInt(data)" sind jedenfalls relativ sinnfrei. Damit
>wandelst du den Inhalt des Strings "data" erstmals explizit in einen
>Integer um und gleich anschliessend implizit wieder in einen String.

Aber wieso kann ich dem TrackBarL1.Value einen String zuweisen, wenn der 
doch als Integer definiert ist?

>"Option Strict" auf "On"
Was bedeutet das? Wo stelle ich das ein?

@Mario

Was soll es mir bringen den Wert wieder auf True zu setzen, außer dass 
es dann überhaupt nicht mehr geht?

Autor: Mario Richter (mario001) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du die Option "CheckForIllegalCrossThreadCalls" auf False stellst, 
dann UNTERDRÜCKST du eine Fehlermeldung über einen unzulässigen Vorgang. 
Und offensichtlich hat dein Programm genau an der Stelle ein Problem !

Ich mach dir nen Vorschlag: Du schreibst dein Programm um, so wie ich's 
dir gleich zeige. Wenn es dann geht, gibste mir - virtuell - einen aus, 
wenn nicht, dann nehm ich alles zurück und behaupte das Gegenteil, ok ?

Also, mach das ganze mal so:
Private Sub DeineDatenEmpfangsRoutine(...)

  ' Folgende Zeile auskommentieren (Überprüfung an)      
  ' Control.CheckForIllegalCrossThreadCalls = False

  Dim data, zwischen As String
  data = SerialPort1.ReadExisting()
  SerialPort1.DiscardInBuffer()

  'Empfangene Daten auswerten:
  If data.Contains("L1Value") Then

    data = data.Remove(0, 7)
    data = CInt(data)
    zwischen = data   'nur zum debuggen

    'TrackBarL1.Value = data
    'Label1.Text = data * 10 & " %"
    ' das wird ersetzt durch:
    SetTrackBarAndLabel(data)

  End If
End Sub

' Delegate für SetTrackBarAndLabel (nötig für asynchrone Calls)
Delegate Sub SetTrackBarAndLabelCallback(data As String)

' Und hier die Sub, die threadsicher TrackBar und Label updatet
Private Sub SetTrackBarAndLabel(ByVal data As String)

  If TrackBarL1.InvokeRequired Then
    Dim d As New SetTrackBarAndLabelCallback(AddressOf SetTrackBarAndLabel)
    Me.Invoke(d, New Object() {data})
  Else
    TrackBarL1Value = data
    Label1.Text = data * 10 & " %"
  End If

End Sub

Eigentlich solltest du noch checken, ob "data" wirklich eine Zahl ist, 
bevor du es auf TrackBar und Label loslässt ...

Viel Erfolg, Mario

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benji Bone wrote:
> @Philipp
>>Zeilen à la "data = CInt(data)" sind jedenfalls relativ sinnfrei. Damit
>>wandelst du den Inhalt des Strings "data" erstmals explizit in einen
>>Integer um und gleich anschliessend implizit wieder in einen String.
>
> Aber wieso kann ich dem TrackBarL1.Value einen String zuweisen, wenn der
> doch als Integer definiert ist?

Es ist durch die implizite Konvertierung möglich. "data" wird in einen 
Integer umgewandelt und dann zugewiesen, aber du hast keine Kontrolle 
darüber. Ausserdem ist es einfach nicht schön.

>>"Option Strict" auf "On"
> Was bedeutet das? Wo stelle ich das ein?

"Option Strict On" bedeutet, dass sich der Code genau an die Regeln 
halten muss, implizite Konvertierungen und solche "Unschönheiten" werfen 
dann einen Fehler. Gibt zwar mehr Schreibarbeit, ist aber weniger 
fehleranfällig. Die Einstellung findest du unter 
Project->Options->Compiler oder sowas...

Autor: Benji Bone (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Mario

Ich habe deinen Code mal eingefügt, aber es funktioniert immer noch 
nicht richtig. :-( Schade, ich hätte dir sehr gerne einen ausgegeben...
Was mir auffällt ist, dass das Programm anscheinend nur die erste Ziffer 
nach "L1Value" beachtet. Ich kann nämlich anhängen was ich will, ohne 
dass es Auswirkungen hat. Ich schicke z.B. "L1Value89384" dann geht die 
TrackBar auf 8 bzw. Label: 80%, bei "L1Value10000" oder "L1Value18373" 
auf 1 bzw. Label: 10%.

???

Autor: Mario Richter (mario001) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade, hätte wetten können dass es das ist ! Zumal du sagst, dass es 
beim ersten Mal immer klappt ...

Versuch doch mal das Problem weiter einzukreisen und finde raus, welcher 
Befehl nicht das tut was er soll.

Autor: Benji Bone (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das Problem mit

data = SerialPort1.ReadLine()

gelöst. Am Ende des Strings muss man noch ein LF dran hängen und schon 
klappts. :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.