How to convert serial 'unsigned 16 bit integer' to 'signed 16 bit integer' in DeltaV using CALC logic?

Hi,

In a brownfield project, we have serial devices sending the modbus data to DeltaV. The serial IO list contains list of  16 bit registers coming to DeltaV (e.g. address range R30001 to R30100).

There is also a column called 'SIGNED' in the customer supplied data where data is 'TRUE or FALSE for a particular 16 bit integer tag.

The problem is the 16 bit integers are laid out such that they are not grouped for signed and usnsigned integers (not contageous). e.g. R30001 to R30010 are SIGNED registers, R30011 to R30015 are UNSIGNED etc...

This if we have to implement in DeltaV; we have to create a seperate 'Dataset' for each block of Contageous Signed or Unsigned registers thus massively increasing the number of datasets per port. (>16).

The customer has said they can not change the data mapping in the field as it is a brownfield project and third party running are very old.

Question is-

Is there any way in DeltaV where we can read the contageous registers (say R30001 to R30100) in one dataset of data type '16 bit unsigned' integers and convert the unsigned tags to 'Signed 16 bit registers using some CALC logic or any algorithm?

Has this been done by anybody in the previous projects or any idea how to implement this logic to convert unsigned integer to signed integer in DeltaV?

Please advise.

 

Thanks and Regards,

Abhijit Joshi

  • You could create two datasets pointing to the same contiguous registers (R30001) but make one dataset signed, the other unsigned.
  • In reply to AdrianOffield:

    Thanks Adrian! This is OK. But, I have interfaces where the dataset count still exceeds even with your suggested solution; I am looking for a solution like data 'type casting' from unsigned integer to signed integer type using some calculation in the Control Module.
  • In reply to AbhiJos:

    I've converted unsigned to signed in the past with a calc block in DeltaV with logic similar to the following:

    If Unsigned_Val <= 32767 then
    Signed_Val := Unsigned_Val;
    Else
    Signed_Val := Unsigned_Val - 65535;
    End_IF;

    or, more concisely

    Signed_Val := (Unsigned_Val <= 32767) ? Unsigned_Val : (Unsigned_Val - 65535);

    It's been a few years and I can't remember if it should be "- 65535" or "- 65536". I'm assuming you would selectively convert only the necessary integers.
  • In reply to Michael Moody:

    Thanks Michael! Looks like the logic will work. I tried with couple of examples and makes sense. Regards, Abhijit.
  • In reply to Michael Moody:

    I had this issue in the past too:
    I believe that negative numbers are represented by a two's complement number.
    Maybe you could write the value from the unsigned parameter to a signed parameter?
    This would be very simple if it works.

    If not, the mask to bitwise NOT the value (if negative) has to be calculated.

    If I remember correctly, DeltaV does not use a twos complement on the padding zeros.