Search code examples
vb.netbytebitarray

VBnet Accessing individual bits of a byte // BitArray length & count are equal to the byte value?


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,


Solution

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