Dynamic Array/Dataset Tag to determine max value

Sounds like a race condition, where multiple EN bits are coming on in the same time frame and the last write to the dataset tag is winning.

Are the PIT tags' values constantly changing and you are trying to pull the value the entire time that the EN tag is on for that pit?

If you are allowed to add modules to your system, I would install Automation Pros' Integration Toolkit. Its completely free and adds a lot of functionality, including iteration in expressions.

This toolkit has a tags() expression function that accepts a list or dataset of tag paths and will poll that list at a set rate and return all the values of the tags in a single dataset. It accepts dynamically building the source tag list so it may do what you are looking for.

We are doing something similar to you but we are using it for monitoring voltages. We have a driving numeric value that tells an expression how many voltages we want to monitor and the expression builds the list of tag paths for the tags() function. We then look at the highest and the average of the returned dataset.

You would have 1 memory tag containing the paths to all the EN bits and their associated PIT tags, and 3 expression tags, all of which would be a dataset type. One expression tag would use tags to monitor all the values from the EN bits, one to build the list of value (PIT) tags to monitor and another that monitors all the selected PIT tags.

Your first tag would be a dataset with two string columns, "enableTagPath and valueTagPath".

"#NAMES"
"enableTagPath","valueTagPath"
"#TYPES"
"str","str"
"#ROWS","1"
"[provider]Path/To/Some/EN/Bit","[provider]Path/To/Some/PIT/Value"

Your second tag (1st expression tag) would have an expression of

unionAll(
	asMap("path", "str", "value", "b"),
	tags(
		unionAll(
			asMap("path", "str"),
			forEach(
				{Path/to/memory/tag},
				asMap("path", it()[0])
			)
		)
	)
)

Your third tag (second expression tag) would have an expression of

unionAll(
	asMap("path", "str"),
	forEach(
		where(
			forEach(
				{path/to/expression/tag/one},
				if(
					it()[1] = 1,
					lookup(
						{path/to/memory/tag},
						it()[0], Null,
						"enableTagPath",
						"valueTagPath"
						), Null
					)
				), !isNull(it())
			),
		asMap("path", it())
	)
)

Your final expression tag would have an expression of

unionAll(
	asMap("path", "str", "value", "f"),
	if(
		len({path/to/second/expression/tag}) > 0,
		tags({path/to/second/expression/tag}), asList()
	)
)

This would be the tag that you do all of your min/max/average calculations on.