LabVIEWForum.de - Gaspruefstand - Programm

LabVIEWForum.de

Normale Version: Gaspruefstand - Programm
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Seiten: 1 2
Hallo,
ich habe ein kleines LabVIEW-Projekt vor mir, um die letzte Woche meines Praktikums sinnvoll zu nutzen.
Ich habe ein bisschen LabVIEWerfahrung, aber eben nur ein bisschenSmile

Ich versuche es moeglichst kurz zu machen, damit eure Zeit nicht so beansprucht wirdBig Grin:

Das Programm soll ohne Details Folgendes koennen:[list]Eine Steuerdatei einlesen die Zeitschrittinformationen enthaelt, die dann umgesetzt werden in neun analoge Spannungen an den Gasflusscontrollern.<>
[st][list]kontinuierlich CAN schreiben und 10 Kanaele lesen (das Schreiben dient nur dazu damit der zugehoerige Sensor nicht abschaltet)<>
[st][list]kontinuierlich 16 analoge Signale lesen.<>
[st][list]Das Lesen der AI's soll mit konstanter Frequenz zwischen 1 und 10kHz moeglich sein. Die gelesenen Daten sollen gemittelt mit 1 - 100 Hz in eine Datei geschrieben werden.<>
[st][list]einen manuellen Modus zur Steuerng der Gasflusscontroller haben<>
[st]Das momentane Programm ist alt, verbuggt, wird nicht sauber beendet, verwendet kein DAQmx und kann kein CAN schreiben (momentan ist ein anderer Computer zusaetzlich an den CAN-Bus angeschlossen, der das CAN-Write uebernimmt um den Sensor im aktiven Zustand zu halten). Und es ist nur fuer niedrige Frequenzen ausgelegt.

Ich versuch mal meine Ueberlegungen bisher zu schildern:

Ich wuerde ein Mainloop verwenden, dass das Lesen der Steuerdatei und das Stellen der Controller uebernimmt. Hierzu wuerde ich einfach die Zeit mit GetTime abchecken und jedesmal wenn der Wert groesser ist, als "Startzeit plus Wert fuer naechsten Zeitschritt aus der Steuerdatei" die Spannung fuer die Controller aendern. Hier wuerde auch die manuelle Kontroller reinkommen. Wenn der User auf manual Mode stellt, wird die Zeit angehalten und man kann selber bissi rumspielen. Wenn man den manuellen Modus wieder ausschaltet, geht es in der Steuerdatei weiter. Saemtliche Informationen ueber Startzeit, Wartezeit, Spannungskonfiguration vor einschalten des manuellen Modus wuerde ich in lokalen Variablen oder in einem Cluster und einem Shiftregister ablegen.

In einem parallelem Loop wuerde ich CAN in einer Flat-Sequence-Structure Lesen und Schreiben lassen ab dem Moment wo das Programm gestartet wurde. Lasst uns dieses Loop als CAN-Loop bezeichnenSmile

In einem weiteren parallelem Loop (AI-Loop) soll nun das analoge Lesen und Mitteln stattfinden und wahrscheinlich waere es auch am schlausten hier die Dateiausgabe der Messwerte zu implementieren.

In dem aktuellen, alten, verbuggten Programm gibt es nur ein einziges Loop das alles uebernimmt. In dem Loop wird jedes Mal EIN Messwert von AI und CAN erfasst und in eine Datei geschrieben. Das Timing ist dementsprechend an die Samplefrequenz von der AI Karte gekoppelt. Das hat den Charme, dass es bei niedrigen Frequenzen ein eisernes Timing ohne Schwanungen ist. Und natuerlich den riesen Nachteil, dass man bei hoeheren Sampleraten kein korrektes Timing mehr hat, da nichts gepuffert wird und der PC einfach zu lang braucht um alles zu verarbeiten und jeden Wert in die Datei zu schreiben.

Hier kommen meine Probleme ins Spiel:

Ich weiss nicht so recht wie ich ein gutes Timing fuer mein AI-Loop machen kann. Bzw. brauch ich das ueberhaupt?
Ich wuerde die Messkarte auf kontinuierlich samplen mit 10kHz stellen und dann in meinem AI-Loop abhaenig von meiner gewuenschten Schreibfrequenz immer z.B. 100 Messwerte aus dem Puffer erfassen und verarbeiten. Sprich mitteln und in die Datei schreiben. Waere das OK oder hat das irgendwelche gravierenden Nachteile bzw. uebersehe ich hier was?

Die naechste Frage ist, wie schnell kann ich das CAN-Loop laufen lassen. Bzw. konkreter wie mache ich hier das Timing. Meine Idee ist bisher fuer das Loop: eine flat sequenz structure mit 1 x einen Wert schreiben, 1x einen Wert lesen, z.B. 20 ms warten
Ist das ok?
Die Daten vom CAN-Loop muessen dann natuerlich an das AI-Loop uebergeben werden. Nachdem diese Daten langsamer herein kommen als das AI-Loop ablaueft, wuerde ich zur Uebergabe eine lokale Variable fuer das Array mit den CAN Daten verwenden. Ein Notifier wuerde ja immer haengen und warten bis die Daten da sind. Dabei laueft der Puffer ja sofort ueber. Deshalb muesste man ein Timeout fuer 'Wait on Notification setzen'. Aber wie lang macht man das? 1 ms? 5 ms? Eine lokale Variable scheint mir deshalb besser geeignet, da ich ja nur an einer Stelle (im CAN-Loop) in sie schreibe.

Und die letzte Frage zu den bisherigen Ueberlegungen betrifft das Mainloop, wenn der User auf manuellen Modus umgestellt hat:
Hier werden ja nun irgendwelche Controls vom Frontpanel gelesen und in Stellsignale umgewandelt.An jeden Control gekoppelt ist eine Berechnung die ueber ein Schalten von Relais entscheidet. Langer Rede kurzer Sinn: Ich moechte, dass diese Berechnung nur dann stattfindet, wenn der User auch wirklich etwas an den Controls geaendert hat.
Meine Loesung bisher fuer so etwas, war jeden Controlwert mit einem Shiftregister durchzuschleifen (oder halt einen Cluster) und fuer jeden Wert zu ueberpruefen ob sich etwas zum Wert zuvor geaendert hat (und dann eben fuer jeden Wert eine Case-Strukture). Das ist sehr unuebersichtlich und gefaellt mir nicht. Gibts da bessere Methoden?

Ohweia, das ist jetzt doch laenger geworden als ich dachte. Danke fuer alle die bis hier durchgehalten habeSmile- und danke an die anderen natuerlich auchTongue

Ich wuerde mich ueber jeglichen Tipp, jegliche Ergaenzung, jegliche Korrektur und jegliche komplett neue, bessere Idee sehr freuen. DankeSmile

Andinger
Im Großen und Ganzen mach ich das auch immer so: Alles, was es gibt - AI, CAN, Temp, DigiIn etc. etc. - läuft in einer eigenen Task ("parallele While-Schleife"). Gesteuert wird jede Task über eine Queue. Daten zwischen Tasks (und MainLoop) werden per Melder und/oder Queues ausgetauscht

' schrieb:Ich weiss nicht so recht wie ich ein gutes Timing fuer mein AI-Loop machen kann. Bzw. brauch ich das ueberhaupt?
Jede Loop läuft mit (z.B.) 50ms. Dass die Sample-Rate 10kHz beträgt, ist was anderes. Die AI-Task hat einen internen Puffer, der für mindestens 100ms reicht. Da er alle 50ms ausgelesen wird, ist 100% Reserve da.

Zitat:Ich wuerde die Messkarte auf kontinuierlich samplen mit 10kHz stellen und dann in meinem AI-Loop abhaenig von meiner gewuenschten Schreibfrequenz immer z.B. 100 Messwerte aus dem Puffer erfassen und verarbeiten. Sprich mitteln und in die Datei schreiben. Waere das OK oder hat das irgendwelche gravierenden Nachteile bzw. uebersehe ich hier was?
Auch diese Methode ist prinzipiell geeignet. Nachteile fallen mir auf die Schnelle keine ein.

Zitat:Die naechste Frage ist, wie schnell kann ich das CAN-Loop laufen lassen.
Ich hab die Channel-API von NI verwendet.
Kannst du auch zwei Loops machen? Eine zum Senden und eine zum Lesen? Lesen geht fast wie AI: Can-Read kennt einen Lesepuffer. Senden ist auch einfach: Einfach einen Datensatz schreiben. Raster geht bis 1ms.

Zitat:Ein Notifier wuerde ja immer haengen und warten bis die Daten da sind. Dabei laueft der Puffer ja sofort ueber. Deshalb muesste man ein Timeout fuer 'Wait on Notification setzen'. Aber wie lang macht man das? 1 ms? 5 ms? Eine lokale Variable scheint mir deshalb besser geeignet, da ich ja nur an einer Stelle (im CAN-Loop) in sie schreibe.
Nein, nimm keine Lokale Variable sondern einen Melder.
Ein Melder ist ja wie eine Lokale Variable. An einer Stelle wird er beschrieben, an allen anderen gelesen. Du kannst einen Melder kontinuierlich auslesen - wie eine lokale Variable.


Zitat:Ich moechte, dass diese Berechnung nur dann stattfindet, wenn der User auch wirklich etwas an den Controls geaendert hat.
Meine Loesung bisher fuer so etwas, war jeden Controlwert mit einem Shiftregister durchzuschleifen (oder halt einen Cluster) und fuer jeden Wert zu ueberpruefen ob sich etwas zum Wert zuvor geaendert hat (und dann eben fuer jeden Wert eine Case-Strukture). Das ist sehr unuebersichtlich und gefaellt mir nicht. Gibts da bessere Methoden?
Event-Struktur !
Hey ist ja sehr nett von dir, des du es dir wirklich durchgelesen hast!! Und noch viel mehr danke fuers AntwortenBig Grin

Zitat:Ich hab die Channel-API von NI verwendet.
Kannst du auch zwei Loops machen? Eine zum Senden und eine zum Lesen? Lesen geht fast wie AI: Can-Read kennt einen Lesepuffer. Senden ist auch einfach: Einfach einen Datensatz schreiben. Raster geht bis 1ms.
Klar kann ich zwei Loops machen. Ich dachte nur, dass sich bei CAN lesen und schreiben gegenseitig beisst, weil es ja ein BUS ist. Ich dachte, wenn ich zwei Loops mache, muss ich ihnen gegenseitig immer mitteilen wann "sie duerfen" - und dann dachte ich, dass es mit einem Loop und ner Sequenz einfacher ist.
Oder wie genau hast du das gedacht?

Zitat:Ein Melder ist ja wie eine Lokale Variable. An einer Stelle wird er beschrieben, an allen anderen gelesen. Du kannst einen Melder kontinuierlich auslesen - wie eine lokale Variable.
Stimmt, stimmt. Ich vergas. Ich hatte zum Thema Melder extra vor zwei Wochen mal ein paar testVIs gemacht - hatte aber irgendwie etwas falsch in Erinnerung. Sehr gut.
Zitat:Event-Struktur !
Dacht ich mir, ich hatte schon profilaktisch am Freitag ein Tutorial dazu ausgedruckt, aber kam noch nicht zum lesenTongue
' schrieb:Ich dachte nur, dass sich bei CAN lesen und schreiben gegenseitig beisst, weil es ja ein BUS ist.
Jetzt, wo du's sagst. Aber: Es beisst sich nicht. Besser gesagt: Das System verkraftet das.

Der Canbus als solcher ist dafür ausgelegt, dass es mal sein kann, dass beide Teilnehmer gleichzeitg senden. Jeder der Teilnehmer merkt das dann und macht je nach seiner eigenen Adresese (respektive Wertigkeit) Sendewiederholungen. Datenverlust wird es also nicht geben.
Ok, zusammengefasst meinst du:
Zwei parallele CAN-Loops (eins zum Lesen, eins zum Senden) mit je z.B. 10 ms Wartezeit wird funktionieren?Smile

Ich werde es dann wohl mal angehenTongue
' schrieb:Zwei parallele CAN-Loops (eins zum Lesen, eins zum Senden) mit je z.B. 10 ms Wartezeit wird funktionieren?Smile
Das geht viel schöner: ohne explizite Wartezeit. Du kannst sowohl der CAN-Write-Task wie auch der CAN-Read-Task ein "Sample-Raster" vorgeben. Den Algorithmus in der jeweiligen Loop kann man dann Sample-Raster-unabhängig gestalten.

Funktionieren? Da sehe ich gar kein Problem. Ich weiß, die CAN-Library und LV können das ohne Probleme. Und dir trau ich jetzt ganz einfach mal zu, dass du ein entsprechend funktionsfähigen Programm schreiben kannst. Cool
Ehrlich gesagt, habe ich keine Ahnung von CAN und von SamplerasternSmile
Du ueberschaetzt mich grenzenlos fuerchte ichTongue.
Naja, ich habe ein bisschen rumprobiert und mir mal angeschaut wie es bisher so gehandhabt wurde
Das Problem ist wohl folgendes:

Alle benutzen hier zum Read Can Channels. Das muss unbedingt so bleiben, weil die Leute daran gewoehnt sind, da ihre Funktionen einzugeben. Channels kann man mit Tasks handhaben.

Fuer den Write-Befehl um den Sensor anzulassen muss ein Bitmuster uebertragen werden. z.B. 5F FF FF FF FF FF FF FF. Es muessen genau 8 Byte sein und es muss genau so ausschauen.

Mein Program
[attachment=24630] [Bild: lv71_img.jpg]

geht nicht, weil Frames und Channels nicht gleichzeitig existieren koennen. Das sagt LabVIEW. Das sagen die Menschen hier. Deshalb verwenden sie zwei PCs.
Ich bin der Meinung dass man 5F FF FF FF FF FF FF FF doch ohne grosse Probleme in einen Channel/Task umwandeln koennen muesste. Aber ich weiss nicht wieSmile

edit: hab gerade das hier gefunden:
http://joule.ni.com/nidu/cds/view/p/id/884/lang/en]

edit:
Ein Problem ist, dass diese VIs nicht mit LabVIEW 7.1 gehen. Koennte mir die jemand konvertieren? Das waere evtl. ein Anfang. Eine Randbemerkung vielleicht noch: Wie krieg ich den llbs in user libraries konvertiert?
' schrieb:Fuer den Write-Befehl um den Sensor anzulassen muss ein Bitmuster uebertragen werden. z.B. 5F FF FF FF FF FF FF FF. Es muessen genau 8 Byte sein und es muss genau so ausschauen.
Der Datenteil einer CAN-Bitschaft ist standardmäßig 64Bit lang. Diese 8 Byte sind also ein ganz normaler Datensatz.

Zitat:Ich bin der Meinung dass man 5F FF FF FF FF FF FF FF doch ohne grosse Probleme in einen Channel/Task umwandeln koennen muesste.
Du könntest folgendes machen: Erweitere das bestehende NCD-File (oder erstelle ein neues) um die Botschaft 0x96. Als Dateninhalt gibst du 8 U8 an. Dann kannst du eine Channel-Task machen, in der du alle 8 U8 auswählst. Und als Daten gibst du diese 8 Bytes an.


Achja,lv71ist eine ungute Version. Ich hab nämlich kein 8.0 und kann daher nicht auf 7.1 runterspeichern. Könnt ihr nix gescheites nehmen? 86 vielleicht? Ph34r
werde gleich ein NCD File erstellen und das testen.
die haben leider kein Geld hier momentan fuer eine hoehere LabVIEW Version. Und auch keinen Nutzen, denn keiner kennt sich wirklich aus.
Ich bin momentan vom Rang der LabVIEW Meister hier und wie du siehst hab ich auch keinen PlanRolleyes

was anderes:
Ich hab das mit dem Melder nochmal probiert.
[attachment=24645]
Problem: die Schleife wartet ja doch und liest nicht den selben Wert nochmal. Man sieht das daran dass der Counter nicht hochzaehlt.
D.h. diese Variante ist irgendwie doch ungeeignet zur Uebertragung von langsameren Daten in ein schnelles Loop, da dieses ja dann ungemein gebremst wird, weil immer gewartet wird.
Bevor ich jetzt ein Timeout und eine weiter Caseabfrage 'if timeout - use old value' verwende, ist es glaub ich doch uebersichtlicher mit lokalen variablen

Haben sie die Melder in LabVIEW8 wohl geaendert? Oder geh ich falsch damit um?
Ich kann im channel keinen Datentyp U8 auswaehlen. Nur Unsigned, Singed und IEEE Float.
Und 64 bit geht damit nicht, da kommt dieses nette x mit rotem Kreis. Maximal 52 bit steht als Fehler dabei.
Und wenn ich versuceh meine 96 FF FF FF FF FF FF FF mit Float zu machen geht das auch nicht, weil es dann irgendwie unendlich wird.

Was mach ich falsch?
[attachment=24648]

Auf der linken Seite sieht man es mit dem Example Programm fuer CAN Frames. Das geht einwandfrei. Der Sensor springt an und wenn ich es abschalte geht er sofort wieder aus.
Seiten: 1 2
Referenz-URLs