libplctag.NET
libplctag.NET copied to clipboard
Boolean Read Not Working
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.
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.
Also, can you fill in the details of tag name, PLC type, protocol, etc
@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 thanks. https://github.com/libplctag/libplctag.NET/tree/71bb92707cc91c3156fab4f79c6adb8e8a4ae36f/src/libplctag/DataTypes
@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.
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.
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
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 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
Would it be possible to create a mapper for dynamic type?
@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
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)
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.
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);
Hello, I just made a pull-request on this subject. https://github.com/libplctag/libplctag.NET/pull/335
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
What is the process (and timeline) for approving this pull-request and deploying it to nuget.org?
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?
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.