Selecting an inbound correction factor & AddValue()


Recommended Posts

Some quick background before the quesiton:

On the app I'm currently working on, we want the customer to have the ability to apply custom calibration formulae to incoming data from a set of soil sensors. The way the systems are built in the field put 4 to 8 sensors at each of a number of measurement stations in a field. So, we do many things based on an array structure like "DataIn[sT][PR]" where 'ST' is the station number and 'PR' is the probe. However, the actual raw inbound data for each probe comes in on individual channels and we currently place those values in the channels with AddValue() as we parse the incoming data strings.

What we want to be able to do is to allow the customer the option of applying a custom calibration to each probe at each station to tweak their system for slight variations in soil type over and above the "standard" values we will be including with the package.

There are four possible formulas that can be applied to the incoming values. Each formula is a polynomial with 2 to 4 terms. We have a setup page all built so the customer can set the coefficients for each term and store those values for each station and probe.

So now, I need a way to apply the chosen formula to the inbound readings. I can't use a channel conversion because they don't work with AddValue() and I can't place a SWITCH or IF statement in the "EVENT" tab of the channel to select a formula.

So how would you solve the problem of doing this:

If (Formula_Select == 1)
   MyChannel.AddValue(VAL + (VAL*A[ST][PR]) + (VAL*B[ST][PR]^2) + (VAL*C[ST][PR]^3))
If (Formula_Select == 2)
   MyChannel.AddValue(a diffferent formula)
If (Formula_Select == 3)
   MyChannel.AddValue(another formula)
...etc
endif

My current thought is to bring the raw values in to one channel and then use a sequence to do the maths after all acquisition for a cycle is done. But that seems a bit wasteful of channels and gets confusing from a programming standpoint after more than just a couple of stations.

Link to comment
Share on other sites

I did an app similar to this where the customer had several variables they were reading and they wanted to calculate another value based on these values. We didn't want to hardcode so the customer could enter their own foruma. So, they might enter V1 + V2^2 + 4*V3^3 and the script would substitute in input values for V1, V2, and V3. I think you want something similar, so here is the script to do it:

private loc
express = formula[x]			 
while (1)
   loc = findoneof(express,"vV")
   if (loc == -1)
	  break
   endif
   express = left(express,loc) + "mydata[" + mid(express,loc+1,1) + "]" + mid(express,loc+2,100)
endwhile			
dataout = evaluate(express)
dataout.time = systime()
mychannel.addvalue(dataout)

mydata is an array for each of the input values.

Link to comment
Share on other sites

Cool, thanks.

Since we're using a custom user protocol to do our devices reads via telemetry, it looks like we'll have to modify that routine or create a new one for this project in order to do this if we want to continue to use MyChannel.AddValue() as the method of inserting readings in to the appropriate channels though, yes?

Just out of curiosity, is there any chance that DF 6.0 might allow a more flexible use of the AddValue() function or provide something similar that would allow pre-processing and conversion before stuffing the value in the channel? In other words, is the idea of bringing the functionality of channel conversions to the AddValue() function being looked at?

Thanks again for the feedback.

Link to comment
Share on other sites

If the addvalue() is in a protocol, then the conversion script would need to be there too. I wouldn't make a special protocol, I'd just create a function that does the conversion and use a flag to enable it. So, the addvalue might look like:

mychannel.addvalue(convert(datain))

and then in convert() put:

function convert(datain)

if (convertflag)

.. do conversion, and return result

else

return(datain)

endif

You might even insert the time in convert() in both cases. Of course you probably do NOT want to use channelname.addvalue, but rather local.channel.addvalue() since you really don't want to specify specific channel names in a protocol, otherwise you have to create those same channel names in all documents you create with the protocol. local.channel.addvalue() is more generic.

Channels don't call their conversion if addvalue() is used because it is assumed that you would be doing any conversion in script.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.