Forum: PC-Programmierung VB.net Darstellung von Daten RS232


von sauerbrunnen (Gast)


Lesenswert?

Hallo, ich versuche folgendes zu erreichen und habe folgende Probleme 
dabei:

Platine mit einem µC wird per USB-RS232 Umwandler an PC angeschlossen.

in VB.net wird ein Programm zur Kommunikation und Steuerung davon 
geschrieben.

Problem liegt beim lesen der Daten die die Platine sendet.

Per Timer wird der Status alle 1000 Millisekunden abgefragt. Dabei kommt 
einiges an Daten rein, und das eben immer wenn der Status abgefragt 
wird, also jede Sekunde, das muss so sein, weil gewisse Werte halbwegs 
in Echtzeit übermittelt werden müssen.

Gedacht (vom µC) ist die Darstellung in zwei Zeilen.
Das ganze kann dann so aussehen:

"-Netzbetrieb-
Aktive E/As: 02"

als Beispiel.

sooo, und genau hier liegt mein Problem. Das ganze soll in einer 
einfachen Textbox dargestellt werden.

Leider gibt es kein klares Zeilenende, sondern jedes "Paket" endet immer 
mit 03. Nun kommen aber pro Zeile gerne mal 2 Pakete, also 4 insgesamt.

Daher kann ich "ReadLine" schon mal nicht verwenden (oder?).

Allerdings beginnt jedes "Paket" mit eigener Start-Kennung.
In diesem Fall:
"05 09" = Beginn erstes "Paket" für die obere Zeile.
"05 01" = Beginn zweites "Paket" für die obere Zeile.

Dann ist alles für die obere Zeile vollständig.
BEIDE "Pakete" enden mit "03" -> ReadLine(03) ist daher nicht möglich 
(vermute ich).

Bei der zweiten Zeile ganz ähnlich...
Hier beginnt das erste Paket mit "02 0a" (Zufall dass 0a Linefeed ist? 
Wahrscheinlich nicht, aber "ReadLine" zusammen mit
1
SerialPort1.NewLine = Chr (10)
 funktioniert nicht. Darstellung dennoch wie am Ende des Beitrags 
beschrieben)
und das zweite Paket der unteren Zeile beginnt mit "02 0d". Auch diese 
Pakete enden alle mit "03".

Folgendes habe ich bereits versucht:
1
Dim empfangsversuch As String 
2
        empfangsversuch = SerialPort1.ReadLine
3
        SerialPort1.NewLine = Chr(10) 'diese Zeile vor "ReadLine" setzen hilft auch nichts. Chr(10) sollte für dieses Format korrekt für "0a" / Linefeed sein.
4
        'TextBox1.Text = empfangsversuch

--> Form friert mit Beginn der Statusabfrage ein. Beim Debugging wird 
die "ReadLine" Zeile markiert und angezeigt "Der E/A-Vorgang wurde wegen 
eines Threadendes oder einer Anwendungsanforderung abgebrochen."

ebenfalls probiert: ReadExisting...
--> dann blitzen einzelne Teile des Empfangs kurz vorbei..man kann mit 
Glück dann kurz noch "Netzb" von "Netzbetrieb" lesen ;) Dann wird das 
schon vom nächsten Teil überschrieben.


Ich möchte noch anhängen dass ich maximal schlechte Grundkenntnisse im 
programmieren habe, ich hoffe mein Problem ist wenigstens verständlich.

Falls das eventuell hilfreich für eine Lösung sein könnte: Alle Pakete 
aller Zeilen haben immer die gleiche Länge...

Mein Ziel: Das Programm soll warten bis BEIDE Zeilen vollständig 
empfangen wurden, und die Daten erst dann in der Textbox aktualisieren, 
da die angezeigten Daten beider Zeilen je nach Menü-Option auch mal 
zusammen hängen.

Der Nutzer soll bestenfalls überhaupt keine kurzzeitig leere oder 
halbvolle Textbox sehen, sondern quasi ohne Übergang von

"-Netzbetrieb-
Aktive E/As: 02"

zu

"-Akkubetrieb-
Aktive E/As: 09"

Zudem frage ich mich, ob ich an der TextBox selbst etwas anpassen soll? 
Sie ist natürlich so groß dass die Daten für eine Zeile auch in die 
Zeile reinpassen...ReadOnly ist zu dem aktiv, da das nicht zum schreiben 
genutzt werden soll. Ansonsten habe ich da nichts weiter verändert.


Okay, langer Text...vielleicht hat ja jemand eine anfängerfreundliche 
Erklärung / Lösung für das Problem.

Vielen Dank bereits!

von Karl Klamson (Gast)


Lesenswert?

Anstatt strings zu senden könntest du dir ein besser zu parsendes 
Protokoll ausdenken und die strings in deinem VB Programm selber 
zusammen setzen.

Alternativ, wenn es wirklich strings seien müssen, alles in einen buffer 
packen und einem RegEx drüber laufen lassen

von Schlaumaier (Gast)


Lesenswert?

1. Benutze keine normale Textbox sondern eine Richtextbox.

2. mach dich mit den mit den Befehl DOEVENT vertraut. Erscheint bei VB 
erst nach Eingabe des 3 Buchstaben, ist sonst nicht in der Pull-Liste.

Ich würde EINE String  deklarieren.

Dann die Daten immer weiter dran hängen.

Dann den String in die Richtextbox übergeben und dann ein Doevent 
hinterher schicken.

Das zwingt das Prg. das Display neu aufzubauen.

Bei der Richtextbox gehen da in VB 2.147.483.647 Zeichen rein. Das ist 
ne Menge. ;)

Eine normale Textbox ist bei 32.767 Zeichen Schluss. Dann gibts ein 
Error.

Multiline muss bei dir auf TRUE stehen. !!!!

Beitrag #6981759 wurde von einem Moderator gelöscht.
von sauerbrunnen (Gast)


Lesenswert?

Danke erstmal für die Ideen.

Karl Klamson schrieb:
> alles in einen buffer
> packen und einem RegEx drüber laufen lassen

Wenn ich RegEx richtig verstehe müsste ich dann für jede mögliche 
Anzeige irgendwie Filter schreiben, das wären im meinem Fall 15 Menüs 
mit jeweils ca 10 Optionen...FALLS ich das mit RegEx richtig verstehe, 
wäre das also eher ungut.

Schlaumaier schrieb:
> mach dich mit den mit den Befehl DOEVENT vertraut.

Auch das klingt nach meinen ersten Google-Recherchen danach, dass ich 
dann quasi alle vollständigen Meldungen, die angezeigt werden könnten, 
in Klartext in den Code einbauen müsste, damit er beim empfangen quasi 
darauf wartet?
Das wäre ähnlich komplex wie bei der "RegEx"-Variante.

Schlaumaier schrieb:
> Ich würde EINE String  deklarieren.
>
> Dann die Daten immer weiter dran hängen.

Damit ich richtig verstehe: Das wäre ja dann der erste Teil von der 
oberen Zeile, den ich deklarieren und alles weitere dahinter hängen 
würde, nehme ich an...

Schlaumaier schrieb:
> Multiline muss bei dir auf TRUE stehen

das hatte ich im Beitrag vergessen, steht auf True.



Ich hatte gehofft es gibt die Möglichkeit immer ab einem bestimmten 
Zeichen (Beginn Zeile A erster Teil, Beginn Zeile B erster Teil) ab DANN 
auf eine bestimmte Anzahl Bytes zu warten, da die Nachricht immer gleich 
lang ist, und das dann entsprechend darzustellen.

Oder...die zweite Zeile beginnt ja mit "0a" (Linefeed) - könnte man VB 
da nicht irgendwie "sagen" dass alles VOR dem 0a in die erste Zeile, und 
alles danach in die zweite soll? BIS zum erneuten Start-Zeichen von der 
oberen Zeile dann wieder...

Oder irgendwie die Beginn-Zeichen der Zeilen rausfiltern und ihm sagen 
"alles nach [Startzeichen erste Zeile Teil A] in die erste Zeile BIS 
Linefeed 0a / Beginn zweite Zeile" und ab dann dann entsprechend wieder 
bis zum Startzeichen erste Zeile.


So einfach ist das wohl nicht möglich?

von Schlaumaier (Gast)


Lesenswert?

Ja + NEIN.

Man kann Doevent auch auf ein Objekt beziehen.

Dann wird nur das Objekt neu gemacht. Den Rest juckt das dann gar nicht.

Doevent verhindert sehr wirkungsvoll das die Meldung "Diese Anwendung 
hat keine Rückmeldung" von Windows selbst erscheint wenn man das Fenster 
anklickt.

OHNE doevent wird nämlich i.d.R. nix angezeigt im Fenster (Textfeld) 
solange das Programm arbeitet. Also auch keine Zähler.

Jedenfalls kenne ich keine andere Methode um ein Zähler in einen LABEL 
z.b. den Stand der Dinge anzuzeigen.

von Schlaumaier (Gast)


Lesenswert?

sauerbrunnen schrieb:
> Oder...die zweite Zeile beginnt ja mit "0a" (Linefeed) - könnte man VB
> da nicht irgendwie "sagen" dass alles VOR dem 0a in die erste Zeile, und
> alles danach in die zweite soll? BIS zum erneuten Start-Zeichen von der
> oberen Zeile dann wieder...

Brauchst du nicht.

Das Rich-Text-Feld erledigt den Job.

Public TX as String.


Sub lese_Daten

lauf = true

do while lauf = true
dim empfangene_daten as String

' hier Daten empfangen via Schnittselle und an den empfangene_daten 
übergeben


if len(empfangen_daten) = true then ' verhindert unnötige Leerzeilen
  tx = Tx + empfangen_daten ' falls CHR(13) erforderlich ist, hier 
einfach dazu machen)
  Rich_text_box.text = tx ' übergibt den ganzen Text an die Box.
  Rich_text_box.doevent ' * sieh unten
  empfangene_daten = "" ' leert den Empfangspuffer
end if

loop

end sub

Das sollte grob reichen.

* Refresh't die Anzeige  ansonsten erscheint das Ergebnis erst wenn die 
Sub beendet ist, oder das PRG anhält. Alternativ wenn es nicht 
funktioniert. my.application.doevent.  Das klappt immer.

Beitrag #6981803 wurde von einem Moderator gelöscht.
von bluppdidupp (Gast)


Lesenswert?

Kirlo schrieb im Beitrag #6981803:
> Mit einem Backgroundworker
+1
DoEvents() ist nahezu immer ein Zeichen für Pfusch.

ReadLine() blockiert den laufenden Thread standardmässig, bis entweder 
das eingestellte NewLine-Zeichen rein gekommen ist oder bis der (evtl.) 
konfigurierte Timeout fällig ist.
Wenn ReadLine() im Standard UI-Thread aufgerufen wird, blockiert man 
dadurch u.U. lange die Message-Loop des UI-Threads und Windows kann an 
das Fenster solange keine Messages (z.B. Maus-Klicks ins Fenster, 
Mausbewegungen, 'zeichne dich mal neu', etc) mehr zustellen und die 
Anwendung hängt dann praktisch durch das ReadLine() komplett und Windows 
hält die Anwendung dann für quasi tot und zeigt dann gerne auch das 
"reagiert nicht mehr" an, wenn man versucht mit der hängenden Anwendung 
zu interagieren.

Den SerialPort würde ich einfach in eigenem Thread (per BackgroundWorker 
z.B.) abfragen und da einfach in Schleife .Read() / .ReadByte() aufrufen 
und alles in einem Puffer sammeln, bis dein "03" da ist und dann den 
Puffer-Inhalt verarbeiten.

Vom Thread des BackgroundWorker aus kann man z.B. via dessen 
.ReportProgress() Inhalte an den UI-Thread/Form weitergeben oder per 
Invoke() der Form oder eines der Controls der Form auch Code im Context 
des UI-Threads ausführen - worüber dann die TextBox im UI-Thread 
aktualisiert werden kann.
(Was nötig ist, weil die Standard Controls unter Windows normalerweise 
nur von dem Thread aus angesteuert werden können/dürfen, von dem aus sie 
auch erstellt wurden)

von Karl K. (karlklamson)


Lesenswert?

sauerbrunnen schrieb:
> FALLS ich das mit RegEx richtig verstehe

Nein tust du nicht. Ein guter Ausdruck parst dir im optimalen Fall 
alles.
Alternativ statt die Informationen aus den Daten zu extrahieren, 
extrahierst du einfach nur den String raus und filterst damit deine 
Startkennung, etc. und alles was du nicht brauchst raus.

von sauerbrunnen (Gast)


Lesenswert?

Danke erneut für eure Ideen.

Schlaumaier schrieb:
> Das sollte grob reichen.

Da mir das mit meinem maximal schlechten Grundkenntnissen am einfachsten 
erschien, habe ich das mal ausprobiert...
1
     Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
2
        lauf = True
3
4
        Do While lauf = True
5
            Dim empfangene_daten As String
6
7
            empfangene_daten = SerialPort1.ReadExisting
8
9
            If Len(empfangene_daten) = True Then ' verhindert unnötige Leerzeilen
10
                TX = TX + empfangene_daten ' falls CHR(13) erforderlich ist, hier einfach dazu machen)
11
                RichTextBox1.Text = TX ' übergibt den ganzen Text an die Box.
12
                Application.DoEvents() ' ########Kann das funktionieren ohne explizit irgendwie auf die RichTextBox zu verweisen? richtextbox1.doevent hat nicht funktioniert.
13
                empfangene_daten = "" ' leert den Empfangspuffer
14
            End If
15
16
        Loop
17
18
    End Sub

Damit friert die Form aber beim Beginn des ganzen ein.

bluppdidupp schrieb:
> und alles in einem Puffer sammeln, bis dein "03" da ist

Das Problem ist ja, dass alle Datenpakete mit 03 enden. Die Zeile ist 
also beim ersten "03" maximal halb-fertig, oder es kommt mal zuerst ein 
Paket für die untere Zeile durch, das ebenfalls mit 03 endet...

bluppdidupp schrieb:
> Den SerialPort würde ich einfach in eigenem Thread (per BackgroundWorker
> z.B.) abfragen

Dämliche Frage - ist meine Abfrage (siehe Code oben) in einem eigene 
Thread?
1
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived

Sollte oben genanntes nicht funktionieren / umsetzbar sein, versuche ich 
mich nochmal mit RegEx zu befassen, wobei ich nicht weiß, wie ich das 
dann genau parse (alles nach den Start-Zeichen von allen Paketen für 
beide Zeilen jeweils bis zum "03" (damit endet ja "alles"), und dann 
noch entsprechend ausdrücken was mit welchem Startzeichen in welche 
Zeile soll). So ungefähr wahrscheinlich?

MFG

von ge-nka (Gast)


Lesenswert?

Du musst bei deiner RS232 Schnittstelle den Event suchen der ausgelöst 
wird wenn ein neuer Byte in das RS232 Register geschrieben wird.
In diesem Event dann den jetz-Byte und vorheriges-Byte prüfen ob das der 
Anfang einer Nachricht ist, und dann irgendwie so wie unten.
Das ganze soll Ereignisgesteuert bleiben damit das Programm alles nicht 
blockiert.
1
dim Buffer as string ' als globale variable
2
dim Nachricht as string ' als globale variable
3
dim Paket_1_1
4
dim Paket_1_2
5
dim Paket_2_1
6
dim Paket_2_2
1
sub event (jetz_Byte as string)
2
3
'Buffer sammeln
4
Buffer = Buffer & jetz_Byte
5
    'Wenn Buffer zwei Zeichen hat, Nachricht-Anfang suchen sonst Buffer löschen
6
    if Len(Buffer) = 2 then
7
    if Buffer="05 09" then
8
      Paket_1_1 = Buffer
9
    else if Buffer = "05 01" then
10
      Paket_1_2 = Buffer
11
    else if Buffer = "02 0a" then
12
      Paket_2_1 = Buffer
13
    else if Buffer = "02 0d" then
14
      Paket_2_2 = Buffer
15
    else 
16
      Buffer=""
17
    end if
18
  end if
19
20
  if Paket_1_1 <> "" then 
21
    'Das Ende der Nachricht suchen, der Buffer wird immer weiter gespeichert. Evtl die Prüfung für max. Länge einbauen dami es nicht ganze ewigkeit auf das Ende wartet.
22
    if jetz_Byte = "03" then
23
      Nachricht = Buffer
24
        'jetzt Nachricht in die Textbox schreiben
25
      Buffer = ""
26
      Paket_1_1 = ""
27
    end if
28
  end if
29
30
  if Paket_1_2 <> "" then 
31
    if jetz_Byte = "03" then
32
      Nachricht = Buffer
33
        'jetzt Nachricht in die Textbox schreiben
34
      Buffer = ""
35
      Paket_1_2 = ""
36
    end if
37
  end if
38
39
  if Paket_2_1 <> "" then 
40
    if jetz_Byte = "03" then
41
      Nachricht = Buffer
42
        'jetzt Nachricht in die Textbox schreiben
43
      Buffer = ""
44
      Paket_2_1 = ""
45
    end if
46
  end if
47
48
  if Paket_2_2 <> "" then 
49
    if jetz_Byte = "03" then
50
      Nachricht = Buffer
51
        'jetzt Nachricht in die Textbox schreiben
52
      Buffer = ""
53
      Paket_2_2 = ""
54
    end if
55
  end if
56
57
end sub

von Schlaumaier (Gast)


Lesenswert?

sauerbrunnen schrieb:
> Damit friert die Form aber beim Beginn des ganzen ein.

JA. Ist klar. Aber das  my.Applikation.doevent baut sie mit den Status 
des Aufrufes wieder auf.

For i = 1 to 100000
Label.text = str(i)
next i

Das einzige was du siehst ist die 100000. wenn er fertig ist mit zählen.

For i = 1 to 100000
Label.text = str(i)
my.Applikation.doevent
next i

Und du siehst ihn zählen. Zwar nicht jede Zahl dazu ist er zu schnell, 
aber die größeren Stellen schon.


DAS ist der Unterschied.
Du musst also jedesmal wenn das Rich_text_feld gefüllt wird, Refresh mit 
my.Applikation.doevent durchführen.

von Schlaumaier (Gast)


Lesenswert?

Der Code von  ge-nka ist fein.

Die App friert aber "gefühlsmäßig" !!!! ein.

Der Grund ist, das VB einfach keine Zeit für die Bildschirmausgabe 
zulässt.

Entweder du macht   nach  'jetzt Nachricht in die Textbox schreiben ' 
ein, my.Applikation.doevent oder du löst das durch einen Timer aus. Was 
dir lieber ist.


Kleiner Hinweis am Rande. my.Applikation.doevent löst nicht nur einen 
Neuzeichnen der Bildschirmausgabe aus, sondern auch die Ausführung eines 
STOP-Button.

z.b.

Während das Prg. läuft klickst du auf ein Button "Abbrechen". Da kannst 
du klicken bis die Maus put geht. Sobald du my.Applikation.doevent 
auslöst, wird auch die Sub des Button abgearbeitet.

Vielleicht hast du mal bei anderen Programmen auf "Abbrechen" geklickt 
und dich gewundert das keine Reaktion kam. Ist das selbe Problem.  Liegt 
in der Tiefe der Struktur von Windows begraben, und daran das das OS 
kein echtes Multi-Tasking kann bzw. zulässt. Ist halt viel aus der Win 
3.11 Zeit übernommen. Sonst wäre es möglich so ein Button auf einen 
eigenen Task zu legen und beide miteinander reden zu lassen.

Bei mein Amiga ging das damals sogar ;)

von tom (Gast)


Lesenswert?

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

Diese läuft in einem eigenen Thread. Bei jedem Event kannst du 
auswerten,
wie viele Bytes angekommen sind und diese lesen und dann auswerten. Oder 
auch eine Zeile lesen, wie du's halt brauchst.

An z.B. eine Textbox wirst du deine Daten dann über Invoke los:

           TextBox1.Invoke(Sub()
                           TextBox1.Text = "hallo" 'da natürlich die 
Daten
                            End Sub)

Dann blockiert auch nix.

von sauerbrunnen (Gast)


Lesenswert?

Sooo,

ge-nka schrieb:
> Du musst bei deiner RS232 Schnittstelle den Event suchen der ausgelöst
> wird wenn ein neuer Byte in das RS232 Register geschrieben wird.
> In diesem Event dann den jetz-Byte und vorheriges-Byte prüfen ob das der
> Anfang einer Nachricht ist, und dann irgendwie so wie unten.
> Das ganze soll Ereignisgesteuert bleiben damit das Programm alles nicht
> blockiert.

Erstmal vielen Dank für den ausführlichen Code, das ist ungefähr was ich 
mit im Kopf vorgestellt hatte, es aber nicht als Code ausdrücken konnte.

Nun habe ich folgenden Code:
1
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
2
3
        jetz_byte = SerialPort1.ReadExisting() 
4
5
   End Sub

und dann:
1
Private Sub Timer3_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer3.Tick
2
        'Buffer sammeln
3
        Buffer = Buffer & jetz_byte
4
        'Wenn Buffer zwei Zeichen hat, Nachricht-Anfang suchen sonst Buffer löschen
5
        If Len(Buffer) = 2 Then
6
            If Buffer = "05 09" Then
7
                Paket_1_1 = Buffer
8
            ElseIf Buffer = "05 01" Then
9
                Paket_1_2 = Buffer
10
            ElseIf Buffer = "02 0a" Then
11
                Paket_2_1 = Buffer
12
            ElseIf Buffer = "02 0d" Then
13
                Paket_2_2 = Buffer
14
            Else
15
                Buffer = ""
16
            End If
17
        End If
18
        If Paket_1_1 <> "" Then
19
            'Das Ende der Nachricht suchen, der Buffer wird immer weiter gespeichert. Evtl die Prüfung für max. Länge einbauen dami es nicht ganze ewigkeit auf das Ende wartet.
20
            If jetz_byte = "03" Then
21
                Nachricht = Buffer
22
                'jetzt Nachricht in die Textbox schreiben
23
                Buffer = ""
24
                Paket_1_1 = ""
25
            End If
26
        End If
27
        If Paket_1_2 <> "" Then
28
            If jetz_byte = "03" Then
29
                Nachricht = Buffer
30
                'jetzt Nachricht in die Textbox schreiben
31
                Buffer = ""
32
                Paket_1_2 = ""
33
            End If
34
        End If
35
        If Paket_2_1 <> "" Then
36
            If jetz_byte = "03" Then
37
                Nachricht = Buffer
38
                'jetzt Nachricht in die Textbox schreiben
39
                Buffer = ""
40
                Paket_2_1 = ""
41
            End If
42
        End If
43
        If Paket_2_2 <> "" Then
44
            If jetz_byte = "03" Then
45
                Nachricht = Buffer
46
                'jetzt Nachricht in die Textbox schreiben
47
                Buffer = ""
48
                Paket_2_2 = ""
49
            End If
50
        End If
51
52
        RichTextBox1.Text = Nachricht
53
        'Muss hier ein Timer.stop rein?
54
    End Sub
55
End Class


Im SerialPort_DataReceived habe ich
1
jetz_byte = SerialPort1.ReadExisting
 Erste Frag: Ist das korrekt? Der Code von ge-nka sammelt ja alles in 
einem Puffer, daher vermute ich dass hier erst mal alles eingelesen 
werden soll, also ReadExisting statt ReadLine o.ä.

Den Code mit dem Puffer (von ge-nka) habe ich in einen Timer gesetzt, 
welcher beim Verbinden gestartet wird, aus folgendem Grund:
1
sub event (jetz_Byte as string)
Löst einen Fehler aus: "Keyword is not valid as an identifiert", bezogen 
auf "event", ich habe es mit "[event]" versucht, dann kommen keine 
Fehler, aber es passiert auch nichts.

Wenn der Code im Timer steht, wird beim starten die Textbox gelceared, 
also der voreingestellte Text "Warten auf Verbindung..." verschwindet, 
mehr passiert aber noch nicht.

Daher folgende Fragen

ge-nka schrieb:
> if Paket_1_1 <> "" then
>     'Das Ende der Nachricht suchen, der Buffer wird immer weiter
> gespeichert. Evtl die Prüfung für max. Länge einbauen dami es nicht
> ganze ewigkeit auf das Ende wartet.

wie "suche" ich das Ende der Nachricht? Bis auf Ende-Kennung "03" ist 
alles andere ja je nach Daten immer unterschiedlich. Das ist die 
wichtigste Frage, weil es ohne wohl nicht geht.

ge-nka schrieb:
> Nachricht = Buffer
>         'jetzt Nachricht in die Textbox schreiben

Das habe ich so erledigt: Im Code von ge-nka steht ja bereits "Nachricht 
= Buffer", ich habe dann ganz am Ende in diesem Sub angehängt
1
RichTextBox1.text = Nachricht

Geht das so?

Danke für eure Geduld - ich komme dem Ziel näher...

von tom (Gast)


Lesenswert?

Das wird wohl so nicht funktionieren bzw. ist schlecht programmiert: Du 
hast dabei 2 Events, die ja fast gegeneinander arbeiten: Den Timer-Event 
und den SerialPort1_DataReceived-Event. Der 2. ist eigentlich das Mittel 
der Wahl, dann brauchst du keinen Timer. Oder doch über den Timer (das 
nennt man Polling), ist aber zumindest nicht elegant. Der 
SerialPort1_DataReceived kommt immer, wenn der µC was sendet (also eher 
in "Echtzeit"). Wenn der µC einen
String raushaut, dann steht der auch komplett im 
SerialPort1.ReadExisting() und du bist fertig. Wenn der einzelne Bytes 
schickt solltest du doch die Anzahl kennen. Wenn nicht brauchst du 
tatsächlich eine Logik zum zusammensammeln. Da ist Ende '03' aber 
gefährlich, eine 03 könnte ja auch mitten auf deinem String stehen.

von tom (Gast)


Lesenswert?

sauerbrunnen schrieb:
> Falls das eventuell hilfreich für eine Lösung sein könnte: Alle Pakete
> aller Zeilen haben immer die gleiche Länge...

Das hatte ich überlesen. Dann ist es doch einfach: überlasse dem Buffer 
des Ports das zusammensammeln: Wenn die Länge z.B. 10 ist

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

 If SerialPort1.BytesToRead < 10 Then Return
  Dim s as String =  SerialPort1.ReadExisting()
  ' s sollte jetzt 10 Bytes haben
  ' Diese nach deiner Logik in die 4 Fälle sortieren und mit Invoke
  ' auf den Text

 end if

Ein Problem könnte eventuell noch darin bestehen, dass der µC schneller 
sendet, als du liest - dann läuft der Eingabepuffer natürlich voll. Man 
sollte
also noch checken, ob SerialPort1.BytesToRead eventuell immer größer 
wird.

von tom (Gast)


Lesenswert?

Schau an, in der Eigenschaft 'ReceivedBytesThreshold' des SerialPort 
kannst du sogar einstellen, bei wieviel Bytes das 
SerialPort1_DataReceived ausgelöst wird. Da würde ich ja die Länge 
deines Strings nehmen. Man lernt nie aus....

von ge-nka (Gast)


Lesenswert?

Man soll ja auch nicht alles eins zu eins abkupfern was ich schreibe, 
das war ja ein Beispiel wie der Algorithmus sein soll.

Zu erst muss man eigentlich Byte für Byte abgreifen und einzeln prüfen.
Und das kannst du nur in:
1
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
2
        jetz_byte = SerialPort1.ReadExisting() 
3
End Sub

 machen.

Apropos "Event" ist ein reserviertes Wort für Compiler.

Klar, muss man diesen "Event" so kurz wie möglich halten, aber zum 
Anfang um Ergebnisse und Gefühl zu kriegen soll es reichen sind ja nur 
7-8 boolesche Prüfungen, und String zusammenbauen.
(richtig wäre da nur den Buffer füllen und in anderen Funktion, Buffer 
Byte nach Byte auswerten und Byte nach Byte leeren)

Zweitens du muss in klaren sein dass das was du in SerialPort kriegst 
ein Byte ist, also kein String, sondern ein ASII Zeichen mit Wert von 
0-255.

Ich kenne mich nicht besonders mit VB.net nicht aus, aber Grundlagen 
sind überall gleich.
Also muss du eigentlich mit einem Array arbeiten Buffer[] oder mit einem 
chr(xxx) das in ein String speichern, was natürlich schlecht zu debugen 
ist, da die Steuerzeichen nicht lesbar in einer Textbox sind.
(Die Zeichen mit den Codes 0-31 sind nicht darstellbare Zeichen. Sie 
werden auch als Steuercodes bezeichnet.)
1
If Buffer = "05 09" Then
2
ElseIf Buffer = "05 01" Then
3
ElseIf Buffer = "02 0a" Then
4
ElseIf Buffer = "02 0d" Then
soll dann dem entsprechend heißen:
1
If Buffer = chr(5) & chr(9) Then
2
ElseIf Buffer = chr(5) & chr(1) Then
3
ElseIf Buffer = chr(5) & chr(10) Then
4
ElseIf Buffer = chr(5) & chr(13) Then

usw.

von tom (Gast)


Lesenswert?

Veto!
SerialPort1.ReadExisting() liest den kompletten Puffer und liefert einen 
String.
Wenn du ein einzelnes Byte lesen willst dann mit SerialPort1.ReadByte()

von Schlaumaier (Gast)


Lesenswert?

ge-nka schrieb:
> If Buffer = "05 09" Then

Wenn du das machst läuft du gegen die wand. Grund :
1. Du analysierst einen 5 Bytes-String. Als einfaches Bla-bla.

Wenn du Zeichen analysieren willst musst du das SO machen. Dabei ist es 
völlig egal, welches Zeichen es ist. Ich habe de Routine unten, sogar 
schon für Hex-Files in angewandeter Form benutzt.

das musst du SO machen.

buffer$ = ganzer_buffer

gefunden_05 = false

for i = 1 to len(ganzer_buffer)
  tx$ = mid(buffer$,i,1)
  if tx$ = chr(05) and gefunden_05 = false then
   gefunden_05 = true
  else
    gefunden_05 = false
  end if

  if tx$ = chr(09) and gefunden_05 = true then
    ' mach hier was du sollst
    gefunden_05 = false
  end if
next i


So kann man ALLES Pharsen.

von tom (Gast)


Lesenswert?

VB.net erlaubt keine Deklaration mit $

Wenn man einen String (kein Byte-Feld) der Länge 5 hat kann man den 
natürlich vergleichen. Wenn man sich wie oben beschrieben den kompletten 
String holt kann man sich die Kennung mit
Dim kennung as String = Puffer.Substring(0, 5)
holen
Dann kann man sich die Parserei sparen.

von Schlaumaier (Gast)


Lesenswert?

tom schrieb:
> VB.net erlaubt keine Deklaration mit $

Sorry mein Fehler. VB-2010 ist das egal man darf es nur nicht mischen.

Dann mach halt

dim tx, buffer as string.


liegt an meiner Faulheit. ;) Ich habe mir angewöhnt vor vielen Jahren 
das $ bedeutet String. Und da VB-2010 das noch erlaubt .... ;)

Ich bekomme auch deshalb in B4X ärger, ist da mein Lieblingstippfehler 
;)

von Schlaumaier (Gast)


Lesenswert?

tom schrieb:
> Dim kennung as String = Puffer.Substring(0, 5)
> holen
> Dann kann man sich die Parserei sparen.

Kann man nicht.
1.) Weil wenn sich die Position des Suchstring verschiebt, wenn die 
Buffer_zeichenkette nicht immer genau gleich ist. ;)

2. Substring hat aber klein Parameter für binäre Vergleiche des 
Suchstring.


Substring ist hervorragend geeignet um Filenamen aus Pfadnamen zu holen, 
aber nicht um serielle Daten zu lesen.

https://docs.microsoft.com/de-de/dotnet/api/system.string.substring?view=net-6.0


Im Gegensatz zu INSTR Funktion.

https://docs.microsoft.com/de-de/office/vba/language/reference/user-interface-help/instr-function

Diese könnte man benutzen, müsste aber dann mit der Mid-Funktion, den 
String auseinander schneiden.

Geht mit den compare parameter, den man mit vbBinaryCompare angeben 
MUSS.

Ansonsten sind ALLE Vergleiche unter = Chr(31) falsch.

Weshalb ich meine Methode bevorzuge. Da ich damit weniger Aufwand habe.
Mid - Funktion liefert bei ungültigen Parametern ein Fehler. Ergo muss 
ich auch noch auf den Rest prüfen, was aufwendiger ist.

von tom (Gast)


Lesenswert?

Schlaumaier schrieb:
> Kann man nicht.
> 1.) Weil wenn sich die Position des Suchstring verschiebt, wenn die
> Buffer_zeichenkette nicht immer genau gleich ist. ;)
>
> 2. Substring hat aber klein Parameter für binäre Vergleiche des
> Suchstring.

Ich glaube, da hast du einen Denkfehler. Die Länge des Strings ist immer 
gleich - das war die Anforderung. Ich lese also immer einen STRING 
gleicher
Länge. In diesem Fall ist es also puppenleicht, parsen und binäre Suche 
kann man sich hierbei sparen.
OK, man muss natürlich sicher stellen, dass der String komplett von 
Anfang an ankommt. Wenn der IC schon feuert und man danach das 
VB-Programm startet könnte man Pech haben. Dann also entweder den Puffer 
leeren - oder doch parsen....

von Schlaumaier (Gast)


Lesenswert?

tom schrieb:
> Wenn der IC schon feuert und man danach das
> VB-Programm startet könnte man Pech haben. Dann also entweder den Puffer
> leeren - oder doch parsen....

OK. bei Perfekt gleicher Länge ist ein Pharser wie meiner Perlen vor die 
Säue das gebe ich zu.

Dann reicht auch

dim daten_im_buffer, teil_1 as string
dim lange_von_zeile as Integer = 10 ' 10 Zeichen lang, k.a.)
dim start as integer = 4 ' wo er anfangen soll zu trennen
dim lang as interger = 3 ' Anzahl der Zeichen die er ab Start lesen soll

if len(daten_im_buffer) = lange_von_zeile then
 Teil_1 = Mid(daten_im_buffer,start,lang)
else
  if len(Daten_im_Buffer > 0 then
    textbox_1.text ="Fehlerhafte Datenlänge empfangen, MACH WAS ;)"
  end if
end if


erinnert mich an Datenbankdateien im Textformat mit fester Feldgröße ;)
So was macht das Leben viel einfacher. Du MUSST aber die LEN-Abfrage 
machen, ansonsten ist beim 1. fehlenden Bytes ein Absturz zu erwarten.
MID-Funktion verzeiht keine Fehler.

von tom (Gast)


Lesenswert?

Schlaumaier schrieb:
> Du MUSST aber die LEN-Abfrage
> machen, ansonsten ist beim 1. fehlenden Bytes ein Absturz zu erwarten.
> MID-Funktion verzeiht keine Fehler.

Ich will ja nicht kleinlich sein - aber MID verzeiht gar nix mehr, 
gibt's im VB.NET auch nicht mehr (nur damit sauerbrunnen nicht 
verzweifelt). Statt dessen substring ;)

Die Überprüfung ist im Prinzip richtig - aber hier auch nicht nötig. 
Mein SerialPort1_DataReceived feuert ja genau nur dann, wenn die 
erwartete Anzahl Bytes da ist.

von Schlaumaier (Gast)


Lesenswert?

tom schrieb:
> aber MID verzeiht gar nix mehr,
> gibt's im VB.NET auch nicht mehr (nur damit sauerbrunnen nicht
> verzweifelt). Statt dessen substring ;)

Ich sollte mir diese nervigen Änderungen in VB.NET wirklich mal antun. 
;)

Aber wie ich mich kenne, würde ich unter VB.net nur die Mid-Funktion mir 
mal eben selbst schreiben. ;)

Wäre nicht die erste Funktion die ich mir nachbilde, weil die neuere 
Syntax mir auf den Sack geht.

tom schrieb:
> Die Überprüfung ist im Prinzip richtig - aber hier auch nicht nötig.
> Mein SerialPort1_DataReceived feuert ja genau nur dann, wenn die
> erwartete Anzahl Bytes da ist.

OK. Aber ich bin ein Feigling.

Und noch NIE wurde durch eins meiner Programme ein Explosit ausgelöst. 
Selber wenn der Compiler ein Fehler hatte. z.b. Das man ein Eingabefeld 
mit komischen Zeichen überlasten konnte.

Grund : Ich bin ein Feigling und fange auch mögliche Fehler ab, die es 
nicht geben darf.

von tom (Gast)


Lesenswert?

Schlaumaier schrieb:
> Grund : Ich bin ein Feigling und fange auch mögliche Fehler ab, die es
> nicht geben darf.

Super, dann bekommst du meine Programme jetzt immer zur Korrektur.
Ich bin Optimist und warte immer, bis der Anwender meckert ;)
Angenehme Nachtruhe.

@sauerbrunnen: Jetzt haben wir hier viel geschwafelt, Ideen entwickelt 
und verworfen. Siehst du noch durch oder läuft dein Programm etwa 
inzwischen schon?

von sauerbrunnen (Gast)


Lesenswert?

Erneut ein "soooo" !

Ich habe hier alles verfolgt und hatte heute Zeit, um zu testen...

Nachdem hier einiges vorgeschlagen, widerlegt, verworfen wurde, sieht 
mein Code aktuell so aus:
1
Private Sub Timer3_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer3.Tick
2
        jetz_byte = SerialPort1.ReadExisting()
3
        'Buffer sammeln
4
        Buffer = Buffer & jetz_byte
5
6
        If Len(Buffer) = 2 Then
7
            If Buffer = Chr(&H5) & Chr(&H9) Then
8
                Paket_1_1 = Buffer
9
            ElseIf Buffer = Chr(&H5) & Chr(&H1) Then
10
                Paket_1_2 = Buffer
11
            ElseIf Buffer = Chr(&H2) & Chr(&HA) Then
12
                Paket_2_1 = Buffer
13
            ElseIf Buffer = Chr(&H2) & Chr(&HD) Then
14
                Paket_2_2 = Buffer
15
                Buffer = ""
16
            End If
17
        End If
18
        If Paket_1_1 <> "" Then
19
            'Das Ende der Nachricht suchen, der Buffer wird immer weiter gespeichert. Evtl die Prüfung für max. Länge einbauen dami es nicht ganze ewigkeit auf das Ende wartet.
20
            If jetz_byte = Chr(&H3) Then
21
                Nachricht = Buffer
22
                'jetzt Nachricht in die Textbox schreiben
23
                Buffer = ""
24
                Paket_1_1 = ""
25
            End If
26
        End If
27
        If Paket_1_2 <> "" Then
28
            If jetz_byte = Chr(&H3) Then
29
                Nachricht = Buffer
30
                'jetzt Nachricht in die Textbox schreiben
31
                Buffer = ""
32
                Paket_1_2 = ""
33
            End If
34
        End If
35
        If Paket_2_1 <> "" Then
36
            If jetz_byte = Chr(&H3) Then
37
                Nachricht = Buffer
38
                'jetzt Nachricht in die Textbox schreiben
39
                Buffer = ""
40
                Paket_2_1 = ""
41
            End If
42
        End If
43
        If Paket_2_2 <> "" Then
44
            If jetz_byte = Chr(&H3) Then
45
                Nachricht = Buffer
46
                'jetzt Nachricht in die Textbox schreiben
47
                Buffer = ""
48
                Paket_2_2 = ""
49
            End If
50
        End If
51
52
        RichTextBox1.Text = Buffer


Geändert habe ich mein unsinniges "05 09" etc. zu
1
Chr(&Hx)

"Chr = xx" hat nicht funktioniert, da er das bei "02 0a", also dem Start 
von Zeile B nicht akzeptiert hat, beim senden verwende ich ebenfalls 
"&Hxx".

Außerdem habe ich
1
RichTextBox1.Text = Nachricht
 zu
1
RichTextBox1.Text = Buffer
 geändert, weil die Textbox leer blieb... bei " = Buffer" erscheinen nun 
Daten...nur nicht ganz so, wie erwünscht. Ich habe in den Properties vom 
SerialPort das "ReceivedBytesTreshold" auf 11 gestellt (so lange sind 
die Datenpakete).


--Nun bestehen noch folgende Probleme:--
 - Manchmal kommt zuerst ein Paket für die zweite Zeile an... es 
erscheint dann die LETZTE Hälfte vom Wort für die untere Zeile....ganz 
am Anfang in der oberen Zeile, alles andere wird dann ebenso unpassend 
angehängt.

- Es erfolgt eine neue Line obwohl die vorherige noch  nicht "voll ist". 
Also weder dass Längenmäßig der Platz in der Richtextbox fehlen würde, 
noch dass das der programmierte Beginn der neue Zeile ist.

- Es erscheinen in der Textbox noch Daten die gefiltert werden müssen. 
(alles was mit "02 85" beginnt, und ebenfalls mit "03" endet, dient 
einer Art Handshake oder Alive-Prüfung dem Programm, dass ursprünglich 
mit dem Gerät kommuniziert hat, das wird in VB als "?????" dargestellt, 
das muss ich noch ignorieren lassen. -> Diese Pakete sind kürzer als 
alle, die tatsächlich dargestellt werden sollen, vielleicht kann man das 
so einbauen.

- Meine Startzeichen aka "05 09" etc. sowie mein Ende "03" werden in der 
Richtextbox mit angezeigt... als eine Art "[]" nur dass es ein ganzes 
Zeichen ist. Hier mal als Copy paste (wird hier nicht richtig angezeigt) 
:

---> ich bin eigentlich davon ausgegangen dass das rausgefiltert wird, 
wenn es im Code als Start/Stopzeichen eingestellt ist...entweder dem ist 
nicht so, oder "mein" Code ist wirkungslos bisher, und das alles wird 
rein durch "ReceivedBytesTreshold" ausgelöst? Das werde ich Morgen bei 
Gelegenheit testen.


Dennoch....es geht voran...und falls nicht alle an meiner 
Ahnungslosigkeit verzweifeln, bekomme ich (wir) das ganze sicher noch 
fertig ;)

Danke!

Beitrag #6988395 wurde vom Autor gelöscht.
von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Wie oben schon gesagt, würde ich das mit einem regulären Ausdruck
rausfiltern, zumal ja auch nach Hex-Zahlen (\x..) gesucht werden
kann.
\x05\x09.....\x03
wobei die Punkte dazwischen das wirklich Gesuchte definieren.
Das mußt du also noch ergänzen, z.B. [0-9]{1,5} = alle 1 - 5stelligen
Zahlen. Dann halt vorne 2 und hinten 1 Zeichen abschneiden bzw.
mit LF ergänzen.
Geht ja gut mit der Mid und Len - Funktion.
Mid(buffer,3, Len(buffer) -1)
Mit der Länge (Len() mußt du ausprobieren. In meiner Sprache
muß ich 3 von Len() abziehen.

: Bearbeitet durch User
von tom (Gast)


Lesenswert?

Ich befürchte, mit dem Timer hast du dir unnötig viele Schwierigkeiten 
eingehandelt. Es ist hier völlig unklar, wie viele Bytes jeweils in 
einer
Sequenz ankommen. Die "ReceivedBytesTreshold" sind hier wirkungslos, 
damit wird eingestellt, bei wieviel Bytes der SerialPort_DataReceived 
ausgelöst wird (diesen Event würde ich wie gesagt deutlich bevorzugen).

Ich will das nochmal kurz verdeutlichen:
Wenn dein Timer sehr 'schnell' ist, dann wird in
jetz_byte = SerialPort1.ReadExisting()
genau ein Byte gelesen (mehr ist noch nicht angekommen) und der Puffer 
gelöscht. Danach liest du wieder 1 Byte.

Wenn dein Timer 'langsam' ist, dann liest du XX Bytes - also irgendeine 
Anzahl, die du dann parsen musst.

Ich würde also doch den SerialPort_DataReceived  bevorzugen. Da holst du 
immer 11 Bytes, fusselst deine Kennung auseinander, merkst dir deine 4 
Teiltexte auf 4 public shared strings, und wenn alle 4 einen Wert haben 
baust du deine beiden Texte zusammen und schreibst die mit Invoke auf 
die beiden Textboxen.

von tom (Gast)


Lesenswert?

versuch doch mal das:

Unter deiner Haupt-Klasse ('Form1')
    Public Shared Text11 As String = ""
    Public Shared Text12 As String = ""
    Public Shared Text21 As String = ""
    Public Shared Text22 As String = ""

Bei Initialisierung des Ports
    SerialPort1.ReceivedBytesThreshold = 11

und dann
    Private Sub SerialPort1_DataReceived(sender As Object, e As 
SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim Buffer = SerialPort1.ReadExisting()
        'Hier gehe ich von deinen ursprünglichen Kennungen aus
        Dim Kennung = Buffer.Substring(0, 5)
        If Kennung = "05 09" Then
            '5 Byte Kennung, hinten die "03" - d.h. von 11 bleiben 4
            'Eventuell anpassen, da wir die Länge kennen kannst du
            'die 03 am Ende auch weglassen
            Text11 = Buffer.Substring(5, 4)
        ElseIf Kennung = .....
                'hier die anderen 3 auswerten
        End If

        If Text11.Length And Text12.Length Then
            TextBox1.Invoke(Sub()
                                TextBox1.Text = Text11 & Text12
                            End Sub)
            Text11 = ""
            Text12 = ""
        End If
        'analog für Text21 + Text22
    End Sub

Und wenn dir was komisch vorkommt hilft natürlich der Debugger extrem. 
Am besten mal direkt nah dem ReadExisting mal nen Breakpoint setzen und 
schauen, was so ankommt...

von sauerbrunnen (Gast)


Lesenswert?

Hallo nochmal, heute habe ich endlich wieder Zeit gefunden...und hätte 
nochmal ein paar Fragen dazu.

tom schrieb:
> Dim Buffer = SerialPort1.ReadExisting()
>         'Hier gehe ich von deinen ursprünglichen Kennungen aus

Muss da außer ReadExisting noch etwas hin? Da ja mit dem nachfolgenden 
Code alles verarbeitet werden soll, müsste das ja so bleiben können.

tom schrieb:
> Dim Kennung = Buffer.Substring(0, 5)
>         If Kennung = "05 09" Then

05 09 habe ich entsprechend mit &Hxx angepasst.
1
 Buffer.Substring(0,5)
 - wie komme ich auf (0,5) ?

tom schrieb:
> '5 Byte Kennung, hinten die "03" - d.h. von 11 bleiben 4
>             'Eventuell anpassen, da wir die Länge kennen kannst du
>             'die 03 am Ende auch weglassen

und wie kommen wir bei 11 Bytes auf 5-Byte Kennung und wo sollte ich die 
03 hier noch eintragen?

tom schrieb:
> ElseIf Kennung = .....
>                 'hier die anderen 3 auswerten

Hauptproblem liegt nun da, dass ich nicht wirklich verstehe wie du beim 
ersten Substring auf (0, 5) kommst und dementsprechend weiß ich nicht 
wie ich hier für die nächsten Teile verfahren muss...

tom schrieb:
> If Text11.Length And Text12.Length Then

Muss hier im fertigen Code .Length noch definiert werden, also wann die 
Länge erreicht ist?

Danke erneut...

von tom (Gast)


Lesenswert?

Bevor ich ausführlich antworte noch eine Anmerkung/Frage: Die Logik 
funktioniert so nur, wenn tatsächlich IMMER jeweils ein 11 Zeichen 
übergeben werden. Irgendwo hattest du doch geschrieben, dass dir 
manchmal noch was anderes dazwischen haut, oder? Dann funktioniert das 
so nicht.

sauerbrunnen schrieb:
> Buffer.Substring(0,5)
>  - wie komme ich auf (0,5) ?

Das bezieht sichauf die alte Kennung mit den 5 Zeichen (z.B. "05 09")

von tom (Gast)


Lesenswert?

So, mir fällt es gerade wie Schuppen aus den Haaren:
Wir reden über verschiedene Kennungen. Meine "05 09" ist ein String der 
Länge 5.

Du verwendest aber in Wirklichkeit 2 Byte - also eine "59". Und am Ende 
steht eine "3" keine "03"

Also:
       Dim Kennung = Buffer.Substring(0, 2)
        If Kennung = "59" Then
            '2 Byte Kennung, hinten die "3" - d.h. von 11 bleiben 8
            'Eventuell anpassen, da wir die Länge kennen kannst du
            'die 3 am Ende auch weglassen
            Text11 = Buffer.Substring(3, 8)

usw.

If Text11.Length.... wird intern in Boolean konvertiert,
d.h. Länge = 0 ->FALSE, Länge > 0 ->TRUE

von tom (Gast)


Lesenswert?

Sorry, es muss natürlich

Text11 = Buffer.Substring(2, 8)

sein. Wer zählen kann ist im Vorteil...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.