Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boolean Read Not Working #178

Closed
the-pied-shadow opened this issue Jun 8, 2021 · 19 comments
Closed

Boolean Read Not Working #178

the-pied-shadow opened this issue Jun 8, 2021 · 19 comments
Labels
bug Something isn't working hardware Related to hardware specific support

Comments

@the-pied-shadow
Copy link

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.

@timyhac
Copy link
Collaborator

timyhac commented Jun 9, 2021

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
Copy link
Collaborator

timyhac commented Jun 9, 2021

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

@the-pied-shadow
Copy link
Author

@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
Copy link
Author

@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.

@FROMCITRUS
Copy link

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.

@Rvieira26
Copy link

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

@FROMCITRUS
Copy link

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

@Rvieira26
Copy link

@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

@avnet78
Copy link

avnet78 commented Aug 26, 2021

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

@timyhac
Copy link
Collaborator

timyhac commented Aug 26, 2021

@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
Copy link
Collaborator

timyhac commented Nov 3, 2021

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)

@kyle-github
Copy link
Member

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.

@kmdarkmaster
Copy link

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);

@jkoplo jkoplo added bug Something isn't working hardware Related to hardware specific support labels Nov 3, 2022
corentingallet added a commit to corentingallet/libplctag.NET that referenced this issue Apr 4, 2023
Always returns False.
Issue : libplctag#178

Signed-off-by: Corentin Gallet <116062990+corentingallet@users.noreply.github.com>
@corentingallet
Copy link
Contributor

Hello,
I just made a pull-request on this subject.
#335

@markshancock
Copy link

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
Copy link

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

@timyhac
Copy link
Collaborator

timyhac commented Jul 4, 2023

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
Copy link
Collaborator

timyhac commented Jul 4, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working hardware Related to hardware specific support
Projects
None yet
Development

No branches or pull requests

10 participants