VB MSCOMM32 - Buffer Input problem

I am using VB6 to communicate with an Arduino microcontroller through the MSCOMM32 DLL.

It is working great, however, I am having trouble isolating each instance of information to process, one at a time.

I don't have the code with me right now, but I basically have a loop on the board that is sending information out the serial port with the serial.print command. Example "something like this": x = 1 Void Loop Serial.Print x x = x + 1

Anyhow, instead of having, say, "1" in the comm buffer on the first cycle of the Arduino loop, I may have 1234 all at once, etc. But, I just need the "1" first, "2" 2nd, etc. on the VB end in order to process each value. It is as if the information is overrunning the mscomm32 buffer too quickly.

Any ideas on how to overcome this? ie, parsing, handshaking, or some other way I need to be sending the info out from the board?

Thanks in advance for you help. Coby.

You need to have some separator between packets. With <1><2><3><4>, it’s easy to see what constitutes a packet. It’s also easy to detect when a packet is not complete.

Paul,

Outstanding idea. That will work just fine.

I am new to being in control on both ends now that I am programming the microcontroller. In the past I had one read info from pre-programmed devices. I am so used to dealing with whats handed to me that I am just too quick to panic. I was forgetting . . . I can determine this now . . . control is great.

I am loving this Arduino work!!!!

Thanks, again, Paul. I will give it a try tonight when I get home and repost my resuts and code later.

Coby.

You can use Serial.println() which automatically inserts a carriage return (ASCII 13) between each packet. Then just have VB6 scan the input buffer using the midstring function Mid() until you find a "vbcr" which is a reserved word in VB6 which is equal to CHR(13).

The tricky part is to remove the beginning of the buffer up to the vbcr and leave the remaining data in the buffer until the next vbcr is found. I do this same method using a simple timer to poll the input buffer every 50ms or so.

BKnight760, thanks for the tip. That's a good line to know. I will go with what Paul says and use the Serial.printin() as my way of seperating since I like using any commands that are already provided, then parse to an array using Split() or the mid() function in VB, and be home free on this step of my project.

Thanks, guys, for all the help.

Coby.

Ok . . . still having a problem. My strings are cut off. Perhaps, due to the data type? I don't know? Thanks for helping again.

Here are two packets I received: They were supposed to be counting 111, 112, 113, 114 etc.

They came through in two packets like so: Packet 1 "112 1"

Packet 2 "13 114 "

Here's what I have running on the board:

long x = 0;

void setup() // run once, when the sketch starts { Serial.begin(9600); // set up Serial library at 9600 bps }

void loop() // run over and over again { x = x + 1; delay(500); Serial.println(x,DEC); }

Here's my VB code:

Private Sub MSComm1_OnComm()

'Values Dim X As Long

'Strings Dim InBuff As String Dim strInput() As String Dim strViola As String

'Variants Arrays

On Error GoTo Err_Handle

Select Case Me.MSComm1.CommEvent Case comEvReceive ' Received RThreshold # of chars.

InBuff = InBuff & Me.MSComm1.Input

strInput = Split(InBuff, Chr(13))

If IsEmpty(strInput) = False Then For X = LBound(strInput) To UBound(strInput) strViola = Trim(strInput(X))

If IsNumeric(strViola) = True Then With Form_UserMainDashboard .Text_Len2Display.Text = strViola .Text_Len2Display.Refresh End With End If Next X End If

End Select

Err_Resume: Exit Sub

Err_Handle: MsgBox "Error Number: " & Err.Number & Chr(32) & Err.Description

GoTo Err_Resume

End Sub

This is as expected. The "input" is what has been received by the PC at the time you call this method. How shall it know you are waiting for more input????

There is more string handling needed. Just take the part right hand from the first (!) CR and remember it for the next call (concatenate the new input).

And mind the NLs... It might simplify the matter a little bit if you do not use println but send the CR as character 0x0d.

Good morning

Any news about this project? Any final solution?

Thanks on advance Best regards Pedro Ferrer

deSilva is correct.

The solution is simple, and I tried to warn you of this issue in my previous post:

“The tricky part is to remove the beginning of the buffer up to the vbcr and leave the remaining data in the buffer until the next vbcr is found. I do this same method using a simple timer to poll the input buffer every 50ms or so.”

Serial data is transmitted 1 byte (character) at a time. So, your data will show up as:
“1”
“11”
“112”
“112”
“1121”
“11211”
“112113”

and so on.

Since you are polling VB’s receive buffer randomly, you cannot expect any certain amount of data to exist in the buffer.

So what you do is append any new data to the data previously revceived.

ReceivedData = ReceivedData & MSComm1.Input

Then, use the Mid() function (basically a substring function) to find the first vbcr in the string. Once you found the first vbcr, everything before it is one command. Remove the command from the string, AND KEEP THE REST OF THE STRING.

for i=1 to len(ReceivedData)
if mid(ReceivedData,i,1) = vbcr then
Command = Mid(ReceivedData,1,i)
ReceivedData=Mid(ReceivedData,i+1,len(ReceivedData))
end if
next i

This way, when you poll the receive buffer the next time, you’ll get the rest of the data you need.

A word of warning here though… You need to make sure that your VB loop keeps up with the amount of data that the Arduino is sending it. The Mid() function doesn’t have very good performance when the strings get very very long.

Hello

Thanks by your reply BKnight760, it was a great help. It works now!

ON VB6

'\ Private Sub Form_Load()

With MSComm1 'sets up COM settings .Handshaking = 0 .RThreshold = 1 .RTSEnable = False .CommPort = 2 .Settings = "9600,n,8,1" .DTREnable = False .PortOpen = True End With

End Sub

'\SEND 'T' LETTER TO ARDUINO Private Sub Command10_Click()

Me.Text1 = "" MSComm1.Output = "T" + Chr(13)

End Sub

'\ Private Sub MSComm1_OnComm()

Dim ReceivedData As String Dim Command As String Dim strDump As String Dim strChr As String

Do While MSComm1.InBufferCount > 0 If MSComm1.InBufferCount > 0 Then 'check for something in buffer strChr = MSComm1.Input ' copy to string If Asc(strChr) = 13 Then ' end if string Exit Do ElseIf Asc(strChr) = 10 Then ' remove chr(10) from string Else strDump = strDump & strChr ' connect chr to string End If End If DoEvents Loop

ReceivedData = strDump Dim i As Integer For i = 1 To Len(ReceivedData) If Mid(ReceivedData, i, 1) = vbCr Then Command = Mid(ReceivedData, 1, i) ReceivedData = Mid(ReceivedData, i + 1, Len(ReceivedData)) End If Next i Me.Text1 = Me.Text1 & ReceivedData

End Sub

ON ARDUINO

int command = 0;

void setup() { Serial.begin(9600); }

void loop() { if (Serial.available()) { command = Serial.read(); if (command == 'T') { Serial.println("U ARE THERE"); delay(5000); Serial.println("U WERE THERE"); command=0; } } }

For now, I have the final result on text1. Don't forget to put it as multiline=true.

Thanks once again by the prompt help Best regards Pedro Ferrer