libplctag.NET icon indicating copy to clipboard operation
libplctag.NET copied to clipboard

Boolean Read Not Working

Open the-pied-shadow opened this issue 3 years ago • 14 comments

For some reason reading a boolean tag always returns FALSE for me. I can write to the tag and in the PLC I see the value change as expected. But myTag.Read() always results with myTag.Value equaling FALSE. See below code:

'

    Debug.Log("Creating Tag");
    myTag = new Tag<BoolPlcMapper, bool>()
    {
        Name = TagName,
        Gateway = IP_Address,
        Path = path,
        PlcType = plc,
        Protocol = protocol,
        Timeout = TimeSpan.FromSeconds(5)
    };
    Debug.Log("Initializing Tag");
    myTag.Initialize();

    Debug.Log("Reading Tag");
    myTag.Read();
    Debug.Log(myTag.Value);
    Debug.Log("Writing Tag as True");
    myTag.Value = true;
    myTag.Write();
    Debug.Log("Reading Tag");
    myTag.Read();
    Debug.Log(myTag.Value);

'

Before this is executed I check in the PLC that the value is currently 0. When executed the tag reads as FALSE. Then I write TRUE to the tag. In the PLC I see the value change to 1 as expected. Then I read the tag again but the value is still FALSE while the value in the PLC is still showing as 1.

I tested reading and writing to a DINT and everything there works properly so it seems related specifically to the BOOL type. Looking at #152 it seems there have been issues related to BOOLS before but there the issue was writing.

the-pied-shadow avatar Jun 08 '21 18:06 the-pied-shadow

Did you try the additional mapper that was provided in that issue? I haven't published the package since saying them to the repository so you'll need to copy paste then into your own application.

timyhac avatar Jun 09 '21 21:06 timyhac

Also, can you fill in the details of tag name, PLC type, protocol, etc

timyhac avatar Jun 09 '21 21:06 timyhac

@timyhac I haven't tried the additional mapper. The links on your comment gave me a 404 error and I wasn't sure where in the repository to find it. If you can re-point me in the direction I can certain copy the class in and give it a shot when I get the chance. I won't be able to re-test until next week.

Tag Name is just "BoolTest" PLC Type is Control Logix Protocol is Ab_eip

the-pied-shadow avatar Jun 09 '21 22:06 the-pied-shadow

@the-pied-shadow thanks. https://github.com/libplctag/libplctag.NET/tree/71bb92707cc91c3156fab4f79c6adb8e8a4ae36f/src/libplctag/DataTypes

timyhac avatar Jun 09 '21 22:06 timyhac

@timyhac I tested with the code from the BoolPlcMapper.cs script. I had the same result. However, I noticed by accident that if I create a bool type Tag (Tag<BoolPlcMapper, bool> myTag) and give it the information to look at a tag which is set as a DINT in the PLC, it reads and writes to it as if it's a bool just fine. This is the case on the copied mapper and the original one. Thought I'd mention that in case it's relevant to the issue.

the-pied-shadow avatar Jun 15 '21 18:06 the-pied-shadow

Not sure if there was other progress on this issue. From what I've tested, it seems like with (at least) this PLC setup, the return isn't 255, so the decode call will always return false. I fixed it by altering bool IPlcMapper<bool>.Decode(Tag tag) from #170 to skip the tag.PlcType == PlcType.Omron check and instead use their method of comparing the value to 0.

The result is the following bool IPlcMapper<bool>.Decode(Tag tag) => tag.GetUInt8(0) != 0; I ran this on a live PLC and that fixed the issue for me. Both reading and writing worked as intended.

this could be breaking older functionality, as prior to #170 the function was comparing with 255.

FROMCITRUS avatar Jun 24 '21 16:06 FROMCITRUS

Hi guys, I just had the same issue. Is it somehow already solved? Could you give me some help? I can read/write DINT, but I can just write a Boolean, however when I try to read I have no error, it just always return False, no matter the TAG value.

BTW. I am very newbie with Visual Studio. I have tried to use the link as mentioned https://github.com/libplctag/libplctag.NET/tree/71bb92707cc91c3156fab4f79c6adb8e8a4ae36f/src/libplctag/DataTypes but I don't know how to install this update (can you give me a tip?)

My piece of code below:

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click

    Dim myTag = New Tag(Of BoolPlcMapper, Boolean)() With
    {
        .Name = "TESTE",
        .Gateway = "136.129.0.17",
        .PlcType = PlcType.ControlLogix,
        .Path = "1,5",
        .Protocol = Protocol.ab_eip,
        .Timeout = TimeSpan.FromMilliseconds(500)
    }


    myTag.Initialize()
    myTag.Value = True
    myTag.Write()


End Sub

Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click

    Dim myTag = New Tag(Of BoolPlcMapper, Boolean)() With
  {
      .Name = "TESTE",
      .Gateway = "136.129.0.17",
      .PlcType = PlcType.ControlLogix,
      .Path = "1,5",
      .Protocol = Protocol.ab_eip,
      .Timeout = TimeSpan.FromMilliseconds(500)
  }


    myTag.Initialize()
    myTag.Read()



    If myTag.Value = 1 Then
        Panel1.BackColor = Color.Green
    Else
        Panel1.BackColor = Color.Red
    End If

End Sub

Rvieira26 avatar Jul 01 '21 07:07 Rvieira26

Hi guys, I just had the same issue. Is it somehow already solved? Could you give me some help? I can read/write DINT, but I can just write a Boolean, however when I try to read I have no error, it just always return False, no matter the TAG value.

BTW. I am very newbie with Visual Studio. I have tried to use the link as mentioned https://github.com/libplctag/libplctag.NET/tree/71bb92707cc91c3156fab4f79c6adb8e8a4ae36f/src/libplctag/DataTypes but I don't know how to install this update (can you give me a tip?)

The fix that seems to work for me is to add a custom class to replace the default BoolPlcMapper with the older one in that link. The source code is all C#, so to do it on your end, you'll need it in VB instead. The C# looks like this

public class CustomBoolPlcMapper : IPlcMapper<bool>
{
    public int? ElementSize => 1;

    public PlcType PlcType { get; set; }
    public int[] ArrayDimensions { get; set; }

    public int? GetElementCount() => 1;

    bool IPlcMapper<bool>.Decode(Tag tag) => tag.GetUInt8(0) == 255;

    void IPlcMapper<bool>.Encode(Tag tag, bool value) => tag.SetUInt8(0, value == true ? (byte)255 : (byte)0 );
}

It's been a while since I used VB, but I believe it should look like this

Public Class CustomBoolPlcMapper Inherits IPlcMapper(Of Boolean)

    Public ReadOnly Property ElementSize As Integer?
        Get
            Return 1
        End Get
    End Property

    Public Property PlcType As PlcType
    Public Property ArrayDimensions As Integer()

    Public Function GetElementCount() As Integer?
        Return 1
    End Function

    Private Function Decode(ByVal tag As Tag) As Boolean
        Return tag.GetUInt8(0) = 255
    End Function

    Private Sub Encode(ByVal tag As Tag, ByVal value As Boolean)
        Return tag.SetUInt8(0, If(value = True, CByte(255), CByte(0)))
    End Sub
End Class

For it to work for me, I had to replace the 255 in Decode() and Encode() with 1

FROMCITRUS avatar Jul 01 '21 12:07 FROMCITRUS

@FROMCITRUS Thanks for helping! Actually, the solution for VB did not work, but it kind of opened my mind.

I guess for VB it works a bit differently, I created a new class, as you suggested, in which I implement the Interface IPLcMapper(Of Boolean). In this class I keep all functions as it is but the Decode, at decode I simple take the return bit and it works. See code below. I am quite sure it is not "elegant" as I have no experience at all with this (I am PLC programmer). If any suggestion to make it better let me know!

Public Class CustomBoolPlcMapper

Implements IPlcMapper(Of Boolean)


Public ReadOnly Property ElementSize As Integer? Implements IPlcMapper(Of Boolean).ElementSize


Public Property PlcType As PlcType Implements IPlcMapper(Of Boolean).PlcType
Public Property ArrayDimensions As Integer() Implements IPlcMapper(Of Boolean).ArrayDimensions

Public Function GetElementCount() As Integer? Implements IPlcMapper(Of Boolean).GetElementCount

End Function


Private Function Decode(ByVal tag As Tag) As Boolean Implements IPlcMapper(Of Boolean).Decode

    Return tag.GetBit(0)

End Function

Private Sub Encode(ByVal tag As Tag, ByVal value As Boolean) Implements IPlcMapper(Of Boolean).Encode

End Sub

End Class

Rvieira26 avatar Jul 02 '21 08:07 Rvieira26

Would it be possible to create a mapper for dynamic type?

avnet78 avatar Aug 26 '21 16:08 avnet78

@avnet78 - yes it would be possible. Can you rephrase this question to give more information about what your problem is please, if it doesn't relate to the rest of this GitHub issue can you please create a new one

timyhac avatar Aug 26 '21 22:08 timyhac

It would be great to fix this. The reason I haven't looked at it is because I don't know the solution for all of the different combinations of:

  • Different PLCs (Omron, ControlLogix, etc)
  • Different Tag Types (BOOL tag, BOOL array, BOOL 2d array, DINT bit, etc)

The mapper can theoretically cater for all scenarios, I just don't know which getter/setter methods apply in each situation, and what the expected values are (i.e. is True = 255 vs True = 1)

timyhac avatar Nov 03 '21 09:11 timyhac

Just to make things more interesting, I have some new code queued up that implements bit tags for PCCC/DF1 PLCs like PLC-5, SLC and MicroLogix. You can use tags like N7:4/2 (read and write), B3:2/13, C19:4.dn, C34:2.acc/4, and also MG12:5.en (enable bit). This will be on the prerelease branch shortly.

kyle-github avatar Nov 03 '21 09:11 kyle-github

Hello everyone,

Thank you for this great library. I encountered this problem too, and the workaround that I found is the following :

replace "bool" type with "sbyte" and replace "BoolPlcMapper" with "SintPlcMapper". The result will be "0" or "1" instead of "false/true". But I can just convert this result to bool easily.

        var myTag = new Tag<SintPlcMapper, sbyte>()
        {
            Name = "TEST_READ_BIT",
            Gateway = "192.168.30.30",
            Path = "1,0",
            PlcType = PlcType.ControlLogix,
            Protocol = Protocol.ab_eip,
            Timeout = TimeSpan.FromSeconds(5)
        };

        myTag.Read();
        Console.WriteLine(myTag.Value);

kmdarkmaster avatar Nov 16 '21 16:11 kmdarkmaster

Hello, I just made a pull-request on this subject. https://github.com/libplctag/libplctag.NET/pull/335

corentingallet avatar Apr 04 '23 14:04 corentingallet

I am seeing this same problem with AB Micro850 PLC - Bool writes work but bool reads always return false. I looked at pull-request #335 and it seems like a reasonable work-around

markshancock avatar Jul 03 '23 16:07 markshancock

What is the process (and timeline) for approving this pull-request and deploying it to nuget.org?

markshancock avatar Jul 03 '23 16:07 markshancock

Hi @markshancock - for that particular Pull Request I am looking for some feedback on what they know about the data encodings for their device.

We have a lot of library consumers now, so we need to be careful about breaking existing apps. I have been bitten more than once by Hyrum's law.

I think what this has shown is that we need to have a repository of knowledge about data type encodings. I will raise it with the libplctag team.

P.S. If you need the behaviour contained there you can create your own mapper. If you do specifically need it to be in the library, are you able to provide some further context around your use case?

timyhac avatar Jul 04 '23 09:07 timyhac

Hi all - an alpha package has been released with the Pull Request by @corentingallet merged. This does appear to support single BOOL tags for all devices we have received support requests on.

As discussed earlier, the best way forward will be to keep a repository of known data encodings somewhere so that we can be sure of which devices the data encoding works for and which it doesn't, and which ones we don't know the data encoding.

For now I will close this ticket out - if anyone finds this ticket in the future due to a BOOL tag data encoding failure, please create a new ticket but link to this one.

timyhac avatar Jul 04 '23 21:07 timyhac