Sequencing Reads in a Pump-Off Controller

Reading the Dynacard data (Dynacard Upload Driver Tag) from a pump-off controller is a multi-step process that involves a number of Modbus messages being exchanged with the controller. The Dynacard Upload Driver tags control the sequencing of the messages, and if you are using a standard, supported pump controller you need not worry about this sequence. However, if you have a non-standard controller or are adding support for a new type of flow computer, you may wish to edit this sequence.

 

You can review your Dynacard's current message sequence by using the Export button provided in the Communications tab of your Dynacard Upload Driver tag’s properties folder. Use this to export the current message sequence to a CSV file, which can be opened up in Excel.

Use the Import button in the same tab to read an edited CSV file and import its sequence into the Dynacard Upload Driver tag.

 

An example of an exported Dynacard sequence:

 

The columns are as follows:

Column Description
Step Name A unique name given to this step in the sequence.
Step Module The name of the sequencer module to run during this step.
Parm1 - Parm20 Parameters to the sequencer module.

 

When a read is triggered in the Dynacard Upload Driver, it will start at the top of this list and run each step module one after the other in sequence. Refer to the following discussion of each of these modules, their parameters and how they work. Combining them should allow you to perform the necessary sequence of reads and writes to get data from your flow computer.

The Dynacard Structure

Raw registers are read from the pump-off controller and saved in memory. These registers are then parsed for the card data, which is saved in a defined structure within the driver. This structure is logged to the VTScada historian, and certain elements of the Dynacard structure (for example, the force / position data) are shown on the Dynacard screen.

The Dynacard structure, and all of its elements, are listed in the chart below. Not every element will be used for every pump-off controller, but your sequence CSV file should use these names exactly in order to ensure that the data is saved properly.

DataGroup Variable Comment
Card1 CardXY The force/position data used in the Dynacard chart
  TimeStamp If no time stamp is provided, the time at which the data was read will be used.
  ShutdownID Shutdown Event ID
  NumPoints  
  MaxLoad  
  MinLoad  
  StrokeLength  
  StrokePeriod  
  ControlMode  
  DHCardXY Downhole force/position data
  DHTimeStamp Downhole time stamp
  DHMaxLoad  
  DHMinLoad  
  DHShutdownID Downhole Shutdown Event ID
  DHNumPoints  
  DHGrossStroke  
  DHNetStroke  
  DHPumpFillage  
  DHFluidLoad  
Card2 Same variables as Card1 data group
Card3 Same variables as Card1 data group
Card4 Same variables as Card1 data group
Card5 Same variables as Card1 data group
Card6 Same variables as Card1 data group
Card7 Same variables as Card1 data group
Card8 Same variables as Card1 data group
Card9 Same variables as Card1 data group
Card10 Same variables as Card1 data group

 

Sequencer Modules

This table provides an overview of each module. Full descriptions follow the table.

Module Description
ReadValues Reads registers from the pump-off controller and puts them in memory
NewDataGroup Adds a new DataGroup to the Dynacard structure
GetValue_Numeric Reads values from memory and saves them in the Dynacard structure as a single numeric value
GetValue_XYCardData Reads values from memory and saves them in the Dynacard structure as a set of XY Dynacard data. This module assumes that the X and Y values are interleaved within a single block of registers (see full description below)
GetValue_XYCardData_Blocks Reads values from memory and saves them in the Dynacard structure as a set of XY Dynacard data. This module assumes that the X and Y values are stored in separate blocks of registers (see full description below)
WriteValue Writes a value to the pump-off controller
ResetValues Clears memory of the previously read values
SetNextStep Sets the next step of the sequence that should be run
CondNextStep Sets the next step of the sequence based on some condition
CounterLimit Sets the next step or sets an error flag when it has been run a designated number of times
CounterReset Resets the counter used in the CounterLimit module
TimeDelay Waits a specified amount of time before proceeding to the next module
EndSequence Ends the sequence; should be the last module in every sequence

 

ReadValues

Reads registers from an RTU and stores them in memory.

Parameters:

1 StartRegister First register to read
2 N Number of registers to read

This module reads any number of registers from the RTU and stores them in memory to be accessed by other modules. Note that this function does not take into account the content of the data being read in any way, including data types. If you wish to read a double floating point, for example, you would start at the appropriate register and request a read of four registers in order to bring back the whole thing.

Note that in many cases, particularly if the Modbus mapping in the pump-off controller is well-organized, it is more efficient to read several values in a single message. If, for example, you wanted to read the data from registers 40010, 40011 and 40013 (but you don’t care about 40012), its usually best to do a single four-register read rather than breaking it out into two smaller reads.

 

NewDataGroup

Adds a new data group to the Dynacard structure

Parameters:

1 GroupName Label to use for the new data group (Card1, Card2, etc.)

This module adds a new data group to the Dynacard structure, and should be used to separate the data read from different cards. Even if only one card’s data is being read, the “Card1” group should still be added before running any “GetValue” modules.

 

GetValue_Numeric

Reads values from memory and adds them to the Dynacard structure

Parameters:

1 VarLabel Label for the variable in the Dynacard structure
2 StartRegister Starting memory register to read (note that these register numbers will match those in the controller's Modbus map)
3 FormatType Data type that is being read - see list of acceptable data types below.
4 UnscaledMin Unscaled minimum value - used to scale the value we're reading
5 UnscaledMax Unscaled maximum value - used to scale the value we're reading
6 ScaledMin Scaled minimum value - used to scale the value we're reading
7 ScaledMax Scaled maximum value - used to scale the value we're reading
8 ReverseRegOrder Set to 1 to read the registers in reverse order (may be necessary for some controllers)
9 IsTimeStamp Set to 1 if we are reading a timestamp

The VarLabel should match one of those listed in The Dynacard Structure table at the beginning of this article.

 

This module reads the registers in memory (see: ReadValues) and interprets them as data values. You can think of this as similar to a standard driver’s read of an RTU, only we’re reading from internal VTScada memory instead of from the pump-off controller directly. The memory registers are mapped the same as those in the pump-off controller, and you can use the parameters to control everything that you would in a standard driver’s read (data type, scaling, reverse order, etc.)

 

One of the following constants should be used for the FormatType parameter:

Constant Data Type Bytes
0 Short Integer 2
1 Long Integer 4
2 Unsigned Short Integer 2
3 Unsigned Long Integer 4
4 Single Precision Floating Point 4
5 Double Precision Floating Point 8
6 Single Byte (High) 1
7 Single Byte (Low) 1

 

GetValue_XYCardData

Reads force / position values from memory and adds them to the Dynacard structure.

Parameters

1 VarLabel Label for the variable in the Dynacard structure (should be either CardXY or DHCardXY)
2 StartRegister Starting memory register to read (note that these register numbers will match those in the controller's Modbus map)
3 FormatType Data type that is being read - see list of acceptable data types in the GetValue_Numeric section.
4 NumPairs Number of X-Y pairs to read
5 UnscaledMinX Unscaled minimum value - used to scale the value we're reading
6 UnscaledMaxX Unscaled maximum value - used to scale the value we're reading
7 ScaledMinX Scaled minimum value - used to scale the value we're reading
8 ScaledMaxX Scaled maximum value - used to scale the value we're reading
9 UnscaledMinY Unscaled minimum value - used to scale the value we're reading
10 UnscaledMaxY Unscaled maximum value - used to scale the value we're reading
11 ScaledMinY Scaled minimum value - used to scale the value we're reading
12 ScaledMaxY Scaled maximum value - used to scale the value we're reading

This module reads the position/load registers in memory (see: ReadValues) and interprets them as data values which are later used to create the Dynacard graph. Beginning at the start register, the FormatType (see the GetValue_Numeric section) and the NumPairs variables combine to tell the sequencer how many registers should be read.

 

This module assumes that X and Y values in the device are interleaved within a single block of registers:

[X1, Y1, X2, Y2, …, Xn, Yn]

 

GetValue_XYCardData_Blocks

Reads force / position values from memory and adds them to the Dynacard structure.

Parameters

1 VarLabel Label for the variable in the Dynacard structure (should be either CardXY or DHCardXY)
2 StartRegisterX Starting memory register to read (note that these register numbers will match those in the controller's Modbus map)
3 StartRegisterY Starting memory register to read (note that these register numbers will match those in the controller's Modbus map)
4 FormatTypeX Data type that is being read - see list of acceptable data types in the GetValue_Numeric section.
5 FormatTypeY Data type that is being read - see list of acceptable data types in the GetValue_Numeric section.
6 NumPairs Number of X-Y pairs to read
7 UnscaledMinX Unscaled minimum value - used to scale the value we're reading
8 UnscaledMaxX Unscaled maximum value - used to scale the value we're reading
9 ScaledMinX Scaled minimum value - used to scale the value we're reading
10 ScaledMaxX Scaled maximum value - used to scale the value we're reading
11 UnscaledMinY Unscaled minimum value - used to scale the value we're reading
12 UnscaledMaxY Unscaled maximum value - used to scale the value we're reading
13 ScaledMinY Scaled minimum value - used to scale the value we're reading
14 ScaledMaxY Scaled maximum value - used to scale the value we're reading

This module reads the position/load registers in memory (see: ReadValues) and interprets them as data values which are later used to create the Dynacard graph. Beginning at the start register, the FormatType (see the GetValue_Numeric section) and the NumPairs variables combine to tell the sequencer how many registers should be read.

 

This module assumes that X and Y values in the device are separated into two distinct blocks of registers:

[X1, X2, …, Xn] and [Y1, Y2, …, Yn]

 

WriteValue

Writes a value to a register in the pump-off controller.

Parameters

1 Address Address of the register in the pump-off controller to write to
2 Value Value to write

 

This module writes a single value to a register in the pump-off controller. The address should be written as though you were performing a standard write with the child Modbus driver. If you wish to write a floating point to register 40001, for example, then the address should be “40001/FLOAT”.

 

ResetValues

Clears the memory holding the values previously read from the RTU

Parameters

-None

This module clears the memory that holds the values that had previously been read from the RTU by the ReadValues module. Usually this module is not necessary, but you may need to run it in cases where the same registers in the pump-off controller are loaded with different information over the course of the read sequence.

 

SetNextStep

Sets the next sequence step to be run.

Parameters

1 StepName Name of the step to run next

 

Usually, the steps of the sequence are run sequentially from top to bottom. This module is used to change that order, specifying the name of the next step to be run (as defined in the first column in the sequence CSV file). After that step runs, the steps will continue to run sequentially from that new point.

 

CondNextStep

Sets the next sequence step to be run based on a condition being true.

Parameters

1 CompValue Main value to compare with the others
2 DataGroup DataGroup from the Dynacard structure (optional)
3 CondCode Condition comparison code (see notes below)
4 Comparison1 Value to compare with CompValue (see notes below)
5 Step1 Sequence step to run next if comparison is true
6 DataGroup1 DataGroup corresponding to Comparison1 (optional)
7 Comparison2 Value to compare with CompValue (see notes below)
8 Step2 Sequence step to run next if comparison is true
9 DataGroup2 DataGroup corresponding to Comparison2 (optional)
10 Comparison3 Value to compare with CompValue (see notes below)
11 Step3 Sequence step to run next if comparison is true
12 DataGroup3 DataGroup corresponding to Comparison3 (optional)
13 Comparison4 Value to compare with CompValue (see notes below)
14 Step4 Sequence step to run next if comparison is true
15 DataGroup4 DataGroup corresponding to Comparison4 (optional)
16 Comparison5 Value to compare with CompValue (see notes below)
17 Step5 Sequence step to run next if comparison is true
18 DataGroup5 DataGroup corresponding to Comparison5 (optional)

Usually, the steps of the sequence are run sequentially from top to bottom. This module is used to change that order, specifying the name of the next step to be run (as defined in the first column in the sequence CSV file) provided a certain condition is met. After that step runs, the steps will continue to run sequentially from that new point.

As an example, this module is used in the Lufkin SAM pump controller to decide how many registers to read. First we read the control mode, and then if it is either 1 (“Downhole”) or 4 (“VFD – Downhole”) then we read the downhole registers in addition to the standard registers.

 

The CompValue parameter is the value that will be compared against each of the other Comparison parameters. Each of these parameters can be either of the following:

  • A value that had previously been saved in the Dynacard structure
  • A constant

 

For example, in the Lufkin SAM case mentioned above we had previously read the control mode with a Get-Value_Numeric, giving it the label “ControlMode”. When doing the comparison to see if it is either a 1 or a 4, we would set the CompValue parameter to “ControlMode”, the Comparison1 parameter to “1” and the Comparison2 parameter to “4”.

If the CompValue or Comparison parameters are values from the Dynacard structure, the DataGroup parameters specify which DataGroup the values reside in within the structure. If no DataGroup parameters are provided, the current DataGroup will be used.

 

The various Step parameters indicate which step of the sequence to progress to in the event that the comparison is true. The comparisons will progress sequentially until one of them is found to be true, in which case that step will be used and the rest of the comparisons won’t be made. If none of the comparisons is true, the sequencer carries on as usual to the next sequential step.

The CondCode parameter tells the system what kind of comparison should be made. The following chart shows the numeric codes that represent the different options.

CondCode Operation
0 ==
1 !=
2 <
3 >
4 <=
5 >=

The same CondCode is used for all comparisons.

 

CounterLimit

Sets the next sequence step or returns an error message when this module has been run a predetermined number of times.

Parameters

1 VarName (Optional) Name of counter variable
2 CountLimit Number of times this should be run before triggering the next step/the error message
3 StepName Sequence step to run next
4 CustomErrMessage Error message to return

This module can be used to repeat a section of the sequence several times. A tally is kept of each time this module is run. Once it has run a number of times equal to or greater than its CountLimit, the module will trigger. If the module has not yet reached its count limit, the sequencer will carry on to the next module as usual.

If StepName is valid, the sequencer will progress to that state upon reaching the limit. If the StepName field has been left blank, an error will be returned and the entire sequencer will stop (declaring the read to be a failure). In this latter case, CustomErrMess can be used to set the error message that will be displayed by the driver’s ‘Stats’ button.

VarName can usually be ignored, and is only necessary if you need to maintain two separate counters within the same sequence. In this case, each counter should be given a unique VarName.

 

CounterReset

Resets the counter used in the CounterLimit module

Parameters

1 VarName Optional) Name of counter variable

This module is used in conjunction with the CounterLimit module defined above. If CounterLimit is going to be used for a given VarName (or lack thereof) multiple times within the same sequence, it can be reset to 0 by calling the Coun-terReset function with that VarName.

 

TimeDelay

Wait a specified number of seconds before progressing to the next module

Parameters

1 Delay

Time in seconds

 

EndSequence

Ends the sequence

Parameters

-None