INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

Grundkonzept einer Datenerfassung/Auswertung



Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!

02.10.2009, 12:57
Beitrag #11

Malte84 Offline
LVF-Grünschnabel
*


Beiträge: 26
Registriert seit: May 2009

8.5
2008
de

45897
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
Danke für die gute Erklärung zum Speichermanager! Durchaus wichtiges und interessantes Hintergrundwissen.
Was mir aber gerade einfällt:
Wenn ich ein Array mit maximaler Größe vor der While-Schleife initialisiere, dann macht es doch keinen Sinn einen Ringpuffer zu verwenden. Der Speicher ist jetzt eh belegt und es wäre doch dann unnötig die CPU ständig damit zu belasten, Teile zu löschen... Oder mache ich jetzt einen Denkfehler?
(Für die Grafanzeige reicht es doch mittels dem LV-Befehl "Teilarray" nur einen bestimmten Teil anzuzeigen...)

Und dann habe ich mich jetzt doch direkt mal mit dem kleineren Datentyp befasst.
Du sagst, womöglich ginge U16 (also unsigned 16 Bit Word, also Wertebreich 0 bis 65535). Wie soll das reichen? Bei Schwingungen habe ich doch auch negative Werte. Das Problem des fehlenden Kommas könnte ich mir noch vorstellen irgendwie mit vorheriger Multiplikation und Komma-Verschiebung zu lösen, aber auch da habe ich keinerlei Erfahrung und das ist jetzt nur geraten.
Wenn ich Messwerte von wenigen nm (ja, nanometer) (Weg) bis 100.000.000 m/s² (Beschleunigung) messe, kann ich mir gerade nicht vorstellen mit U16 hinzukommen...
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.10.2009, 13:43
Beitrag #12

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.689
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
' schrieb:Wenn ich ein Array mit maximaler Größe vor der While-Schleife initialisiere, dann macht es doch keinen Sinn einen Ringpuffer zu verwenden. Der Speicher ist jetzt eh belegt und es wäre doch dann unnötig die CPU ständig damit zu belasten, Teile zu löschen... Oder mache ich jetzt einen Denkfehler?
Jein. Das kommt darauf an.
Ist deine (3-Minuten-)Messung spätestens dann beendet, wenn das Array voll ist, dann brauchst du keinen Ringpuffer. Bei der nächsten Messung würde das Array ja wieder von vorne beginnend aufgefüllt werden.
Willst du aber einen Ringpuffer als solchen haben, hat das an sich nichts mit dem Array-Initialisieren als solchem zu tun. Für den Ringpuffer brauchst du auch ein initialisiertes Array. Der Ringpuffer ist ja nur dazu da, um bei einer (un-)endlich lang dauernden Messung nur z.B. die letzten 3 Minuten zu speichern.
Weder bei der Ringpuffermethode, noch bei der ohne, werden Teile gelöscht - zumindest nicht explizit. Bei jeder dieser Methoden werden lediglich Daten überschrieben und ein Lese- und ein Schreibzeiger angepasst. Genau dieses Überschreiben (Replace) ist ja Ziel der Übung.

Zitat:(Für die Grafanzeige reicht es doch mittels dem LV-Befehl "Teilarray" nur einen bestimmten Teil anzuzeigen...)
Das ist in einfacher Weise richtig für einen linearen Puffer: Methode ohne Ringpuffer. Weil bei dieser Methode der Beginn der Daten immer am Array-Anfang liegt.
Bei einem Ringpuffer liegt aber der Anfang der Daten beliebig im Array. Nämlich an der Lese-Position (die zuerst Null ist und bei vollem Ringpuffer mit der nächsten Schreibposition identisch ist). Weiterer Unterschied: Die Anzahl der Daten. Bei ohne Ringpuffer ist das immer die Länge des Arrays. Bei mit Ringpuffer muss die Differenz zwischen Lese- und Schreibposition beachtet werden.

Zitat:Und dann habe ich mich jetzt doch direkt mal mit dem kleineren Datentyp befasst.
Genau, du hast dich damit befasst. So ist es ja vorgesehen - dich damit zu befassen, was noch nichts über das Ergebnis aussagt.
Es muss natürlich zuerst der Messbereich festgelegt werden. Wenn der von 0 bis 400 Bar (also ohne Nachkommastellen) geht kann man U16 nehmen. Bei -120 bis 1500 Grad Celsiun (auch ohne Nachkommastellen) muss man schon auf I16 umsteigen. Bei +- 0,001 bis 999,999 mm (also Auflösung 1µ auf 1m) kann man mit 1000 multiplizieren, in µm rechnen und I32 verwenden. I32 ist immer doch besser als DBL. Wenn du eine Frequenz auf 12 Stellen genau messen willst, bist du dann doch wieder bei 64Bit (I64 oder DBL).
Hinweis:
Die Methode mit der Scalierung (mm => µm) und der Verwendung von Integer anstelle von DBL/SGL war früher mal interessant wegen des Geschwindigkeitsvorteiles von INT gegenüber DBL. Jetzt ist glaub ich auch DBL sehr schnell.

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.10.2009, 14:16
Beitrag #13

Malte84 Offline
LVF-Grünschnabel
*


Beiträge: 26
Registriert seit: May 2009

8.5
2008
de

45897
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
Zitat:Ist deine (3-Minuten-)Messung spätestens dann beendet, wenn das Array voll ist, dann brauchst du keinen Ringpuffer. Bei der nächsten Messung würde das Array ja wieder von vorne beginnend aufgefüllt werden.
Willst du aber einen Ringpuffer als solchen haben, hat das an sich nichts mit dem Array-Initialisieren als solchem zu tun. Für den Ringpuffer brauchst du auch ein initialisiertes Array. Der Ringpuffer ist ja nur dazu da, um bei einer (un-)endlich lang dauernden Messung nur z.B. die letzten 3 Minuten zu speichern.
Weder bei der Ringpuffermethode, noch bei der ohne, werden Teile gelöscht - zumindest nicht explizit. Bei jeder dieser Methoden werden lediglich Daten überschrieben und ein Lese- und ein Schreibzeiger angepasst. Genau dieses Überschreiben (Replace) ist ja Ziel der Übung.
Ok, vermutlich habe ich eine falsche Vorstellung vom Ringpuffer. Bisher habe ich mir den manuell vorgestellt (Array ist 2 Pufferlängen groß, erster Pufferinhalt wird reingeschrieben, zweiter Pufferinhalt wird reingeschrieben, dritter wird reingeschrieben mit Überschreiben des ersten, vierter wird reingeschrieben mit Überschreiben des zweiten, etc). Das nennt man scheinbar "linear"? So meinst du es aber vermutlich nicht, sondern eben dynamisch mit Lese- und Schreibzeigern, von denen ich aber (bisher) nichts verstehe/kenne.

Aber: Ist das notwendig? Reicht für meine Anwendung ein linearer Ringpuffer nicht völlig aus?

Folgende Idee: Für die Verarbeitung ist es ja nicht notwendig, dass ich so viele "Vergangenheitswerte" mitnehme. Es würde, um zB den Knick beim Intergieren zu vermeiden, völlig ausreichen jeweils den Pufferinhalt vom letzten Durchlauf mitzunehmen. Ich muss hier ja sowieso begrenzen, weil sonst in der Verarbeitung viel zu viele Daten ankommen und die Schleifengeschwindigkeit mit zunehmender Datenmenge ins unendliche geht.
Also: "Manueller Ringpuffer". Dh, immer nur den aktuellen Pufferinhalt und den vom Durchlauf zuvor in die Verarbeitung schicken, dort verarbeiten, im Graf nur den letzten anzeigen und die Daten (falls Speicherung gewünscht) dann in ein sehr groß initialisiertes Array schicken, welches so mit der Zeit aufgefüllt wird. Vor der Speicherung evtl noch den leeren Rest abschneiden und das wars.

Aber wahrscheinlich habe ich es doch noch nicht verstanden und auch hier ist wieder ein Denkfehler drin? -_-

@Datentypen:
Gut, da werde ich dann wohl leider nicht viel einsparen können. Danke für die Erklärung.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.10.2009, 16:48
Beitrag #14

Malte84 Offline
LVF-Grünschnabel
*


Beiträge: 26
Registriert seit: May 2009

8.5
2008
de

45897
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
Hm, ich habs jetzt mal so gemacht. Aber wenn ich mit 3 MHz abtaste, läuft mir trotzdem der Speicher voll (Auslagerungsdatei). Diese wird auch nicht geleert, wenn ich das Programm neu starte.
Ich verstehe nicht wieso das ist... Das Array wird mit der Dimension 2*Puffergröße initialisiert und dann immer nur mit replace neu befüllt. Was wird da so groß? Und vor allem, wieso bleibt die Auslagerungsdatei auch nach Programmende so groß? Ist das ein Windows-Problem? (Windows XP Prof mit SP3 hier)
Datenspeicherung in txt-Datei ist deaktiviert (wenn kein Haken gesetzt ist, laufen die Daten in der entsprechenden Case-Struktur einfach ins Leere und sollten daher nicht im Speicher behalten werden. Oder werden sie es an dieser Stelle aus irgendeinem Grund doch?)

Hach, schwierig...
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.10.2009, 18:32 (Dieser Beitrag wurde zuletzt bearbeitet: 02.10.2009 18:37 von IchSelbst.)
Beitrag #15

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.689
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
' schrieb:Ok, vermutlich habe ich eine falsche Vorstellung vom Ringpuffer. Bisher habe ich mir den manuell vorgestellt (Array ist 2 Pufferlängen groß, erster Pufferinhalt wird reingeschrieben, zweiter Pufferinhalt wird reingeschrieben, dritter wird reingeschrieben mit Überschreiben des ersten, vierter wird reingeschrieben mit Überschreiben des zweiten, etc). Das nennt man scheinbar "linear"? So meinst du es aber vermutlich nicht, sondern eben dynamisch mit Lese- und Schreibzeigern, von denen ich aber (bisher) nichts verstehe/kenne.
Mit linear hab ich gemeint: Hat einen Anfang immer bei 0 und ein Ende immer bei MaxLength-1. (Das ergibt dann einen "linearen Pfeil", der immer bei 0 beginnt in in Richtung Ende kuckt und MaxLength lang ist).
Ein Ringpuffer ansich hat - wie eben ein Ring, also ein Kreis - keinen Anfang und kein Ende, (respektive ist der Anfang immer mit dem Ende identisch, wenn der Puffer ganz voll ist). Anfang und Ende werden festgelegt durch die beiden Zeiger "Lese ab hier" und "Schreibe ab hier". Außerdem müssen die Teile, die in den Puffer geschrieben werden sollen, nicht zwangsläufig alle gleich lang sein. Bei einen Ringpuffer muss auch folgendes Problem beachtet werden: Der Ringpuffer selbst ist organisiert als linearer Speicherbereich - also mit Anfang und Ende. Der Ringpuffermanager muss sich nun darum kümmern, dass nicht über das "lineare Ende" hinausgeschrieben werden darf, sondern dass ein Umbruch auf den linearen Anfang gemacht werden muss.

Zitat:Aber: Ist das notwendig? Reicht für meine Anwendung ein linearer Ringpuffer nicht völlig aus?
Wenn du alles im Griff hast, kannst du selbstverständlich auch einen optimierten Ringpuffer verwenden. So wie du gesagt hast: Der Ringpuffer ist so groß wie zwei Datensätze, die einfach wechselweise überschrieben werden. Aber vorsicht hier: Die neuen Datensätze müssen immer die gleiche Größe haben (was selbstverständlich möglich ist, wenn man mit dem DaqMX immer eine feste Zahl ausliest)

Zitat:Folgende Idee: Für die Verarbeitung ist es ja nicht notwendig, dass ich so viele "Vergangenheitswerte" mitnehme. Es würde, um zB den Knick beim Intergieren zu vermeiden, völlig ausreichen jeweils den Pufferinhalt vom letzten Durchlauf mitzunehmen. Ich muss hier ja sowieso begrenzen, weil sonst in der Verarbeitung viel zu viele Daten ankommen und die Schleifengeschwindigkeit mit zunehmender Datenmenge ins unendliche geht.
Also: "Manueller Ringpuffer". Dh, immer nur den aktuellen Pufferinhalt und den vom Durchlauf zuvor in die Verarbeitung schicken, dort verarbeiten, im Graf nur den letzten anzeigen und die Daten (falls Speicherung gewünscht) dann in ein sehr groß initialisiertes Array schicken, welches so mit der Zeit aufgefüllt wird. Vor der Speicherung evtl noch den leeren Rest abschneiden und das wars.
Aber wahrscheinlich habe ich es doch noch nicht verstanden und auch hier ist wieder ein Denkfehler drin?
Wie, wo soll hier ein Denkfehler sein? Tongue
Jetzt, als du erklärt hast, was du brauchst und was du nicht brauchst, sehe ich gleich, dass das auch so geht. Es könnte auch noch so gehen: Du hast drei Arrays parallel laufen. Zwei der Länge MaxLength (M1, M2) und eines der Länge 2*MaxLength (MM). Außerdem gibt es eine Boolsche Variable M?, die mit jedem DaqMX-Rd getoggelt wird. Ist M? true, wird M1 überschrieben und MM ergibt sich aus M2+M1. Ist M? false, wird M2 überschieben und MM ergibt sich aus M1+M2. Beachte: Alle drei Arrays sind initialisiert und werden nur mit Replace ersetzt.

Zitat:@Datentypen: Gut, da werde ich dann wohl leider nicht viel einsparen können.
Jetzt hast du's aber schriftlich und kannst nachweisen, warum du so viel Speicher brauchst.



Zitat:Und vor allem, wieso bleibt die Auslagerungsdatei auch nach Programmende so groß? Ist das ein Windows-Problem? (Windows XP Prof mit SP3 hier)
JaNein.
Wenn du alles so gemacht hast wie erklärt, sollte es nicht zu solchen Problemen kommen. Speichermanager sind immer sehr kompliziert. Wer (LV oder Win32) da genau wo seine Finger drinnen hat, weis hier nur einer. Normalerweise würde ich aber sagen, dass LV, also dein Programm daran schuld ist (einen speziellen Fehler in LV, den du gerade gefunden hast, schließen wird vorerst aus genauso wie einen in WinXP).
Der Fehler muss nicht zwangsläufig von der Array-Geschichte kommen, die hier gerade diskutiert wird. Möglicherweise generierst du ständig Handle und schließt sie nicht wieder. Das führt früher oder später (bei 3MHz eher früher) zu einen Überlastung des Systems.

Kannst du mal ein Bild vom Blockdiagramm mit den Arrays und den Datenflüssen davor machen? Vielleicht sehe ich ja was.

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
05.10.2009, 13:00
Beitrag #16

Malte84 Offline
LVF-Grünschnabel
*


Beiträge: 26
Registriert seit: May 2009

8.5
2008
de

45897
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
@Ringpuffer:
Alles klar. Dann brauche ich wohl keinen dynamischen Ringpuffer, denn ich lese eine feste Zahl an Samples aus.

@programmiertechnische Umsetzung des Ringpuffers:
Zitat:Es könnte auch noch so gehen: Du hast drei Arrays parallel laufen. Zwei der Länge MaxLength (M1, M2) und eines der Länge 2*MaxLength (MM). Außerdem gibt es eine Boolsche Variable M?, die mit jedem DaqMX-Rd getoggelt wird. Ist M? true, wird M1 überschrieben und MM ergibt sich aus M2+M1. Ist M? false, wird M2 überschieben und MM ergibt sich aus M1+M2. Beachte: Alle drei Arrays sind initialisiert und werden nur mit Replace ersetzt.
Hört sich gut an.
Bisher habe ich das mit einer Case-Struktur gelöst, die durch den Schleifenzähler gesteuert wird. Also erst wird ein Array initialisiert, das die Länge 2*Samplepuffer hat. Im ersten Durchlauf wird dann die erste Sampleladung zweimal hintereinander in dieses Array gespeichert. Im zweiten Durchlauf wird die neue Sampleladung an die zweite Position in dem Array gespeichert und ab dem 3. Durchlauf werden immer erst die alten Daten von Position 2 mittels Schieberegister an Position 1 verschoben (ersetzt) und dann die neuen Daten an Position 2 ersetzt. Ich hoffe man versteht, was ich meine...

Zur Verdeutlichung der Screenshot...

Danke mal wiederSmile


Angehängte Datei(en) Thumbnail(s)
   
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
05.10.2009, 16:12
Beitrag #17

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.689
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
' schrieb:Im ersten Durchlauf wird dann die erste Sampleladung zweimal hintereinander in dieses Array gespeichert. Im zweiten Durchlauf wird die neue Sampleladung an die zweite Position in dem Array gespeichert und ab dem 3. Durchlauf werden immer erst die alten Daten von Position 2 mittels Schieberegister an Position 1 verschoben (ersetzt) und dann die neuen Daten an Position 2 ersetzt.
Ich hoffe man versteht, was ich meine...
Ja, verstehe ich.

Hier ein Ansatz dieses Verfahren zu optimieren. Versuch mal folgendes:

Nimm eine While-Schleife mit einem (1) Schieberegister. Die While-Schleife macht gar nichts. Lediglich das Schieberegister ist durchverbunden. Jetzt ziehst du das Schieberegister nach unten auf (Feature: Schieberegister!) - und siehe da nach der While-Schleife hast du zwei Arrays. Mit genau der Funktionalität die du haben willst. Noch Addieren (Replace) und gut. Vorteil: Das Verschieben von 2 nach 1 geht automatisch. Kannst du das mal probieren?


Was macht denn dein Speicherüberlauf?

Ich sehe in deinem Bild eine While-Schleife mit Autoindizierung. Autoindizierung ist nichts anderes als "An Array anhängen" - mit allen Nachteilen des Speichermanagers.

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
05.10.2009, 16:13 (Dieser Beitrag wurde zuletzt bearbeitet: 05.10.2009 16:15 von Malte84.)
Beitrag #18

Malte84 Offline
LVF-Grünschnabel
*


Beiträge: 26
Registriert seit: May 2009

8.5
2008
de

45897
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
Ach wie blöd... Ich habe mir gerade nochmal meine Methode zur Datenspeicherung angeguckt... Ich gehe mit den Daten aus der While-Schleife und nutze die Autoinidzierung. Dass hier die gesamten Daten aller Schleifendurchläufe anfallen, ist ja völlig klar. Und die gehen in die Auslagerungsdatei...
Na gut, also werde ich das mal umbauenWink

Edit: Jetzt haben wir zeitgleich gepostet... Immerhin habe ich meinen Fehler selbst erkannt... Deine Methode werde ich testen, nachdem ich das oben genannte Problem beseitigt habe. Denn Deine Lösung ist glaube ich nochmal performanter...
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
05.10.2009, 18:35
Beitrag #19

Malte84 Offline
LVF-Grünschnabel
*


Beiträge: 26
Registriert seit: May 2009

8.5
2008
de

45897
Deutschland
Grundkonzept einer Datenerfassung/Auswertung
Ich habe jetzt noch ein paar Dinge geändert, so dass ich leider nicht mehr dazu gekommen bin deine Methode auszuprobieren.
Es läuft jetzt aber stabil, auch im 3 MHz Bereich. Werde deine Methode in den nächsten Tagen trotzdem mal ausprobieren.

Nochmal ein großes Dankeschön für die vielen und wirklich guten Tipps!
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
30
Antwort schreiben 


Möglicherweise verwandte Themen...
Themen Verfasser Antworten Views Letzter Beitrag
Question Auswertung von Schwellwerten / Aufzeichnung in TDMS ZwergNase 3 3.940 12.08.2019 19:57
Letzter Beitrag: GerdW
  Datenerfassung mit einer zeitgesteuerten Schleife DM_94 16 10.646 25.07.2018 10:20
Letzter Beitrag: DM_94
  Auswertung Drehgeber mit NI 9401 BenutzernameNO 6 6.594 29.08.2016 13:25
Letzter Beitrag: GerdW
  Datenerfassung cDAQ + NI9203 keine synchrone Datenerfassung dieseldunst 5 6.539 24.06.2016 14:49
Letzter Beitrag: jg
  Datenerfassung und Auswertung Rajesh 9 7.947 09.06.2015 07:40
Letzter Beitrag: wladimir s
  Laufzeitprobleme; Auswertung Lifter 7 6.274 27.11.2013 21:33
Letzter Beitrag: jg

Gehe zu: