Twincat 3 CSV File nach bestimmten Angaben durchsuchen und nur diese lesen.

Wasabi85

Level-1
Beiträge
8
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo SPS Forum

Ich habe ein kleines Problem mit Twincat 3 und der CSV Geschichte.

Ein CSV File zu schreiben und dieses z.b. auf einen Stick zu laden funktioniert sehr gut. Nun möchte ich aber bestimmte Zeilen aus so einer Datei herauslesen und dessen Werte benutzen können.

Beispiel:

Ich habe 40 Zeilen(Programme) mit je 10 Werten. Jeder Wert soll in ein Array zurück geladen werden. Angaben wie z.b. Temperatur, Wasserstand, Endpunkte etc.

Wie stelle ich das nun am besten an eine CSV Datei zu öffnen und z.b. nach Programm 14 zu suchen. Und dann halt nur Programm 14 mit all seinen Daten zu laden?

Versucht habe ich es mit dem Beispiel von Beckhoff selbst wo in die CSV File gelesen und geschrieben wird. Mein Erfolg hält sich bisher leider sehr in Grenzen weil ich nicht mal genau weiss wo ich am besten ansätzen kann.

Ich komme nicht weiter und brauche dringend Hilfe.

Vielen Dank


Dominik
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi, Danke für die schnelle Antwort.

Wie genau müsste das den dann aussehen im Code? Wo genau müsste ich den mit diesem MemBufferReader ansetzen damit dieser richtig funktioniert?


Vielen Dank

Dominik
 
Ok Ich habe es nun mit FB_CSVMemBufferReader versucht. Das Problem was ich noch nicht verstehe ist nun wie ich dem Programm es klar machen kann wohin die Dateien wieder geladen werden sollen.
Ich habe nun einfach alles Rückwärts versucht.

Obendrein weiss ich noch nicht genau wie ich nun in diesem File nach einer gewissen Zeile suchen kann. Auch mag er meine Auflistung nicht richtig. nach Database[0, 5] sagt er das der Konstante Index 9 etc.. nicht in der Range von 0 bis 5 ist.

Wenn ich z.b. nach dem Namen P12 suche soll er dort stehen bleiben und alles in dieser Zeile in die richtigen Bereiche laden. Und die suche im CSV File beenden.

Code:
CASE step OF
	0:	(* Wait for rising edge at bRead variable *)
		IF bRead THEN
			bRead 	:= FALSE;
			bBusy 	:= TRUE;
			bError	:= FALSE;
			nErrId	:= 0;
			hFile	:= 0;
			nRow	:= 0;
			nColumn	:= 0;
			MEMSET( ADR( database ), 0, SIZEOF( database ) );
			step 		:= 1;
		END_IF


		
	1:	(* Open source file *)
		fbFileOpen(  bExecute := FALSE  );
		fbFileOpen( sNetId := sNetId, sPathName := sFileName, nMode := FOPEN_MODEREAD OR FOPEN_MODETEXT,(* Open file in TEXT mode! *)
					ePath := PATH_GENERIC, bExecute := TRUE );
		step := 2;


		
		
		
	2:(* Wait until open not busy *)
		fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
		IF NOT fbFileOpen.bBusy THEN
			IF NOT fbFileOpen.bError THEN
				step := 3;
			ELSE(* Error: file not found? *)
				step := 100;
			END_IF
		END_IF


	3:	(* Read single line (record) *)
		fbFileGets( bExecute := FALSE );
		fbFileGets( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
		step := 4;
 
	
	4:(* Wait until read not busy *)
		fbFileGets( bExecute := FALSE, bError => bError, nErrID => nErrID, sLine => sCSVLine );
		IF NOT fbFileGets.bBusy THEN
			IF NOT fbFileGets.bError THEN
				IF fbFileGets.bEOF THEN
					step := 10;(* End of file reached => Close source file *)
				ELSE


					(* F B_FileGets returns text line without the CR (carriage return) character.
					We have to restore the CR character (replace the $L character with $R$L characters) *)
					IF RIGHT( sCSVLine, 1 ) = '$L' THEN
						sCSVLine := REPLACE( sCSVLine, '$R$L', 2, LEN( sCSVLine ) );
					END_IF


					step := 5;
				END_IF
			ELSE(* Error *)
				step := 100;
			END_IF
		END_IF


	5:(* Parse single line (record) *)
		fbReader.eCmd := eEnumCmd_First;(* Read first field value *)
		REPEAT
			fbReader( pBuffer := ADR( sCSVLine ), cbBuffer := SIZEOF( sCSVLine ), getValue => sCSVField );
			
			IF fbReader.bOk THEN
				fbReader.eCmd := eEnumCmd_Next;(* Read next field value *)


				IF ( nRow <= MAX_CSV_ROWS ) THEN
					IF ( nColumn <= MAX_CSV_COLUMNS ) THEN
						database[nRow, nColumn] := CSVFIELD_TO_STRING( sCSVField, FALSE );(* TODO: Save or use the field value in your application *)
	GvAllg.sPrgNummer						:= 				 (database[0, 0]);								// Programmnummer 
	GvPara.iRezeptPG 						:= STRING_TO_INT (database[0, 1]);								// PH-Glas Rezeptur
	GvPara.aiTempGlas[GvPara.iRezeptPG]		:= STRING_TO_INT (database[0, 2]);								// Soll Temperatur PH-Glas	
	GvIn.iPyrometerB10In 					:= STRING_TO_INT (database[0, 3]);								// Ist Temperatur PH-Glas
	GvPara.iParm2TolTemp					:= STRING_TO_INT (database[0, 4]);								// Toleranz Temperatur PH-Glas
	GvIn.Glas_Oberflaeche 					:= STRING_TO_REAL (database[0, 5]);								// Schwellenerkennung Glasoberfläche
	GvPara.arTauchtiefe[GvPara.iRezeptPG] 	:= STRING_TO_REAL (database[0, 6]);								// Tauchtiefe
	GvPara.aiTauchzeit[GvPara.iRezeptPG] 	:= STRING_TO_INT (database[0, 7]);								// Tauchzeit
	GvPara.iRezeptGK 						:= STRING_TO_INT (database[0, 8]);								// Glasschaft Rezeptur
	GvPara.arFotodiode[GvPara.iRezeptGK] 	:= STRING_TO_REAL (database[0, 9]);								// Variation Glaserkennung		
	GvAllg.rVorwaermzeit_Umr 				:= STRING_TO_REAL (database[0, 10]);							// Vorwärmzeit
	GvPara.arPosGlasVor[GvPara.iRezeptGK] 	:= STRING_TO_REAL (database[0, 11]);							// Position Glas Vorwärmen
	GvPara.arPos_Ausbl[GvPara.iRezeptGK] 	:= STRING_TO_REAL (database[0, 12]);							// Position Kuppe Ausblasen 
	GvPara.arKuppengr[GvPara.iRezeptGK]		:= STRING_TO_REAL (database[0, 13]);							// Soll-Wert Kuppengrösse
	GvAllg.rKuppeIstwert 					:= STRING_TO_REAL (database[0, 14]);							// Ist-Wert Kuppengrösse
	GvPara.arTolKuppengr[GvPara.iRezeptGK]	:= STRING_TO_REAL (database[0, 15]);							// Toleranz Kuppengrösse
	GvPara.aiGlaslaenge[GvPara.iRezeptGK]	:= STRING_TO_INT (database[0, 16]);								// Glaslänge
	GvPara.rParm1Tiegelmax					:= STRING_TO_REAL (database[0, 17]);							// Endpunkt im Tiegel 			
	GvPara.iTimeOut							:= STRING_TO_DINT (database[0, 18]);							// Zeit Glaserkennung
	GvAllg.iKuppeCSV						:= STRING_TO_INT (database[0, 19]);								// Glas OK = 1 / NIcht OK = 0
	GvPara.rPAnteil1[GvPara.iRezeptGK] 		:= STRING_TO_REAL (database[0, 20]);							// P-Anteil für den PID Regler Glas formen 
	GvPara.rPAnteil2[GvPara.iRezeptGK]		:= STRING_TO_REAL (database[0, 21]);							// P-Anteil für den PID Regler Glas formen
	GvPara.rIAnteil1[GvPara.iRezeptGK]		:= STRING_TO_REAL (database[0, 22]);							// I-Anteil für den PID Regler Glas formen
	GvPara.rIAnteil2[GvPara.iRezeptGK]		:= STRING_TO_REAL (database[0, 23]);							// I-Anteil für den PID Regler Glas formen 	
	GvPara.iPowerAnteil1[GvPara.iRezeptGK]	:= STRING_TO_INT (database[0, 24]);								// Power-Anteil für den PID Regler Glas formen
	GvPara.iPowerAnteil2[GvPara.iRezeptGK] 	:= STRING_TO_INT (database[0, 25]);								// Power-Anteil für den PID Regler Glas formen
				END_IF
				 END_IF


				nColumn := nColumn + 1;(* Increment number of read columns *)
				IF fbReader.bCRLF THEN(* CRLF == TRUE => End of reacord reached *)
					nRow 		:= nRow + 1;(* Increment number of read records *)
					nColumn 	:= 0;(* Reset number of columns *)
				END_IF


			ELSE(* Error: End of record reached or all fields read *)
				step := 3;(* Try to read next line *)
			END_IF
		UNTIL NOT fbReader.bOk
		END_REPEAT


	10:	(* Close source file *)
		fbFileClose( bExecute := FALSE );
		fbFileClose( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
		step := 11;


	11:(* Wait until close not busy *)
		fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
		IF ( NOT fbFileClose.bBusy ) THEN
			hFile := 0;
			step := 100;
		END_IF


	100: (* Error or ready step => cleanup *)
		IF ( hFile <> 0 ) THEN
			step := 10; (* Close the source file *)
		ELSE
			bBusy := FALSE;
			step := 0;	(* Ready *)
		END_IF


END_CASE

Wie kann ich das nun realisieren.

Freundliche Grüsse

Wasabi85
 
Zurück
Oben