?
Solved

How to receive binary data in VB6?

Posted on 2005-05-04
8
Medium Priority
?
2,102 Views
Last Modified: 2010-05-18
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?
0
Comment
Question by:KenMac06
8 Comments
 
LVL 13

Expert Comment

by:softplus
ID: 13927011
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
 
LVL 13

Expert Comment

by:softplus
ID: 13927030
"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
 

Author Comment

by:KenMac06
ID: 13928201
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:cookre
ID: 13928502
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
 

Author Comment

by:KenMac06
ID: 13934361
"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
 
LVL 13

Accepted Solution

by:
softplus earned 225 total points
ID: 13934456
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
 
LVL 1

Assisted Solution

by:super786
super786 earned 150 total points
ID: 14031321
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
 

Author Comment

by:KenMac06
ID: 14036153
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

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will learn different types of Android Layout and some basics of an Android App.
When you discover the power of the R programming language, you are going to wonder how you ever lived without it! Learn why the language merits a place in your programming arsenal.
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

755 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question