My application saves data in a .txt file. I have created a progress bar to indicate the progress of the file writing up to 100%. However, when the program runs, the screen no longer refreshes until the writing in the file is completed.
I was wondering if there is a way to give an update on the screen through a program line.
The program writes the entire file in a loop. So I made a second program option without the loop, where it writes one part at each scan, but even then the progress bar does not update. Why does this happen?
PROGRAM SALVA_LEIT_WTXT
VAR
IP: STRING := '192.168.0.1';
// TRANSITION OF START OF WRITING
TR_SSALV: R_TRIG;
Date_Time: RTCLK.GetDateAndTime;
// YEAR
ANO: UINT;
// MONTH
MES: UINT;
// DAY
DIA: UINT;
// HOUR
HORA: UINT;
// MINUTE
MINUTO: UINT;
// SECONDS
SEGUNDO: UINT;
// STRING YEAR
STR_ANO: STRING;
// STRING MONTH
STR_MES: STRING;
// STRING DAY
STR_DIA: STRING;
// STRING HOUR
STR_HORA: STRING;
// STRING MINUTE
STR_MINUTO: STRING;
sFileName: CAA.FILENAME;
// SIZE OF STRING
TAM_STR: INT;
// DATA VALUE CONVERTED TO STRING
VAL_STRING2: STRING;
// STRING OF TIME
TEMPO_STRING: STRING;
LOOP: INT;
txt_Virg: STRING := ',';
txt_Fim_Cab: STRING := '}';
txt_Tempo: STRING := 'TIME:';
txt_IP: STRING := '{IP:';
udiWriteError1 : RTS_IEC_RESULT;
udiCloseError1 : RTS_IEC_RESULT;
xText_Write: STRING(10000);
udiWrite : UDINT;
udiOpenError1 : RTS_IEC_RESULT;
hFile : RTS_IEC_HANDLE := RTS_INVALID_HANDLE;
// WRITE FILE
MESCR: BOOL;
MDATA: BOOL;
// TRANSITION OF END OF WRITING
TR2_NSSALV: F_TRIG;
LOOP2: UINT;
// PERCENTAGE OF WRITING TO PROGRESS BAR
RPERC: REAL;
// TRANSITION OF START
TR_INIC: R_TRIG;
// SAVE
SSALV: BOOL;
// TABLE OF TIMES OF DATA STORED TO WRITE TO TXT
TEMPO: ARRAY[1..10000] OF UDINT;
// STORED DATA TO WRITE TO TXT
MSG_COM: ARRAY[1..10000, 1..5008] OF BYTE;
END_VAR
// THIS PROGRAM WRITES THE FULL TXT FILE IN A LOOP, AND THE PROGRESS BAR IN THE SCREEN DOESN`T UPDATE.
// (IF I PUT THE PROGRAM IN STEP-BY-STEP, THE PROGRESS BAR UPDATES)
TR_SSALV(CLK:=SSALV); IF TR_SSALV.Q THEN MESCR:=TRUE; END_IF; // SET BIT OF STARTING OF FILE WRITING
TR2_NSSALV(CLK:=MESCR);
IF TR2_NSSALV.Q THEN udiCloseError1:= SysFileClose(hFile:= hFile); END_IF; //Close the file at the end
//DEFINE THE FILE NAME AND DIRECTORY
IF MESCR AND NOT Date_Time.xDone THEN
GVL.ESCO := FALSE;
Date_Time(xExecute:= TRUE);
DTU.DTSplit(dtDateAndTime:= Date_Time.dtDateAndTime, puiYear:=ADR(ANO), puiMonth:= ADR(MES), puiDay:= ADR(DIA), puiHour:= ADR(HORA), puiMinute:= ADR(MINUTO), puiSecond:= ADR(SEGUNDO));//PEGA DADOS DE DATA E HORA
STR_ANO := CONCAT(UINT_TO_STRING(ANO),''); STR_MES := CONCAT(UINT_TO_STRING(MES),''); STR_DIA := CONCAT(UINT_TO_STRING(DIA),''); STR_HORA := CONCAT(UINT_TO_STRING(HORA),''); STR_MINUTO := CONCAT(UINT_TO_STRING(MINUTO),'_');
sFileName := CONCAT(STR_ANO,STR_MES); sFileName := CONCAT(sFileName,STR_DIA); sFileName := CONCAT(sFileName,STR_HORA); sFileName := CONCAT(sFileName,STR_MINUTO); sFileName := CONCAT(sFileName,UINT_TO_STRING(SEGUNDO)); sFileName := CONCAT(sFileName,'.txt');
sFileName := CONCAT('C:\Laser\Gravados\', sFileName);
hFile:= SysFileOpen(szFile:= sFileName, am:= ACCESS_MODE.AM_WRITE_PLUS, pResult:= ADR(udiOpenError1));
MDATA := FALSE;
IF Date_Time.xError THEN
//erro
END_IF
END_IF
//STARTING STRING VARIABLE
TR_INIC(CLK := Date_Time.xDone);
IF TR_INIC.Q THEN xText_Write := ''; END_IF;
//MOUNTING THE PACKAGE STRING AND WRITING TO TXT
IF MESCR AND Date_Time.xDone THEN
FOR LOOP2 := 1 TO 3000 BY 1 DO
RPERC := 100.0 * (UINT_TO_REAL(LOOP2) / 3000.0); //PERCENT OF PROGRESS BAR
//IS THERE A WAY TO CALL HERE A SCREEN UPDATE BY PROGRAM LINE?????????????????????????????
StrConcatA(pstFrom:= ADR(txt_IP), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(IP), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(txt_Virg), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(txt_Tempo), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
TEMPO_STRING := UDINT_TO_STRING(TEMPO[LOOP2]);
StrConcatA(pstFrom:= ADR(TEMPO_STRING), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(txt_Fim_Cab), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
FOR LOOP:= 1 TO 5008 BY 1 DO
VAL_STRING2 := INT_TO_STRING(MSG_COM[LOOP2,LOOP]);
StrConcatA(pstFrom:= ADR(VAL_STRING2), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
IF LOOP < 5008 THEN StrConcatA(pstFrom:= ADR(txt_Virg), pstTo:= ADR(xText_Write), iBufferSize:= 10000); END_IF;
TAM_STR := LEN(xText_Write);
IF TAM_STR >= 200 THEN
IF hFile <> RTS_INVALID_HANDLE THEN
udiWrite:= SysFileWrite(hFile:= hFile, pbyBuffer:= ADR(xText_Write), ulSize:= INT_TO_UDINT(LEN(xText_Write)), pResult:= ADR(udiWriteError1));
xText_Write := '';
END_IF
END_IF
END_FOR;
END_FOR;
Yes. This is true. But in fact I would like my program with priority over screen. I understood that with 1 ms of ciclic interval, my program takes all processment and the screen doesn`t update even when the program is not in a loop. Then, my question is: Is there a way to call a screen update by program?
Thank you by your reply!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
A FOR loop might be the fastest way to save the file but as you've noticed it drastically increases cycle time for that 1 cycle you are saving a file. This means that other lower priority tasks get put on hold. You can get creative with creating a separate task for saving the files that will help speed up the saving process if you don't want to lock up the system.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Even when not in a loop, I have the same problem unless I rise up the interval of ciclic time to over 20ms. But this is not desired....
However, my final project would be with the multi-core codesys. Then, I think this wouldn't be a problem to me, once I can put the TXT file program in a separate core. I will wait to buy it and then I will reanalize this issue.
Thanks!!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My application saves data in a .txt file. I have created a progress bar to indicate the progress of the file writing up to 100%. However, when the program runs, the screen no longer refreshes until the writing in the file is completed.
I was wondering if there is a way to give an update on the screen through a program line.
The program writes the entire file in a loop. So I made a second program option without the loop, where it writes one part at each scan, but even then the progress bar does not update. Why does this happen?
PROGRAM SALVA_LEIT_WTXT
VAR
IP: STRING := '192.168.0.1';
// TRANSITION OF START OF WRITING
TR_SSALV: R_TRIG;
Date_Time: RTCLK.GetDateAndTime;
// YEAR
ANO: UINT;
// MONTH
MES: UINT;
// DAY
DIA: UINT;
// HOUR
HORA: UINT;
// MINUTE
MINUTO: UINT;
// SECONDS
SEGUNDO: UINT;
// STRING YEAR
STR_ANO: STRING;
// STRING MONTH
STR_MES: STRING;
// STRING DAY
STR_DIA: STRING;
// STRING HOUR
STR_HORA: STRING;
// STRING MINUTE
STR_MINUTO: STRING;
sFileName: CAA.FILENAME;
// SIZE OF STRING
TAM_STR: INT;
// DATA VALUE CONVERTED TO STRING
VAL_STRING2: STRING;
// STRING OF TIME
TEMPO_STRING: STRING;
LOOP: INT;
txt_Virg: STRING := ',';
txt_Fim_Cab: STRING := '}';
txt_Tempo: STRING := 'TIME:';
txt_IP: STRING := '{IP:';
udiWriteError1 : RTS_IEC_RESULT;
udiCloseError1 : RTS_IEC_RESULT;
xText_Write: STRING(10000);
udiWrite : UDINT;
udiOpenError1 : RTS_IEC_RESULT;
hFile : RTS_IEC_HANDLE := RTS_INVALID_HANDLE;
// WRITE FILE
MESCR: BOOL;
MDATA: BOOL;
// TRANSITION OF END OF WRITING
TR2_NSSALV: F_TRIG;
LOOP2: UINT;
// PERCENTAGE OF WRITING TO PROGRESS BAR
RPERC: REAL;
// TRANSITION OF START
TR_INIC: R_TRIG;
// SAVE
SSALV: BOOL;
// TABLE OF TIMES OF DATA STORED TO WRITE TO TXT
TEMPO: ARRAY[1..10000] OF UDINT;
// STORED DATA TO WRITE TO TXT
MSG_COM: ARRAY[1..10000, 1..5008] OF BYTE;
END_VAR
// THIS PROGRAM WRITES THE FULL TXT FILE IN A LOOP, AND THE PROGRESS BAR IN THE SCREEN DOESN`T UPDATE.
// (IF I PUT THE PROGRAM IN STEP-BY-STEP, THE PROGRESS BAR UPDATES)
TR_SSALV(CLK:=SSALV); IF TR_SSALV.Q THEN MESCR:=TRUE; END_IF; // SET BIT OF STARTING OF FILE WRITING
TR2_NSSALV(CLK:=MESCR);
IF TR2_NSSALV.Q THEN udiCloseError1:= SysFileClose(hFile:= hFile); END_IF; //Close the file at the end
//DEFINE THE FILE NAME AND DIRECTORY
IF MESCR AND NOT Date_Time.xDone THEN
GVL.ESCO := FALSE;
Date_Time(xExecute:= TRUE);
DTU.DTSplit(dtDateAndTime:= Date_Time.dtDateAndTime, puiYear:=ADR(ANO), puiMonth:= ADR(MES), puiDay:= ADR(DIA), puiHour:= ADR(HORA), puiMinute:= ADR(MINUTO), puiSecond:= ADR(SEGUNDO));//PEGA DADOS DE DATA E HORA
STR_ANO := CONCAT(UINT_TO_STRING(ANO),''); STR_MES := CONCAT(UINT_TO_STRING(MES),''); STR_DIA := CONCAT(UINT_TO_STRING(DIA),''); STR_HORA := CONCAT(UINT_TO_STRING(HORA),''); STR_MINUTO := CONCAT(UINT_TO_STRING(MINUTO),'_');
sFileName := CONCAT(STR_ANO,STR_MES); sFileName := CONCAT(sFileName,STR_DIA); sFileName := CONCAT(sFileName,STR_HORA); sFileName := CONCAT(sFileName,STR_MINUTO); sFileName := CONCAT(sFileName,UINT_TO_STRING(SEGUNDO)); sFileName := CONCAT(sFileName,'.txt');
sFileName := CONCAT('C:\Laser\Gravados\', sFileName);
hFile:= SysFileOpen(szFile:= sFileName, am:= ACCESS_MODE.AM_WRITE_PLUS, pResult:= ADR(udiOpenError1));
MDATA := FALSE;
IF Date_Time.xError THEN
//erro
END_IF
END_IF
//STARTING STRING VARIABLE
TR_INIC(CLK := Date_Time.xDone);
IF TR_INIC.Q THEN xText_Write := ''; END_IF;
//MOUNTING THE PACKAGE STRING AND WRITING TO TXT
IF MESCR AND Date_Time.xDone THEN
FOR LOOP2 := 1 TO 3000 BY 1 DO
RPERC := 100.0 * (UINT_TO_REAL(LOOP2) / 3000.0); //PERCENT OF PROGRESS BAR
//IS THERE A WAY TO CALL HERE A SCREEN UPDATE BY PROGRAM LINE?????????????????????????????
StrConcatA(pstFrom:= ADR(txt_IP), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(IP), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(txt_Virg), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(txt_Tempo), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
TEMPO_STRING := UDINT_TO_STRING(TEMPO[LOOP2]);
StrConcatA(pstFrom:= ADR(TEMPO_STRING), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
StrConcatA(pstFrom:= ADR(txt_Fim_Cab), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
FOR LOOP:= 1 TO 5008 BY 1 DO
VAL_STRING2 := INT_TO_STRING(MSG_COM[LOOP2,LOOP]);
StrConcatA(pstFrom:= ADR(VAL_STRING2), pstTo:= ADR(xText_Write), iBufferSize:= 10000);
IF LOOP < 5008 THEN StrConcatA(pstFrom:= ADR(txt_Virg), pstTo:= ADR(xText_Write), iBufferSize:= 10000); END_IF;
TAM_STR := LEN(xText_Write);
IF TAM_STR >= 200 THEN
IF hFile <> RTS_INVALID_HANDLE THEN
udiWrite:= SysFileWrite(hFile:= hFile, pbyBuffer:= ADR(xText_Write), ulSize:= INT_TO_UDINT(LEN(xText_Write)), pResult:= ADR(udiWriteError1));
xText_Write := '';
END_IF
END_IF
END_FOR;
END_FOR;
END_IF
Hello sir,
could it be that in your project the visu_task has a lower priority than the task you use to write to the file?
Best regards,
Marcel
Yes. This is true. But in fact I would like my program with priority over screen. I understood that with 1 ms of ciclic interval, my program takes all processment and the screen doesn`t update even when the program is not in a loop. Then, my question is:
Is there a way to call a screen update by program?
Thank you by your reply!
Hello sir,
no there is no public way to force a screen update.
Even if there would be a way, if the VISU_TASK gets no CPU-time, it cannot paint.
Best regards,
Marcel
Do you need to use FOR loops? I would highly consider changing it to a CASE statement so that your program can continue to cycle properly. A good example can be found in the help: https://help.codesys.com/webapp/Examples;product=CAA_FILE;version=3.5.13.0
A FOR loop might be the fastest way to save the file but as you've noticed it drastically increases cycle time for that 1 cycle you are saving a file. This means that other lower priority tasks get put on hold. You can get creative with creating a separate task for saving the files that will help speed up the saving process if you don't want to lock up the system.
Even when not in a loop, I have the same problem unless I rise up the interval of ciclic time to over 20ms. But this is not desired....
However, my final project would be with the multi-core codesys. Then, I think this wouldn't be a problem to me, once I can put the TXT file program in a separate core. I will wait to buy it and then I will reanalize this issue.
Thanks!!