Best Approach for High-Frequency Event-Based Data Logging and Graphing

Hello everyone,

I’m currently working on migrating a legacy project to a new network architecture and applying lessons learned over time. In the old project, I had to graph a high-frequency variable (LoadCell) in real time, but only under specific conditions, not continuously.

To achieve this, I wrote the following script
:

def create_data():
   date = system.tag.readBlocking(["[System]Gateway/CurrentDateTime"])[0].value
   VIN = system.tag.readBlocking(["[Amvian]_PLC_/Controller:Global/Traceability_ST8/VIN_Number"])[0].value
   model = system.tag.readBlocking(["[Amvian]_PLC_/Controller:Global/Traceability_ST8/Model"])[0].value	
   pos = system.tag.readBlocking(["[Amvian]_PLC_/Program:TESTER/Graph/Cushion/POS"])[0].value	
   	
   for i in range(pos):
   	try:
   		GraphData = system.tag.readBlocking([("[Amvian]_PLC_/Program:TESTER/Graph/Cushion/FIFO_ARRAY_{}_".format(i))])[0].value	
   		query = "INSERT INTO `amvian_db`.`graph_cushion` (`Fecha`, `VIN`, `Model`, `Data`) VALUES (?, ?, ?, ?);"
   		args = [date, VIN, model, GraphData]
   		system.db.runPrepUpdate(query, args)
   	except Exception as e:
   		print("Detalle del error: {}".format(e))

This script reads a FIFO from the PLC whenever a certain condition is met and inserts the array of values into a database. I then use these values for real-time graphing.

Now, in this new architecture (and license), I have both Tag Historian and SQL Bridge available, and I’m trying to improve or replace the above method using more built-in tools.

Here’s what I’ve tried:

  • I tested SQL Bridge (Transaction Groups) by setting tags to scan as fast as 10 ms (PLC cycle is 15 ms), with the group executing at 10 to 100 ms. However, this often leads to the same value being inserted multiple times (up to 7 times) before the tag actually updates, since the OPC tag hasn't refreshed yet.
  • Tag Historian seems less viable here, because I need to log data based on an event, not on a timed basis.

What I’m looking for:

A robust method to record high-frequency values only when a specific event occurs, avoiding duplicate entries or wasted storage. I’d love to hear how others have approached this, especially in scenarios where performance and data accuracy are crucial.

Any suggestions on:

  • Using scripting vs transaction groups
  • Proper OPC tag group settings for high-speed acquisition
  • Storing full arrays in the PLC vs individual points

would be greatly appreciated.

Thanks in advance for your help!

For this kind of application, don't use tags in the transaction groups--use direct OPC items, and set the group's OPC mode to "Read" instead of subscribed. (The trigger can be a tag.)

OPC tags do not have ordered delivery, so values that change at the same time as a trigger can be delivered after the transaction fires. OPC Read mode causes the group to deliberately read fresh data after the trigger.

However, the elephant in the room here is that polling protocols struggle go as fast as you seem to want, particularly if the PLC is also serving other traffic. (If you look at your diagnostics, I bet your PLC connection is substantially overloaded.)

3 Likes

As Phil has said, Tag Historian is not set up for this type of thing. And in my experience with the rate you appear to want, Transaction Groups really aren't either.

When I have needed to do this, I have setup a ring buffer in the PLC with enough space that I could have a reasonable scan rate in Ignition. Then I used a Gateway Timer Event, which would scan my trigger tag, while (note the script checks each time, I am not using a 'while loop') the trigger tag is true, I pull data from the buffer using system.opc* functions.

In this way, the PLC stores the data in an array which give far more resolution than you can achieve otherwise. It also keeps the load mostly off your tag system.

4 Likes