Autor |
Beitrag |
avoid
      
Beiträge: 230
Erhaltene Danke: 4
MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
|
Verfasst: So 05.06.11 14:43
hi alle zusammen.
ich hab da mal ein problem, wie sollte es auch anders sein.
ich bastel mir gerade mit "Microsoft Visual C# 2010 Express" eine Windows-Forms anwendung. diese soll daten über den serialport empfangen, auswerten und anzeigen.
ich hab mir also ein par elemente zusammen geklickt:
- button1, textbox1, textbox2, textbox3, serialport1, timer1, ...
dem button hab ich ein click event verpasst das den timer startet und stoppt. außerdem öffnet und schließt der button dabei den serialport.
baudrate, port, multiline für die drei textboxen usw. sind alle voreingestellt, weil ich in dieser anwendung nur die funktionalität teste.
im tick event des timer hab ich dann meinen code der die daten abruft und verarbeitet. und genau dabei hab ich so meine probleme.
wenn serialport1 offen ist übergebe ich die daten aus dem puffer an den string "ex". der string "ex" hat dann einen inhalt der ungefähr so aussehen kann: "S1,0,S2,0 S1,200,S2,13 S1,3,S2,9 ......." es handelt sich in diesem beispiel string um zwei sensor werte (S1=x und S2=y). ich habe das komma und das leerzeichen als operatoren für mögliche split operationen vorgesehn. das format in dem die daten gesendet werden kann ich aber ändern falls nötig, das ist nicht vorgegeben.
die daten übergebe ich mit "ex = serialPort1.ReadExisting();" sprich, ich packe den gesamten puffer inhalt in die variable "ex" egal ob vollständig oder nicht. ich halte das für sinnvoll weil es um echtzeit messung geht, da können schon mal ein par werte unter den tisch fallen.
und jetzt gehen die probleme los:
wenn ich den string "ex" jetzt mit "s = ex.Split(' ');" am leerzeichen trenne und in das array "s" packe kann es vorkommen das der erste und/oder der letzte array eintrag nicht vollständig ist.
wie kann ich das prüfen oder von vornherein vermeiden?
mache ich jetzt in der nächsten schleife mit "sa = s[i].Split(',');" weiter kommen immer am anfang und ende ein oder zwei leere/fehlerhafte array felder dabei raus.
für die ausgabe in die richtige textbox hab ich dann noch eine if abfrage die kuckt ob es sich um "S1" oder "S2" handelt und den wert der darauf folgenden zelle in die richtige textbox packt. aber dabei kommen trotzdem teilweise leere werte oder von z.b. 3200 nur die 3 an weil der rest noch nicht im puffer war.
ich hab es schon mit "serialPort1.ReadLine();" versucht aber dabei sammelt sich zu viel im puffer und auf dauer ist es keine echtzeit mehr. außerdem muß ich dann den timer auf 100 hoch drehen da sonst die komplette anwendung blockiert wird.
----------------
ich hoffe mal jemand hat nen tip für mich auch ohne meinen kompletten code zu sehen. warscheinlich sehe ich den wald vor lauter bäumen nicht.
danke schon mal.
avoid
Moderiert von Christian S.: Überflüssige Zeilenumbrüche entfernt
|
|
avoid 
      
Beiträge: 230
Erhaltene Danke: 4
MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
|
Verfasst: Mo 06.06.11 20:31
zum besseren verständniss hier doch noch der code vom timer.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| private void timer1_Tick(object sender, EventArgs e) { if (serialPort1.IsOpen == true) { string ex; string[] s,sa; int i,i2,i3; try { ex = serialPort1.ReadExisting(); textBox1.AppendText(ex); s = ex.Split(' ');
for (i3 = 0; i3 < s.Length; i3++) { sa = s[i3].Split(','); for (i = 0; i < sa.Length; i++) { label1.Text = i.ToString();
if (sa[i] == "S1") {
i2 = i + 1; textBox2.AppendText(sa[i2] + "\n"); }
if (sa[i] == "S2") { i2 = i + 1; textBox3.AppendText(sa[i2] + "\n"); } } } } catch { } } } |
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 06.06.11 20:41
Hi!
Ich habe noch nicht ganz verstanden, was das Problem ist. Liegt das nun beim Lesen der Werte vom Port oder beim String-Split. Irgendwie wird das nicht ganz deutlich.
Auf jeden Fall benutzt man zum Lesen von einem SerialPort eigentlich keinen Timer, sondern reagiert auf das DataReceived-Event des Ports. Wenn das ausgelöst wird, ruft man die Daten mit ReadLine oder ReadExisting ab. In einem meiner Programme sieht das so aus, wobei ich nicht mehr genau weiß, wie deses try-catch-Konstrukt zustande gekommen ist. Aber funktinoiert
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| internal void _Port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { string data = null; try { data = _Port.ReadLine(); } catch { data = _Port.ReadExisting(); } if (!String.IsNullOrEmpty(data)) HandleData(data); } |
Grüße,
Christian
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 06.06.11 23:21
Zitat: | In einem meiner Programme sieht das so aus, wobei ich nicht mehr genau weiß, wie deses try-catch-Konstrukt zustande gekommen ist |
Du wolltest vermutlich nur die TimeoutException fangen. Dann macht das Sinn. Denn wenn der ReadLine knallt weil der Port nicht offen ist hilft auch kein ReadExisting
Zitat: | ich hab es schon mit "serialPort1.ReadLine();" versucht aber dabei sammelt sich zu viel im puffer und auf dauer ist es keine echtzeit mehr. |
Du könntest versuchen in einem separaten Thread den Port in einer Schleife um ReadByte herum auszulesen. Dabei einen eigenen kleinen Buffer füllen bis du ein Schlüsselwert Paar zusammenhast und diesen dann weiterreichen/weiterbearbeiten. Wenn diese Schleife deinen Daten nicht hinterherkommt kannst du das mit Echtzeit eh vergessen und in deinem bisherigen Ansatz die unvollständigen Eintragungen einfach wegwerfen.
Also Pseudocode etwa
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| while (!stop) { try { buffer += port.ReadByte(); if (buffer.ContainsCompleteKeyValuePair) { DoSomething(buffer); buffer.Clear(); } } catch (TimeoutException) { } } |
|
|
avoid 
      
Beiträge: 230
Erhaltene Danke: 4
MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
|
Verfasst: Di 07.06.11 00:57
ok so wie cristian es geschrieben hat, kann ich die leeren strings raus filtern, das klappt.
danke schon mal dafür.
ralf, verstehe ich deinen code richtig?
Zitat: |
buffer += port.ReadByte(); // oder ReadExisting
|
das += hängt an buffer etwas rann und ersetzt nicht den inhalt?
muß ich wohl im einsteigerbuch überlesen haben.
Zitat: |
if (buffer.ContainsCompleteKeyValuePair)
{
DoSomething(buffer);
buffer.Clear();
}
|
kannst du mir für den roten bereich ein beispiel geben?
bei meinen beiden sensor werten ist das problem das die zwischen 0 und 65xxx sein können.
-----------------------------
ich hab aber auf grund eurer antworten eine idee.
könnte es klappen wenn ich die daten in diesem format an den PC sende?
"S1,0,E,S2,0,E,S1,200,E,S2,13,E,S1,3,E"
so könnte ich den string am komma aufsplitten und wie gehabt mit "if (sa[i] == "S1")" arbeiten.
nur das ich S1 bzw. S2 als start werte sehe, dann abfrage ob zwei array felder weiter ein E enthalten ist.
und wenn ja verwende ich das array feld dazwischen, weil es vollständig sein sollte.
gibts kein E oder keine zwei weiteren felder nach S1 bzw. S2 dann ist die schleife beendet.
ich denk so mach ich das, mit einer anfangs- und endmarkierung die zeigt
ob die zu verwurschtenden daten komplett sind.
-----------------------------
ach wegen dem timer, den benutz ich weil ich damit verhindere das das programm einfriert solange was gearbeitet wird.
hab ich mal irgendwo gelesen und klappt auch soweit.
doch ich sollte wohl lieber mal nachlesen wie der background worker funktioniert wie mir scheind.
wichtig ist mir im grunde, das ich am ende in echtzeit die beiden sensor werte in ihre textfelder bekomme
und das im dritten textfeld die rohdaten nachgelesen werden können um einen sende fehler zu erkennen.
nicht das ich verzweifelt nach fehlern im programm suche und es liegt an einer schlechten verbindung.
ich hab vor die serielle verbindung auf funk um zu bauen, wenn mein tool läuft.
ich werd versuchen das alles so um zu setzen und lass es euch wissen ob es geklappt hat.
danke schon mal.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 07.06.11 09:17
Zitat: | Zitat: | buffer += port.ReadByte(); // oder ReadExisting |
das += hängt an buffer etwas rann und ersetzt nicht den inhalt?
muß ich wohl im einsteigerbuch überlesen haben. |
Nun wie ich gesagt habe war das nur Pseudocode. Und ich wollte damit ausdrücken das du halt Byteweise einlesen könntest und solange irgendwie Bytes sammeln bist du aus der Bytefolge deren Bedeutung erkennen kannst.
Zitat: | Zitat: | if (buffer.ContainsCompleteKeyValuePair)
{
DoSomething(buffer);
buffer.Clear();
} |
kannst du mir für den roten bereich ein beispiel geben?
bei meinen beiden sensor werten ist das problem das die zwischen 0 und 65xxx sein können. |
Deine Daten scheinen ja eine kommagetrennte Liste von abwechselnden Keys(deines Sensorbezeichnung) und deren Werten zu sein.
In der ContainsCompleteKeyValuePair Methode/Property könntest du also testen ob 2 Kommmata angekommen sind. Oder per Regex ob die Daten im Buffer das Format 'Sensor,Wert,' vollständig erfüllen ist etc. Der Möglichkeiten sind da viele.
|
|
avoid 
      
Beiträge: 230
Erhaltene Danke: 4
MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
|
Verfasst: Mi 08.06.11 01:48
ok, ich hab meinen code jetzt etwas angepasst in dem ich das datareceved event vom serialport nutze
und dort die empfangenen daten direckt in eine string variable packe.
ich hab noch eine kleine frage am rande.
zum testen nutze ich gerade nur 4800baud später werde ich auf höhere datenraten wechseln.
muß ich das jetzt schon in der verarbeitung berücksichtigen?
-----edit-----
ich heng euch mal das VCS 2010 Express projeckt an, dann könnt ihr es ausprobieren.
der string den ich empfange ist jetzt so aufgebaut: S1,wert,E,S2,wert,E,
der wird quasi in einer endlos schleife an den PC gesendet.
Einloggen, um Attachments anzusehen!
|
|
|