Crimson 3.1 Data Log Question

Bullzi

Lifetime Supporting Member
Join Date
Jun 2012
Location
Colorado
Posts
1,530
Hi Everyone,
Hope you all are safe and well.


I have a question about creating a Data Log snapshot in Crimson 3.1. I have created a HMI screen that shows the day of the month, and data for that day. See the attached screenshot. Each of column data is stored in the PLC as a array. So there is a total of 16 arrays with 32 elements each (I only use elements 1-31 for the days in the month).


What I want to do is create a log file on the SD card that is set up like the screen shot. I know how to create the file and how to trigger it but what I want to know is how to format the file so the arrays to be in the proper columns. I want to be able to import to a Excel file have everything lines up nicely.



What I want is 16 columns of data with 31 rows under it but what I am afraid will happen is I will end up with 496 columns with 1 row of data under each column.



Any thoughts on how to do this?
Thanks for any help you can provide!!

Monthly Detail.png
 
On the contents of your log file, each item will be a column. You can drag the items to re-order them.

The first column will be the date and the 2nd column will be the time, but after that, your columns will be whatever order you list the tags in your log file contents tab. Also note that the header for the column will be taken from the tag label.

The problem you will have is that not all months have the same number of days, and the field for Each File Holds is a constant (can't be set to an expression). I would probably make that field 365 and use an excel macro to parse the data by the month. You could probably write a script in Crimson to create these files too...that could get complicated, but should be reliable once you have the details sorted out.

EDIT: After re-reading, you already have data reserved in the PLC for all this data for a whole year. You can probably just create 12 logs, one for each month each with its own trigger bit or flag tag, then condition the triggers to only occur during the correct month. You will have some empty rows, but those can be ignored.

I think your date and time column will have the same data for each whole file (plus a couple seconds depending on how long the creation of the file takes). If your day of the month is also part of the PLC data, then that shouldn't be too much of an issue, just hide or delete the first two columns of the resulting csv file.
 
Last edited:
Scratch that

Too late to EDIT: scratch what I said up there...
I see your dilemma. I see two ways to deal with this, and the choice might depend on how the data is organized in the PLC as well as the HMI.

1) Custom logging. Write a program to read the data from the PLC and create a file. For the present month, I suppose this means replacing the file at whatever interval you decide.
2) Log live values and trigger at the end of each day. This means today's data doesn't show up in the file.
 
Create a comma separated file (.csv) and Excel will be able to open it with all the data in the right columns. Something like this, but will be full of errors:


Code:
// write data to comma separated files .csv

int rowCount = 1;
int targetFile;  //handle for targetFile
cstring targetLine;


targetFile = OpenFile(targetPath + targetFilename,1);

For (rowCount = 1, rowCount < 31, rowCount++){

     targetLine = ((IntToText(Column1Array(rowcount),10,2) + "," + (IntToText(Column2Array(rowcount),10,7) + "," + etc ;
     writefileline (targetFile, targetLine);
}

close targetFile
 
Save the log as a CSV file so for example
Col1, Col 2, Col3, col 4 (then add CR carriage return)
1,2,3,4 (CR)
2,23.4,56 (CR)
and so on... a comma separates the columns and a CR will separate the rows.
 
Thanks everyone for the help. I will try and write a program that will do this. I may be back for more help on the program but I want to see if I can make it work myself first. Got nothing but time on my hands there days anyway. :)
 
Here is what I have done so far. It is not finished by any means just what I am working with now.


Code:
// Create the file first
 File_Create_Success = CreateFile("/LOGS/MONTHLY_DETAIL/MONTH_DETAIL_LOG(TIME_DATE.MONTH).csv"); 

// write data to comma separated files .csv

int rowCount = 1;
int targetFile;  //handle for targetFile
cstring targetLine;


targetFile = OpenFile("/LOGS/MONTHLY_DETAIL/MONTH_DETAIL_LOG(TIME_DATE.MONTH).csv",1);

For (rowCount = 1; rowCount < 31; rowCount++)
     {
     targetLine = ((IntToText(DATA_ARRAY_TAGS.DAILY_ARRAY.SUPPLY_VOLUME[(rowcount)],10,2) + "," + (IntToText(Column2Array(rowcount),10,7) + "," + etc ;
     writefileline (targetFile, targetLine);
     }

CloseFile(targetfile)
Hit my first few snags:
I want to create a file that has the month number in it so I know what month the data is for. I have a tag that is storing the month number. So is the code for creating the file correct?


Next it looks like I need to convert my data to a string. The IntToText function needs a Int data type. All the data I need to write is Floating Point data. How do I convert that to Text. I didn't see a real to text function.


Is there another function to write to a file data that isn't a string? Seems like the conversion to text is an unnecessary step.


Thanks again.
 
A bit more information than you want, but it covers the bases. Once you have the date and time in a string you can use that string to name a file:

To get the current date and time information:

Code:
int dateTime; // somewhere to store the current Date and Time
cstring dateTimeNow; // current date and time in a string

dateTime = GetNow(); // get the current date/time

    dateTimeNow = IntToText(GetYear(dateTime),10,2) + "-" + IntToText(GetMonth(dateTime),10,2) + "-" + IntToText(GetDate(dateTime),10,2) + "-" + 
        IntToText(GetHour(dateTime),10,2) + "-" + IntToText(GetMin(dateTime),10,2) + "-" + IntToText(GetSec(dateTime),10,2);
If you just want the month you can use GetMonth instead of GetNow.

DecToText() allows conversion of Real to Text.

If the formatting isn't a concern you can use:
AsText(intVal) or AsText(floatVal) to convert to Strings.

Yes you do have to convert things to strings, a number 3 and a text 3 may look the same but are different.


You can check that the flash card is there and ready to store data:

Code:
int driveStatus; // drive status

driveStatus = GetDriveStatus('D');
 
I cant thank you enough BryanG!!



Your ideas and recommendations was just what I needed to get me over the hump. I learned a lot in the process. I appreciate you taking the time to help.


If anyone is interested here is the code That I used to make it work.
Code:
//This program is used to write the Monthly data to a file so that ia looks like the screen on the HMI

// VARs 
int File_Create_Success;
int RowCount = 1;
int TargetFile;  
cstring TargetLine;
cstring LogMonth;
cstring LogHeader;

//create the file with the month in the name so it can be identified in the log
LogMonth = "/LOGS/MONTHLY_DETAIL/MONTHLY_LOG_" + IntToText(TIME_DATE.MONTH,10,2) + "-" + IntToText(TIME_DATE.YEAR,10,4) + ".CSV";
File_Create_Success = CreateFile(LogMonth);

// write data to comma separated files .csv
TargetFile = OpenFile(LogMonth,1);
//Write the Log Header first
LogHeader = "Supply Vol.,Supply Max Q,Well 1 Min Level,Well 2 Min Level,Well 3 Min Level,Inj. Room Meter Vol.,Inj. Room Max Q,Inj. 2 Vol.,Inj. 2 Max Q,Wetland Vol.,Wetland Max Q,Inj. Total Vol.,Inj. Max Q,Inj Well 1 Max Press,Inj Well 2 Max Press,Inj Well 3 Max Press"; 
WriteFileLine(TargetFile,LogHeader);

//Use the for loop to write all the data to the log file

for (RowCount = 1; RowCount < 31; RowCount++)
     {
     TargetLine = (DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.SUPPLY_VOLUME[(RowCount)],1,9,1,0,0) + "," +  DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.SUPPLY_MAX_Q[(RowCount)],1,3,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.DEEP_MIN_PSI_WELL_1[RowCount],1,3,1,0,0)) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.DEEP_MIN_PSI_WELL_2[(RowCount)],1,3,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.DEEP_MIN_PSI_WELL_3[(RowCount)],1,3,1,0,0) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.INJECTION_METER_VOLUME[(RowCount)],1,9,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.INJECTION_METER_MAX_Q[(RowCount)],1,3,1,0,0) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.INJECTION_WELL2_METER_VOLUME[(RowCount)],1,9,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.INJECTION_WELL2_METER_MAX_Q[(RowCount)],1,3,1,0,0) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.WETLAND_METER_VOLUME[(RowCount)],1,5,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.WETLAND_METER_MAX_Q[(RowCount)],1,3,1,0,0) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.INJECTION_TOTAL_VOLUME[(RowCount)],1,9,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.INJECTION_TOTAL_MAX_Q[(RowCount)],1,3,1,0,0) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.MAX_PRESS_INJECTION_WELL_1[(RowCount)],1,3,1,0,0)
     + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.MAX_PRESS_INJECTION_WELL_2[(RowCount)],1,3,1,0,0) + "," + DecToText(DATA_ARRAY_TAGS.DAILY_ARRAY.MAX_PRESS_INJECTION_WELL_3[(RowCount)],1,3,1,0,0);
     WriteFileLine (TargetFile, TargetLine);
     }

CloseFile(TargetFile);
 
No problem, I mostly just copied and pasted from my own programmes.


You might need to add 'C:' to the front of your data path, sometimes it works without and sometimes it doesn't. Maybe because I was also using a USB data stick that connects on 'D:'.


Redlion use a programme that is based on C though they have made it more resilient and less likely to crash. In C you have to try to catch errors before they happen otherwise the program just crashes.
https://en.wikibooks.org/wiki/C_Programming/Error_handling
 
Last edited:
No problem, I mostly just copied and pasted from my own programmes.
What do you think I did? Copied and Pasted from your program.:)


You might need to add 'C:' to the front of your data path, sometimes it works without and sometimes it doesn't.


The file path was already created because I tried to do this via the standard logging function in Crimson. But when I removed that log file from Crimson the directory went away and my program wouldn't create the file. IF I put the C: in front of the path would that fix my issue?



Thanks again!!
 

Similar Topics

We use the data logger to pull our manually input lab data daily. I currently have it set up as a continuous pull and pulls at noon and midnight...
Replies
2
Views
1,374
Crimson data logger is a really good tool. I have an array of many items, each item has many attributes - which are stored in tag arrays. I will...
Replies
0
Views
2,835
Hi, I have a complex database in Crimson 3.0 and in one of the display pages I am trying to get a tag to show the sum of several other tags. The...
Replies
3
Views
163
Hi I have been using Red Lion products for some time, I had a thought over the bank holiday weekend, As you do. It would be nice if whenever a...
Replies
4
Views
1,015
Looking for information regarding what data types are supported in Crimson 3.1 programs. Cstring is self explanatory. Professor Google hasn't been...
Replies
1
Views
1,151
Back
Top Bottom