How to move data from cells in a cell in a destinct column (importing CoDeSys variables)

3 views (last 30 days)
Hi All
I have a challenge of reading PLC (CoDeSys IEC 61131) variables from a text file and putting them into an array(:,4). Here is an example of the formatting:
VAR_GLOBAL PERSISTENT
// Default Interfaces
g_stCAL : ST_GLOBAL_CAL; // Calibration interface
g_stCFG : ST_GLOBAL_CFG := 10; //test for dimensions // Configuration interface
g_stDAT : ST_GLOBAL_DAT; // Statistical data interface
g_stOPT : ST_GLOBAL_OPT; // Option interface
g_stSET : ST_GLOBAL_SET; // Settings interface
g_nLifetimePlcRun : ULINT; // [ms] Total time the PLC is running during it's life time
END_VAR
The variables are grouped within VAR_xxx and END_VAR. The formating is like <var_name>:<data_type> := <initial_value>; // <comment> Within the file there are multiple groups of variable types. So VAR_GLOBAL PERSISTENT / VAR_GLOBAL CONSTANT / VAR_GLOBAL but in my case they can all be added to the same array. The following I already have:
01: fileID = fopen(iFile,'r');
02: TestStruct = fscanf(fileID,'%c');
03: [VarIdxStart,VarIdxStop] = regexp(TestStruct,'VAR_.+?\r\n') % Find locations of 'VAR_xxx'
04: [EndIdxStart,EndIdxStop] = regexp(TestStruct,'END_VAR') % Find locations of 'END_VAR'
05: Result = cell(1,4); % Initialise 'name' 'datatype' 'initial value' 'comment'
06: for idx = 1 : max(size(VarIdxStart))
07: Variables = splitlines(extractBetween(TestStruct,VarIdxStop(idx),(EndIdxStart(idx)-1))); % Get variables and put into list
08: Variables = Variables(~cellfun('isempty',Variables)); % Remove empty cells
09: Variables = Variables(cellfun(@(tmp) contains(tmp,{':' ';'}),Variables)); % Remove cell not containing variable declarations
10: initIdx = cellfun(@(tmp) contains(tmp,{':='}),Variables); % Indication that cell contains initialisation values
11: Variables = cellfun(@(tmp) split(tmp,{':=' ':' ';'})', Variables, 'UniformOutput', false); % Split on init value, colon or semicolon
12: Variables = cat(1,Variables{:}); % Move data into same level
13: Result = cat(1,Result,Variables); % Add found variables to
My problem lies in the 2nd variable 'g_stCFG'. For testing I have added an initialisation value (in this case not appropriate, but it is for testing). When the initialisation value is NOT present then the code produces the desired information, but in an array(:,3).
So I added line '10:' to have an index to the and added the ':=' condition to the split of line '11:' so the result looks like:
Variables(6x1)cell
'1x3 cell' => g_stCAL ST_GLOBAL_CAL // Calibration interface
'1x4 cell' => g_stCFG ST_GLOBAL_CFG 10 //test for dimensions
'1x3 cell' => g_stDAT ST_GLOBAL_DAT // Statistical data interface
'1x3 cell' ...
'1x3 cell' ...
'1x3 cell' => g_nLifetimePlcRun ULINT // [ms] Total time the PLC is running during it's life time
This causes that line '12:' results in a crash as the size of the cells are not equal. So how to 'extend' all entries that have a '1x3 cell' and preferely that the comment moves to the 4th row. Or does anybody have a quicker way of importing the data? Thanks for any help.
Ludo

Accepted Answer

Mathieu NOE
Mathieu NOE on 9 Nov 2023
hello
maybe this ?
where the lines in your file do not have initial values , I inserted a zero in 3rd position ; this is done in these two extra lines of code :
%%%% my mod %%%
mm = max(cellfun(@numel, Variables));
Variables = cellfun(@(tmp) [tmp(:,1:2) zeros(1, mm - numel(tmp)) tmp(:,3:end)], Variables, 'un', 0); % introduce a zero in 3rd position if needed
%%%%%%%%%%%%%%%
full code
iFile = 'test.txt'; % my test file
fileID = fopen(iFile,'r');
TestStruct = fscanf(fileID,'%c');
[VarIdxStart,VarIdxStop] = regexp(TestStruct,'VAR_.+?\r\n'); % Find locations of 'VAR_xxx'
[EndIdxStart,EndIdxStop] = regexp(TestStruct,'END_VAR'); % Find locations of 'END_VAR'
% Result = cell(1,4); % Initialise 'name' 'datatype' 'initial value' 'comment'
Result = {'name','datatype','initial value','comment'}; % Initialise 'name' 'datatype' 'initial value' 'comment'
for idx = 1 : max(size(VarIdxStart))
Variables = splitlines(extractBetween(TestStruct,VarIdxStop(idx),(EndIdxStart(idx)-1))); % Get variables and put into list
Variables = Variables(~cellfun('isempty',Variables)); % Remove empty cells
Variables = Variables(cellfun(@(tmp) contains(tmp,{':' ';'}),Variables)); % Remove cell not containing variable declarations
initIdx = cellfun(@(tmp) contains(tmp,{':='}),Variables); % Indication that cell contains initialisation values
Variables = cellfun(@(tmp) split(tmp,{':=' ':' ';'})', Variables,'UniformOutput' , false); % Split on init value, colon or semicolon
%%%% my mod %%%
mm = max(cellfun(@numel, Variables));
Variables = cellfun(@(tmp) [tmp(:,1:2) zeros(1, mm - numel(tmp)) tmp(:,3:end)], Variables, 'un', 0); % introduce a zero in 3rd position if needed
%%%%%%%%%%%%%%%
Variables = cat(1,Variables{:}); % Move data into same level
Result = cat(1,Result,Variables); % Add found variables to
end
my result so far :
  4 Comments
Ludo Houben
Ludo Houben on 10 Nov 2023
Yes, I wanted that but I already solved the 'STRING' part myself. I solved it with 'repmat'
cellfun(@(tmp) [tmp(:,1:2) repmat("",1, mm - numel(tmp)) tmp(:,3:end)], Variables, 'un', 0);
You can add any data in the field to add in that way. In my case an empty STRING, but whatever the user wants.
Cheers
Ludo

Sign in to comment.

More Answers (0)

Categories

Find more on PLC Code Generation Basics in Help Center and File Exchange

Products


Release

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!