How to receive binary data in VB6?

I can receive ascii-formatted integers without a problem - I just want to avoid the overhead of formatting on my embedded PIC microprocessor & I the overhead of extracting the data back into integer form at the PC end.  
I've set MScomm.InputMode to binary, and the Rthreshold to 10 bytes (0 because I have 5 channels worth of 16 bit data)
 
Every string received is minced: its either the null string"", or "?????"

Private Sub MSComm1_OnComm()    
    Dim i As Integer
    Dim InBufferCount As Integer
    Dim Tmp As Integer
    UploadData As String ' I've tried Byte and Variant. A byte array might work, but I don't know how to copy a String into a
                                   ' Byte array  
 
   InBufferCount = MSComm1.InBufferCount ' is 10 only if inputMode is set to Text
    UploadData = MSComm1.Input ' copy Input in case it gets overwritten by more incoming data
           
    For i = 0 To 4 ' 5 channels of 16 bit data - haven't included the stuff to combine the hi & lo bytes.
' this is the bit that doesn't work....
        'Tmp = Val(Mid(UploadData, i, 1)) ' Tmp and Val give a type mismatch - can't seem to extract the data from the sub
                                                          ' string from Mid(UploadData, i, 1))
        Ch(i).Text = MidB(UploadData, (2 * i) + 1, 1) * 256   ' this works but only
                                                          ' when  UploadData contain Text rather than binary
    Next i

'End Sub

Any ideas?
KenMac06Asked:
Who is Participating?
 
softplusConnect With a Mentor Commented:
Sorry, my mistake -- don't use strings when retrieving binary data, use arrays of byte

Something like this:
dim intData%(0 to 4)
dim bytInput() as Byte

   InBufferCount = MSComm1.InBufferCount ' is 10 only if inputMode is set to Text
   ' should be 10, if you're waiting for 5 words
  bytInput = MSComm1.Input ' make sure inputMode is set to binary
  if InBufferCount <> 10 then exit sub ' throw error, whatever, something's fishy :)

  for i = 0 to 4
    intData(i) = bytInput( i*2 +1 ) * 256 + bytInput(i*2)
  next

One issue you'll need to cover: synchronisation! When do you start recieving? when do you stop? Do you always get 10 bytes? What happens when one byte goes missing or is corrupted in transmission? This will all depend a bit on your setup, I can't imagine that the input is just 5 words without any start/stop information :). Capturing the binary input from the serial port is the easy part, syncing it to the desired channels could be tougher - meaning you'll probably need to manage the input buffer yourself and read the values byte by byte, determine start/stop and somehow check for impossible values (meaning corrupted or missing bytes). A good idea would be to add some sort of simple start/stop information (for example 5x 0), a simple checksum (just xor the 5 words and pass that on the end). That way you know where to start recieving data, if data has been corrupted on the way - meaning you just collect valid data and throw the bad stuff away :)

John
0
 
softplusCommented:
Um, if the data is coming as a binary (byte), then you'll need to convert the string, try

bytValue = Asc(Mid(UploadData,i,1))  (will return a byte in the range 0 - 254)

For 5 channels of 16 bit data, you should however do it more like this:
For i = 0 to 4
  intValue = Asc(Mid(UploadData, i*2, 1)) * 256 + Asc(Mid(UploadData, i*2 + 1, 1))
Next
(possibly swap high and low bytes, I'm not certain)

This is assuming you're receiving the data correctly (i.e. speed, stopbits, parity all correct; which I assume since you were able to get text data).

John
0
 
softplusCommented:
"intValue" = the value for the channel, i.e. save it in an array or something; the way it is here it will be overwritten each time :)
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
KenMac06Author Commented:
The first problem is that UploadData is not getting the data - it seems as if, because its defined as a string, it will treat any 0 in the binary stream as a null terminator, and hence return "".  
0
 
cookreCommented:
From http://www.yes-tele.com/mscomm.html

Input Property
Returns and removes a stream of data from the receive buffer. This property is not available at design time and is read-only at run time.

Syntax
object.Input
The Input property syntax has these parts:
Part Description
object An object expression that evaluates to an object in the Applies To list.

Remarks
The InputLen property determines the number of characters that are read by the Input property. Setting InputLen to 0 causes the Input property to read the entire contents of the receive buffer.

The InputMode property determines the type of data that is retrieved with the Input property. If InputMode is set to comInputModeText then the Input property returns text data in a Variant. If InputMode is comInputModeBinary then the Input property returns binary data in an array of bytes in a Variant.
0
 
KenMac06Author Commented:
"If InputMode is comInputModeBinary then the Input property returns binary data in an array of bytes in a Variant." Does that mean that I have to copy the bytes from .Input,  one at a time, or is there a way to pass a pointer to a byte array, and copy a message-worth at a time? i.e. can I avoid having to  take over the responsibility of managing the input buffer?
 
0
 
super786Connect With a Mentor Commented:
If you leave it as a string, do a UploadData = StrConv(UploadData, vbUnicode).  This will pad your binary string out with ascii 0's so that it is a normal string.  Then your Mid() stuff should work properly.  What you are seeing with the "?????" is 10 bytes of data being treated as 5 unicode bytes, since all strings in VB are unicode.
0
 
KenMac06Author Commented:
I gave up on binary - I too was worried about synchronisation and not being able to add a checksum.
For the record, the overhead of formatting binary as ascii is insignificant (1 - 2 millisecs) in comparison to the time to transmit the bytes (1millisec/byte, so about 40 millisecs in all). That gets me 20 lots of samples per sec easily, and possibly 25. I'm digitising something with 5 shaft encoders, rather than a waveform against time, so it doesn't matter if I lose  the odd (set of) sample.
So here is the non-binary message catcher, for the record...

Private Sub MSComm1_OnComm()
' triggered by the arrival of 38 bytes 5 Channels worth of 16 bit samples, formatted as 5 ascii digits/chan, split up by commas.
' I use a timer to fire Q's out to a PIC micro, and it sends the data back. The two programs work in lock step.
' tried InputMode = Binary, to reduce the cpu overhead (no need to format the int16 as ascii),
' although it precludes software XOn/XOff flowcontrol or buffering
' However, UploadData was always "" or "?????"

' RThreshold = 10 for binary to suit the bare minumum packet size of 5 Channels worth of 16 bit samples
' Now 30 5 bytes/ch, comma delimiter after each field except for end of line <Cr><Lf>
' byte ordering:  Byte 0 = Ch(0)MSB...Byte 9:= Ch(4)LSB

' Comes into this Sub when MSComm1.InBufferCount = RThreshold i.e. 10 chars...
   
    Dim InBufferCount As Integer ' mostly just for checking in debugger to see how much data I've got
    'Dim Finish As Single
    Dim TmpString(5), T As String
    Dim i As Integer
    ' Dim Chan(5) As Integer ' Ch is the control - no need for Chan.
    Dim Tmp, Zsigned As Integer
    'Dim Period As Single
    Dim X, Z As Long
   
    'Finish = Timer   ' note end time.
    'Period = Finish - Start
    'txtPeriod.Text = Str(Period)
   
    InBufferCount = MSComm1.InBufferCount
    UploadData = MSComm1.Input ' copy Input in case it gets overwritten by more incoming data
       
   
    bReplyRxd = True
    For i = 0 To 4
        Ch(i).Text = Mid(UploadData, (6 * i) + 7, 5) ' String elements start at 1, not 0
                                                                        ' 6* because each field is delimited by a "," for readability
    Next i
   
End Sub
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.