I have data samples that I am taking at 1 minute intervals over 24 hours. This represents a percentage of speed / uptime. Is there an easy way to calculate an average of these 1440 samples to display on a dashboard?
Follow the instructions within this post to implement a GetData() command and pull the sampled data into the macro: Note: In this example I’m retrieving data from LW-59. You may need a variable to hold the total sum and average and a variable to count the number of samples. The data type I am reading this example is a short, but please configure the data type of the variable used within GetData() such that it matches the type sampled.
Store the total count within HMI memory, in this example I am storing the count within LW-1000: Note: Information related to the SetData() command can be found within the post mentioned above as well.
Add the current data to a running total and save this data within HMI memory as well:
Calculate the average and set this within HMI memory:
Is each sample obtained from a different register or tag within the external device or is this data read into the same register at one minute intervals?
A single register at intervals. The plan was to use the Data Sampling under Data/History to keep 24 hours worth, and hopefully summarize it from in there. Ultimately there are 35 production lines to do all of this with.
If it is only a single register, then you can develop a solution using the example mentioned above. The GetData() will occur at 1 minute intervals due to periodical execution. It will retain a running total and average based on the current sample count. I would recommend that you reset the total and count registers daily to ensure that these values remain within a valid range.
I need to do a rolling average of the last 24 hours. Can I pull data from the Data Sampling like a FIFO so as I add the latest minute, I can remove the minute from 24 hours ago?
Or some way to maintain a FIFO that doesn’t involve 1440 GetData() and SetData() commands?
Can you please advise the data type of the data you would like to average? I will try to give you an example of a queue as defined within our macro shortly.
I will be using integer data. Updates come in at 60 second intervals, and I plan to keep 24 hours (1440 samples) as a “Last 24 hours” display in a rolling queue.
Thank you for the update, if you have time it would be great if you can post the solution you’ve developed or a brief description of it on our forum for anyone else that might have this question. Have a great day!
FUNCTION_BLOCK UpTimeCalc
VAR_INPUT
running : BOOL;
END_VAR
VAR_OUTPUT
runSeconds : WORD;
avg24H : REAL;
END_VAR
VAR
snapshot : BOOL;
active : ARRAY[0…60] OF BOOL;
history24H : ARRAY[0…1440] OF BYTE;
secondCount : INT;
calcAvg : DWORD;
i : INT;
END_VAR
// Function is called every 1 second
secondCount := secondCount + 1;
// Once per minute, reset the second counter and set the snapshot bit for 1 scan
IF (secondCount = 60) THEN
secondCount := 0;
snapshot := TRUE;
ELSE
snapshot :=FALSE;
END_IF
// Active array tracks each seconds status
active[secondCount] := running;
// Generate a rolling average for the current minute
calcAvg := 0;
FOR i := 0 TO 59 DO
IF(active[i] = TRUE) THEN
calcAvg := calcAvg + 1;
END_IF
END_FOR
// Set the runSecond output for display
runSeconds := DWORD_TO_WORD(calcAvg);
// Each minute, recalculate the 24 hour rolling average
IF(snapshot = TRUE) THEN
calcAvg := 0;
FOR i:= 0 TO 1439 DO
history24H[i] := history24H[i+1];
calcAvg := calcAvg + history24H[i];
END_FOR
history24H[1440] := WORD_TO_BYTE(runSeconds);
calcAvg := calcAvg + runSeconds;
avg24H := 100.0*(DWORD_TO_REAL(calcAvg) / 86400); // 86,400 seconds in 24 hours. X100 to get a percentage
END_IF