Benutzer mit den meisten Antworten
HID USB Stream auslesen

Frage
-
Hallo MSDN Nutzer,
Ich nutze VB.Net und WPF und habe folgende Aufgabenstellung:
Ich habe ein USB Gerät das mit dauerhaft einen Wert aus 32 Bit liefert der so aussieht:
00 A1 05 35 FF B4 05 AF 01 0F 05 A5 01 AD 04 D1 01 EF 03 52 00 15 01 92 01 4B FF DE 00 16 A0 02
Aus diesem Wert kann ich jeweils 7 Werte für X, 7 Werte für Y und 1 Wert für Z entnehmen.
Ein Wert X sowie ein Wert Y entsprechen 0,001024 Sekunden.Wie kann ich das Gerät so ansprechen, das ich sekündlich alle geforderten Werte abspeichern kann ohne das sich das komplette Projekt aufhängt?
Nach aufgerundeter Rechnung benötige ich diesen 32 Bit Wert ungefähr 500 Mal die Sekunde.
Wenn ich das hinbekämen würde wär ich schon sehr weit. Denn danach geht es daran diese Werte in einem Line-Chart darzustellen.
Ich hoffe jemand von euch kann mir helfen.
MfG ASkuN
Antworten
-
Ich denke du musst einen API-Recall initialisieren. Ich habe das Gefühl das du die Daten selbst lesen willst, und damit ist Deine Methode zu langsam.
Ich denke du müsstest das Gerät initialisieren und dann per API einen Ereignishandler in Deinem Programm mitteilen, somit wird deine Prozedur jedes mal aufgerufen wenn Daten eintreffen, die Du dann abarbeiten musst. Im Moment rufst du die Funktion auf (erstellst einen Puffer und legst Zeiger fest) wodurch dir Daten zwischen 2 Aufrufen durch die Lappen gehen.
Solche Nachrichtenschleifen in Dein eigenes Programm zu implementieren sind an sich möglich, aber bedarf einer genauen Planung und Wissen wie der Ablauf in dem Gerät von statten geht.
Vielleicht kann Dir Elmar Boye da helfen, einer der Forum Gurus hier [Anerkennend gemeint :-)]
Gruß Thomas
- Bearbeitet tommytom73 Dienstag, 14. Mai 2013 15:08 Namen falsch geschieben
- Als Antwort markiert ASkuN Dienstag, 14. Mai 2013 15:19
Alle Antworten
-
Hallo
Das sieht mir danach aus, das man mit Threads arbeiten müsste.
Thread 1:
- Daten auslesen und aufbereiten
- Daten in einer Collection z.B.(Queue) ablegenThread 2:
- Daten aus der Collection auslesen und dann anzeigen Bzw. speichern.Ich weiß jetzt nicht was Du mit "ohne das sich das komplette Projekt aufhängt?" meinst. Du scheinst ja schon Code geschrieben zu haben der nicht richtig funktioniert. Müsste man sehen um vielleicht Tipps zu geben.
Gruß Thomas
-
also das Problem ist einfach, das es sich um eine erhebliche Menge an Daten handelt die ich pro Sekunde brauche. Ich fülle zwei Textboxen und ein ComponentOne Chart und damit ist es schon sehr langsam....ich habe die zwei Textboxen jetzt rausgelassen und es geht schonmal doppelt so schnell aber immer noch zu langsam....
könntest du mir ein Beispiel für eine Thread Methodik geben wie du es lösen würdest? Ich habe schon diverse Methoden ausprobiert (Vielleicht auch mit Verständnisproblem falsch gecoded!) wie zum Beispiel System.Threading.Thread und System.Componentmodel.Backgroundworker
MfG ASkuN
-
Ich habe mal schnell ein Bespiel geschrieben welches mit 2 Threads arbeitet. Der Erste Thread überwacht ein Verzeichnis und bei Änderungen speichert er diese in die Auflistung (Queue). Der zweite Thread prüft ständig ob es Einträge in der Auflistung gibt, wenn ja nimmt er dieses Object aus der Auflistung heraus und zeigt es in einer Listbox an.
Die ist wie gesagt ein ganz einfaches Beispiel, welches nur zeigen soll wie es ungefähr gehen könnte, da ich nicht weiß wie Deine Daten ankommen. Mann sollte es auch noch threadsicher machen siehe Queue
Gruß Thomas
Public Class Form1 ' Private Structure objTest Public strEreignis As String Public strFile As String Public Overrides Function ToString() As String Return strEreignis & ":" & strFile End Function End Structure ' Private WithEvents bwReadThread As System.ComponentModel.BackgroundWorker Private WithEvents bwSaveThread As System.ComponentModel.BackgroundWorker Private lstQueue As System.Collections.Generic.Queue(Of objTest) Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing If IsNothing(bwReadThread) = False AndAlso bwReadThread.IsBusy = True Then bwReadThread.CancelAsync bwReadThread.Dispose End If If IsNothing(bwSaveThread) = False AndAlso bwSaveThread.IsBusy = True Then bwSaveThread.CancelAsync bwSaveThread.Dispose End If End Sub ' Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load lstQueue = New System.Collections.Generic.Queue(Of objTest) bwReadThread = New System.ComponentModel.BackgroundWorker bwReadThread.WorkerSupportsCancellation = True bwReadThread.RunWorkerAsync '// bwSaveThread = New System.ComponentModel.BackgroundWorker bwSaveThread.WorkerSupportsCancellation = True bwSaveThread.WorkerReportsProgress = True bwSaveThread.RunWorkerAsync '// End Sub ' #Region "Thread-1" ' Private Sub AusleseThread_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwReadThread.DoWork '// Dim fw As New IO.FileSystemWatcher("C:\Users\[USER]\AppData\Local\Temp") AddHandler fw.Changed, AddressOf ObjectChanged AddHandler fw.Renamed, AddressOf ObjectRenamed fw.EnableRaisingEvents = True '// Do While DirectCast(sender, System.ComponentModel.BackgroundWorker).CancellationPending = False Loop '// fw.EnableRaisingEvents = False '// End Sub ' Private Sub ObjectChanged(sender As Object, e As System.IO.FileSystemEventArgs) Dim t As New objTest t.strEreignis = "geändert" t.strFile = e.Name Me.lstQueue.Enqueue(t) End Sub ' Private Sub ObjectRenamed(sender As Object, e As System.IO.RenamedEventArgs) Dim t As New objTest t.strEreignis = "umbenannt" t.strFile = e.Name Me.lstQueue.Enqueue(t) End Sub ' #End Region ' #Region "Thread-2" ' Private Sub AnzeigeThread_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwSaveThread.DoWork '// Do While DirectCast(sender, System.ComponentModel.BackgroundWorker).CancellationPending = False '// If Me.lstQueue.Count > 0 Then DirectCast(sender, System.ComponentModel.BackgroundWorker).ReportProgress(0, Me.lstQueue.Dequeue) End If '// Loop '// End Sub ' Private Sub AnzeigeThread_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bwSaveThread.ProgressChanged If IsNothing(e.UserState) = False Then Me.ListBox1.Items.Add(DirectCast(e.UserState, objTest).ToString) End If End Sub ' #End Region ' End Class
-
Okey erstmal Danke für die ausführliche Antwort. Jetzt geht's einen Schritt weiter...
Ich habe ein USB HID Device das ich mittels Produkt ID und Vendor ID (PID & VID) ansprechen kann. Ich habe herausgefunden das meine Methodik zu langsam ist (es kommen nicht alle Datenpakete an).
Beim einstecken dieses Geräts fängt er sofort an Datenflüsse zu senden in Form von diesen 32 Byte Paketen.
Ich brauche eine Methode, Funktion, DLL was auch immer um sehr sauber mit diesem Gerät zu kommunizieren.
Danke im Voraus...
P.S.: Mit der Produkt und Vendor ID habe ich es BIS jetzt gemacht. Natürlich hat das Gerät auch eine eindeutige Seriennummer....Hoffe das hilft vielleicht....
MfG ASkuN
- Bearbeitet ASkuN Dienstag, 14. Mai 2013 13:13
-
Das ist ein Gerät zum Auslesen des Puls und EKG Wert einer Person. Das Device sendet beim Einstecken sofort kontinuierlich diese 32 Bytes los.
Ich handle nach dem Prinzip wie es in diesem Projekt zu sehen ist ("generichid_vb")
MfG ASkuN
-
Also die "theoretische Lösung" würde so aussehn:
Thread #1:
Schreibt den Datenfluss der vom HID kommt in einen Buffer ("Buffer #1") mit ausreichender Größe.
Thread #2:
Sammelt und ordnet die Byte Pakete aus dem Buffer ("Buffer #1") in deinem neuen Zwischenbuffer ("Buffer #2") und bildet den grafischen View in einem Chart.
So viel zum theoretischen jetzt muss ich es nur noch hinbekommen die Kommunikation mit dem HID zu realisieren...
MfG ASkuN
-
Gibt es einen Treiber? Wie wird das Gerät im Gerätemanager angezeigt?
Finde ich komisch das das Gerät ungefragt (ohne Initialisierung) Daten sendet. Die meisten Medizin-Produkte die ich kenne werden über virtuelle Com-Ports aktiviert und erst wenn ich den Datenempfang initialisiere geht das senden der Daten los. Die Gräte welche Direkt per USB angeschlossen sind haben meisten einen Device-Treiber den man per API-Funktionen initialisieren und den Datenempfang kontrollieren kann.
In Deinem Fall ist es schwierig dir Tipps zu geben ohne weitere Kenntnisse über das Gerät.
Ich würde anhand Deiner Informationen folgende Schritte versuchen.
1. Den Empfang der Daten in dem ersten Thread
2. Eine Klasse erstellen welche die empfangenen Daten aufnimmt, verarbeitet, und dann strukturiert bereitstellt.
3. Das erzeugte Objekt in die Auflistung packen
4. Der zweite Thread übernimmt dann die Speicherung der Daten oder Anzeige in der GUI
5. Die meisten Diagramm-Controls kann man meistens per Datenbindung direkt mit einer Datenquelle verbinden. (Außer Du hast vor die EKG-Ableitungskurven in Echtzeit anzuzeigen dann hast Du ganz schön was vor Dir.Gruß Thomas
-
Es ist ganz schön schwierig alles so darzustellen das ich keine Probleme mit dem Auftraggeber bekomme :-)
Das Device wird als eingestecktes USB HID gelistet. In der Beispielanwendung ("HIDTest.exe") aus der ZIP Datei wird das mit HidD_GetAttributes realisiert.
Das Gerät an sich wird per USB-Dongle nutzbar gemacht und aktiviert.
Zu Punkt 1:
Das mache ich ja schon, das Problem ist das die Methode (die auch im Beispielprojekt genutzt wird) nicht schnell genug arbeitet. Es gehen immer zwischen 3 und 20 Pakete verloren.
MfG ASkuN
-
Ich denke du musst einen API-Recall initialisieren. Ich habe das Gefühl das du die Daten selbst lesen willst, und damit ist Deine Methode zu langsam.
Ich denke du müsstest das Gerät initialisieren und dann per API einen Ereignishandler in Deinem Programm mitteilen, somit wird deine Prozedur jedes mal aufgerufen wenn Daten eintreffen, die Du dann abarbeiten musst. Im Moment rufst du die Funktion auf (erstellst einen Puffer und legst Zeiger fest) wodurch dir Daten zwischen 2 Aufrufen durch die Lappen gehen.
Solche Nachrichtenschleifen in Dein eigenes Programm zu implementieren sind an sich möglich, aber bedarf einer genauen Planung und Wissen wie der Ablauf in dem Gerät von statten geht.
Vielleicht kann Dir Elmar Boye da helfen, einer der Forum Gurus hier [Anerkennend gemeint :-)]
Gruß Thomas
- Bearbeitet tommytom73 Dienstag, 14. Mai 2013 15:08 Namen falsch geschieben
- Als Antwort markiert ASkuN Dienstag, 14. Mai 2013 15:19
-
ich danke dir :) ich bin auf so einen Lösungsweg vor ca. einer halben Stunde gestoßen und habe es endlich realisiert bekommen.
Zur Lösung:
Jedes Mal wenn Daten des Sticks kommen wird meine Methode OnDataReceived Aufgerufen und diese Speichert dann über einen Thread die Daten in einen Buffer. Parallel läuft ein zweiter Thread der den Buffer überwacht und neue Daten in den View für die grafische Ansicht umwandeln :)
Mit viel denken, probieren und nachfragen kommt man am Schluss doch immer auf einen Punkt :)
Vielen Dank :)
MfG ASkuN
-
"ASkuN" schrieb im Newsbeitrag> Ich brauche eine Methode, Funktion, DLL was auch immer um sehr sauber mit> diesem Gerät zu kommunizieren.und was sagt der Hersteller dazu, die gibt es normalerweise vom Hersteller -gibt es eine Beschreibung?Oder wollt Ihr nur ein Gerät für Eure Zwecke missbrauchen?Du müsstet ja wenigstens wissen was die Werte bedeuten.
-
"ASkuN" schrieb> Der Hersteller ist ein Partner von uns und wir stellen die Software her.> Ich weiß was die Werte genau bedeutet, doch darf ich keine öffentlichen> Angaben (wegen Datenschutzgründen) machen.Das Demo das Du hattest ist irgendwo aus dem Internet, das habe ich auchschon seit langem auf dem Rechner lieen.Nun kannst Du das Teil nehmen, die Funktionen herausziehen und Dir Deineeigenen Klasse daraus aufbauen, passend zu dem Gerät.Her gibts auch noch ein paar Beispiele zur Inspiration.