-
Notifications
You must be signed in to change notification settings - Fork 60
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
Cannot Declare Array[0..15] Bool #437
Comments
BOOL arrays are very confusing in the PLC itself. Rockwell creates them internally as a set of 32-bit integers. Each bit is one BOOL. Unfortunately, Rockwell did not translate that outside the PLC so the PLC treats a BOOL array as an array of 32-bit integers with a length of the number of BOOL elements divided by 32 and a size rounded up. That means that if you create a BOOL array of 10 elements, you will actually get a BOOL array of 32 elements but the PLC and the CIP network protocol will show this as an array of one element of 32-bits. A BOOL array of 33 elements will show up as a 32-bit integer array of 2 elements. So take the number of BOOL elements, divide by 32, and round up. BOOL[10] -> UDINT[1] Even more unfortunately, Omron does not do the same thing. Omron uses 16-bit integers as the base element, but internally does NOT pad unused bytes within that 16-bit integer. We have seen garbage bits in the unused space. |
I forgot to mention that you need to set the number of elements in the tag (in the .NET code creating the tag) to the number of UDINT elements, NOT the number of BOOL elements. |
We attempted to encode this logic into a BoolMapper, but have found it only works in some very specific scenarios. Bool arrays were one of the reasons I decided to deprecate (and eventually remove) the Mapper system entirely. In terms of debugging this following Kyle's advice you could create a Tag tag = new()
{
Name = "Allarms",
Gateway = ...,
Path = ...,
PlcType = PlcType.ControlLogix,
Protocol = Protocol.ab_eip,
ElementSize = 4,
ElementCount = 1,
};
tag.Initialize();
tag.SetBit(3, true); // Sets "Allarms[3]" to true
tag.Write(); If you want to continue to use the Mapper system, you will need to code test this for all scenarios you expect to support - I see that you're allowing for multiple Protocols and PlcTypes in your code, so you'll need to determine how each combination encodes BOOL arrays and code for that. |
Exactly, I have some generic functions that initialize the Tag: protected internal IItem? GetArrayItem(EEIPItemModel itemModel)
{
return itemModel.DataType switch
{
ItemDataType.SINT => InitializeTag<SintPlcMapper, sbyte[]>(itemModel),
ItemDataType.USINT => InitializeTag<BytePlcMapper, byte[]>(itemModel),
ItemDataType.INT16 => InitializeTag<IntPlcMapper, short[]>(itemModel),
ItemDataType.DINT => InitializeTag<DintPlcMapper, int[]>(itemModel),
ItemDataType.LINT => InitializeTag<LintPlcMapper, long[]>(itemModel),
ItemDataType.WORD => InitializeTag<UShortPlcMapper, ushort[]>(itemModel),
ItemDataType.DWORD => InitializeTag<UIntPlcMapper, uint[]>(itemModel),
ItemDataType.ULINT => InitializeTag<ULongPlcMapper, ulong[]>(itemModel),
ItemDataType.REAL => InitializeTag<RealPlcMapper, float[]>(itemModel),
ItemDataType.LREAL => InitializeTag<LrealPlcMapper, double[]>(itemModel),
ItemDataType.BOOL => configuration.PlcType == EEIPPlcType.CompactLogix
? InitializeTag<ExtesionClass.BoolPlcMapper, bool[]>(itemModel)
: InitializeTag<libplctag.DataTypes.BoolPlcMapper, bool[]>(itemModel),
ItemDataType.STRING => InitializeTag<ExtesionClass.StringPlcMapper, string[]>(itemModel),
_ => null,
};
}
protected internal IItem? GetItem(EEIPItemModel itemModel)
{
return itemModel.DataType switch
{
ItemDataType.SINT => InitializeTag<SintPlcMapper, sbyte>(itemModel),
ItemDataType.USINT => InitializeTag<BytePlcMapper, byte>(itemModel),
ItemDataType.INT16 => InitializeTag<IntPlcMapper, short>(itemModel),
ItemDataType.DINT => InitializeTag<DintPlcMapper, int>(itemModel),
ItemDataType.LINT => InitializeTag<LintPlcMapper, long>(itemModel),
ItemDataType.WORD => InitializeTag<UShortPlcMapper, ushort>(itemModel),
ItemDataType.DWORD => InitializeTag<UIntPlcMapper, uint>(itemModel),
ItemDataType.ULINT => InitializeTag<ULongPlcMapper, ulong>(itemModel),
ItemDataType.REAL => InitializeTag<RealPlcMapper, float>(itemModel),
ItemDataType.LREAL => InitializeTag<LrealPlcMapper, double>(itemModel),
ItemDataType.BOOL => configuration.PlcType == EEIPPlcType.CompactLogix
? InitializeTag<ExtesionClass.BoolPlcMapper, bool>(itemModel)
: InitializeTag<libplctag.DataTypes.BoolPlcMapper, bool>(itemModel),
ItemDataType.STRING => InitializeTag<ExtesionClass.StringPlcMapper, string>(itemModel),
_ => null,
};
}
protected internal IItem? InitializeTag<M, T>(EEIPItemModel itemModel) where M : IPlcMapper<T>, new()
{
try
{
return new EEIPItem<M, T>(itemModel, configuration);
}
catch (LibPlcTagException ex)
{
throw new ItemException(MessagesError.EEIPItemCreateException, ex);
}
} new EEIPItem() performs the tag initialization action I mentioned in the first comment. Some of the mappers I had to create myself (Bool, Byte, String, UInt, ULong, UShort) |
Be careful. A single BOOL is returned as a byte value (IIRC). But a BOOL array is returned as some number of UDINT values (actually data type 0xD3). If the BOOL is in a UDT, then it is different again. I should really write up a wiki page just for BOOL. |
In terms of my stance towards Were you able to use the advice above to work with the BOOL[0..15] tag? |
No, for now I'm on another project, as I said above I bypassed the problem by declaring the array with 32 positions, but monitoring only 16 of them, as soon as I have some time I think I'll stop using mappers and I'll try to find one generic solution to directly instantiate Tag(). Thanks for sharing the link to the discussion on Tag<M, T> I missed it. |
Ok great - thanks! |
<VariableArray itemId="Allarms" dataType="BOOL" dimension="16" />
I have this tag, a bool array of 16 positions, which when I try to monitor gives me the error: OutOfBound, but if I declare the array of size 32 at plc level and go to monitor the 16, as before, it works.
The text was updated successfully, but these errors were encountered: