Hallo, ich habe ein Programm gemacht, das mit einer Waage kommuniziert - also auf Knopfdruck das Wiegeergebnis ausliest und anzeigt. Das funktioniert alles soweit gut. Mein Problem ist, wie bekomme ich die Daten formatiert? - Bzw. an welcher Stelle muss ich da ansetzen? Die Waage liefert z. B. "S S 127.3 g <Return>" ich möchte aber in meiner Textbox nur "127,3 g" stehen haben. Wenn ich nach meinem Invoke-Befehl nur schon eine MSGBOX machen will, die mir das ganze etwas formatiert, erhalte ich schon folgende nette Meldung: Der Index und die Länge müssen sich auf eine Position in der Zeichenfolge beziehen - Parameter: length Es scheint mir, als ob noch nicht alle Daten da sind und das Programm schon weiter läuft. Kann man irgendwie abprüfen ob alles da ist? Wo muss ich mit dem formatieren ansetzen? Ich hoffe, dass einer mir weiterhelfen kann. Gruß Stefan Private Sub cmd_wiegen_uebernehmen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_wiegen_uebernehmen.Click ' Anzeigefeld leeren TextBox_Waagendisplay.Text = Nothing ToolStripStatusLabel_Gewicht.Text = Nothing ' Befehl an Schnittstelle / Gerät senden If ComboBox_Waagen_Modell.SelectedItem = "MODEM" Then Serielle_Schnittstelle.WriteLine("ATI3" & (Chr(13))) End If If ComboBox_Waagen_Modell.SelectedItem = "Mettler-Toledo" Then Serielle_Schnittstelle.WriteLine("S" & (Chr(13))) End If End Sub ======================================================================== ============================================== Private Sub Serielle_Schnittstelle_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles Serielle_Schnittstelle.DataReceived Try TextBox_Waagendisplay.Invoke(New myDelegate(AddressOf updateTextBox), New Object() {}) MsgBox(TextBox_Waagendisplay.Text.Substring(4, 10), MsgBoxStyle.Information, "Waagendisplay formatiert...") Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Fehler aufgetreten... ...Gerät / Port richtig eingestellt?") Exit Sub End Try End Sub ======================================================================== ================================================ Public Delegate Sub myDelegate() Public Sub updateTextBox() With TextBox_Waagendisplay .Font = New Font("Microsoft Sans Serif", 16.0!, FontStyle.Bold) .AppendText(Serielle_Schnittstelle.ReadExisting) .ScrollToCaret() End With End Sub
Das ist VB, richtig?
> "S S 127.3 g <Return>"
Kann die Waage nur in Gramm oder auch in Kilogramm anzeigen, und wieviel
jeweils? Wenn die Waage nur Gramm anzeigen kann, und das beispielsweise
nur bis 10 kg, dann muss deine Textbox mit den letzten 9 Zeichen (ohne
Return) von rechts aus deinen empfangenen Daten gefüllt werden, und
dafür bietet VB viele nette Textfunktionen...
Oder ist das nicht das, was du dir vorstellst?
Ralf
Hallo Ralf, die Einheit ist variabel - Waage kann z. B. auch Stückzählen. L. T. Datenbeschreibung ist die Anzeige 10 Stellen wobei aber die Stellen davor mit Leerzeichen erscheinen. Ja, es ist VB .NEt 2005. Wo kann ich versuchen da anzusetzen? - Hast du ein Beispiel? Wenn ich mit Substring was "rausschneiden" will, klappt das irgendwie immer nur mit der Fehlermeldung, da wohl noch Daten ankommen bzw. noch nicht alle Daten da sind. Ich habe schon versucht mit einem TextChanged Ereignis der Textbox zu arbeiten, aber da läuft es auch auf den Fehler. Dadurch, dass wohl noch Daten ankommen, wird wohl mehrfach das DataReceived Ereignis durchlaufen. Hast du noch eine Idee??? Mein Programm ist vergleichbar mit dem Beispiel unter http://www.devx.com/dotnet/Article/31001/0/page/2 Jedoch ist da auch nichts gezeigt, wie man was formatiert bzw. an welcher Stelle. Gruß Stefan
Ach so du arbeitest in der seriellen Schnittstelle mit Polling? Dann könntest du eine Bool-Variable verwenden, die erst dann auf True geht, wenn das Return empfangen wurde, das zeigt dir dann an, dass die Daten komplett sind... Deine Anzeige-Routine pollt diese Bool-Variable, und gibt erst aus, nachdem die Variable True ist. Nach der Ausgabe setzt die Ausgabe-Routine die Variable auf False... Zum Thema String bearbeiten, in VB6 gabs da die left- bzw. right-Funktionen (und noch viele andere ähnliche)... Sag Bescheid, obs geklappt hat... Ralf
>Dadurch, dass wohl noch Daten ankommen, wird wohl mehrfach das >DataReceived Ereignis durchlaufen Das vermutest du richtig ändere deine Programmstruktur. Der Zugriff auf Textboxen hat nichts in der Empfangsroutine für einzelne Zeichen zu suchen. Das Einzige was du da machst, ist die Zeichen in einen String zu übernehmen und möglicherweise zu signalisieren wann der String die entsprechende Länge hat, damit er weiterverarbeitet werden kann.
Hallo, habt Ihr zufällig ein kleines Beispiel wie Ihr das genau meint bzw. man sowas aufbaut? Gruß Stefan
Wow, der Programmcode den du hast hast du ja vollständig kopiert von dem Link den du angibst. Jetzt kapiere ich auch warum du so eine ungünstige Programmstruktur nimmst. Nun das geht hervorragend für ein Terminalprogramm aber nicht für deinen Anwendungsfall. Du willst eine Waage abfragen und ich schätze das funktioniert folgendermaßen: Du sendest einen Befehl und bekommst eine Antwort. Dazu brauchst du kein Event wenn daten ankommen, die kommen nämlich nur wenn du sie anforderst und damit wird es sehr einfach. Du schreibst nämlich nur auf die Schnittstelle und wenn die entsprechende Anzahl Zeichen der Antwort da ist liest du das ganze aus. Dazu braucht man kein Bsp, man muss nur die Serialportklasse kennen, hierzu gibt es die MSDN http://msdn2.microsoft.com/en-us/library/system.io.ports.serialport.aspx nebenbei ist da auch ein Bsp, aber das solltest du auch so hinbekommen.
Hallo Wolfram, ja, ich sende nur einen Befehl und greife auf die Antwort zurück. Das würde bedeuten, dass ich gleich bei dem Klick auf den Wiege-Button den Befehl sende und den Empfang auslese und ggf. noch formatiere. Zum formatieren hatte mir jemand mal folgendes vorgeschlagen: Dim a As String Dim wert As Double If Double.TryParse(string_von_waage, out wert) = true Then a.Format(“{0:#####.0} g”, wert) textbox.Text = a Else textbox.Text = “Fehler” End If findest du das GUT??? Wenn man mit dem DataReceived Event arbeitet, muss man wohl immer ein Invoke machen und ein Delegate, damit die Daten in die Textbox geschrieben werden. - Ansonsten bekommt man so schöne Meldungen wie diese: Der Zugriff auf das Steuerelement TextBox_Waagendisplay erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde." Source="System.Windows.Forms" Zusammengefasst würde ich jetzt sowas machen (Modem ist zum testen, wenn ich die Waage nicht dran habe): ' Befehl an Schnittstelle / Gerät senden If ComboBox_Waagen_Modell.SelectedItem = "MODEM" Then Serielle_Schnittstelle.WriteLine("ATI3" & (Chr(13))) End If If ComboBox_Waagen_Modell.SelectedItem = "Mettler-Toledo" Then Serielle_Schnittstelle.WriteLine("S" & (Chr(13))) End If TextBox_Waagendisplay.Text = Serielle_Schnittstelle.ReadExisting() (Formatieren)
Hallo, habe festgestellt, dass man besser noch ein Sleep ins Programm einbauen sollte - sonst kann es sein, dass noch nicht alle Daten im Puffer der Schnittstelle zur Verfügung stehen bzw. noch etwas vom vorherigen Versuch wohl da ist. System.Threading.Thread.Sleep(100) ' 1000 = 1 Sekunde warten sollte helfen! Gruß Stefan
>ja, ich sende nur einen Befehl und greife auf die Antwort zurück. >Das würde bedeuten, dass ich gleich bei dem Klick auf den Wiege-Button >den Befehl sende und den Empfang auslese und ggf. noch formatiere. dachte ich es mir doch, du brauchst keinen receive Event sondern es geht ganz einfach: schreiben->auslesen >Zum formatieren hatte mir jemand mal folgendes vorgeschlagen:... du kennst doch das geanue Format der Antwort, schneide alles überflüssige weg und mache dann die Umwandlung >Wenn man mit dem DataReceived Event arbeitet, muss ... genau deswegen ist es nötig, deshalb vermeidet man solche Abfragen wenn nicht unbedingt nötig, da hieraus gewöhnlich ein sehr unübersichtlicher Code entsteht. Das Sleep ist keine schlechte Idee da das Senden über die Serielle dauert. Aber bist damit immer noch sehr unsauber. Entweder du arbeitest mit Timeout für die Antwort oder du wartest bis die entsprechende Anzahl von Zeichen gekommen ist, dann erst liest du. Natürlich solltest du dann immer noch einen Timeout haben.
Warum machst du das denn nicht einfach ereignisgesteuert über das TextBoxFeld, das die Daten einliest? Geht das in *.NET nicht? Ich habe das in meinen Accessdatenbanken immer so gehandhabt, daß ein Textfeld (Variablenfeld) beim Eintreffen einer neuen validen Nachricht einmalig aktualisiert wurde. Formatierungen kann man dann über ein versteckt eingelesenens Feld (Visibility = 0) und einem anderen sichtbaren Feld realisieren, wobei man auf das nichtsichtbare die in VBA vorhandenen Textoperatoren und Konversionfunktionen loslässt. Damit wird dann nur "bei Änderung" und auch nur einmalig gerechnet. (also nix "polling" oder wait state oder so ...)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.