I'm trying to communicate with a PLC that accepts/sends 16-bit values, with each single bit allowing for a check to happen or not.
To do this, I've been attempting to use the .Net BitArray but the results have been anything but succesful.
The underlaying structure is made out of an array of two bytes, both bytes are initialised with the value 0.
When I create a new bitarray using one of these bytes, I expected to get an array with 8 values set to false. This is not the case.
With a byte value of 0, the length and count of the bitarray is also zero. While I could presume that leading zeros are dropped, this seems very counterintuitive.
When I create a bitarray using a byte with the value of 200, I expected to get an array with 8 values (True, True, False, False, True, False, False, False). However, I instead get a bitarray with a length and count of 200?
Code is currently this :
Private FaultBits as Byte = 0
Public Sub SetBitValue(index As Integer, value As Boolean)
Try
If index < 0 Then
Throw New Exception("Index is below zero!")
End If
If index > 7 Then
Throw New Exception("Index out of bounds! Maximum allowed index value is 7")
End If
'If BitConverter.IsLittleEndian Then
'ToDo
'End If
Dim bitArray_Section As BitArray = Nothing
bitArray_Section = New BitArray(FaultBits)
'bitArray_Section.Length = 8 'Truncates incorrectly
bitArray_Section.Item(index) = value 'Set the individual bit
FaultBits = ConvertToByte(bitArray_Section) 'Set back to byte
Catch ex As Exception
Throw New Exception("clsFaultBits : SetBitValue : w. Index " & index & " : Exception : " & ex.Message())
End Try
End Sub
And the get-equivalent :
Public Function GetBitValue(index As Integer) As Boolean
Try
If index < 0 Then
Throw New Exception("Index is below zero!")
End If
If index > 7 Then
Throw New Exception("Index out of bounds! Maximum allowed index value is 7")
End If
Dim bitArray_Section As BitArray = Nothing
bitArray_Section = New BitArray(FaultBits)
'bitArray_Section.Length = 8
Return bitArray_Section.Item(index)
Catch ex As Exception
Throw New Exception("clsFaultBits : GetBitValue : w. Index " & index & " : Exception : " & ex.Message())
End Try
End Function
The convert function, I assumed this would have a length of 8 which is wrong :
Public Function ConvertToByte(bits As BitArray) As Byte
Try
If bits.Count <> 8 Then
Throw New Exception("Invalid amount of bits!")
End If
Dim returnbyte(1) As Byte
bits.CopyTo(returnbyte, 0)
Return returnbyte(0)
Catch ex As Exception
Throw New Exception("clsFaultBits : ConvertToByte : Exception : " & ex.Message())
End Try
End Function
ByteValue :: BitarrayLength / Count
0 :: 0 / 0
200 :: 200 / 200
10 :: 10 / 10
What I would like to accomplish :
Receive a byte (1-0-0-1-0-0-1-0)
Enable the booleans in the program by reading the individual bits: Check1, Check4, Check7
Set the individual bits of the output Byte starting at 0-0-0-0-0-0-0-0
Turn on 5 : 0-0-0-0-1-0-0-0
Turn on 2 : 0-1-0-0-1-0-0-0
Send Byte
Am I completely misusing the BitArray class? What am I doing wrong? What would allow me to change individual bit values without running into this chaos?
Why is the length / count of the BitArray the same value as the Byte, instead of the amount of bits the Byte is composed of?
I am aware the code has yet to take in account endian-ness.
Thanks in advance,
I'm not sure BitArray class is what you need. Anyway you can't create a BitArray from an Integer value. The statement New BitArray(200)
, for example, will create a BitArray of 200 items all set to 0.
If you need to send 16-bit values I think it would be simpler to use UShort
(also called UInt16
) datatype instead of a BitArray and use @djv suggestion to check the single bit. To set bits you have to make use of some "binary" algebra and the And
operator. Remember to always use unsigned datatypes and be aware that bit count starts from right.