.NET Forum / .NET Framework / Compact Framework / August 2007
Accessing the Bluetooth COM ports in VB
|
|
Thread rating:  |
silverfox - 09 Aug 2007 05:51 GMT I have been trying to write a VB program to use Bluetooth to communicate between a PDA running Windows CE 4.2 and another BT device. I found this article that got me started: http://www.devx.com/wireless/Article/11511
Using the technique in this article, I can successfully transmit data but the receive part fails. In fact it slows the PDA to a crawl. Does anyone have any ideas on how to modify the original program so that the receive function will work?
BTW, I am using VS 2005 and the original program was for an earlier version of VS. I am not sure if this is relevant.
Here is the relevant section of the source from the article:
Dim infileHandler As Long Dim outfileHandler As Long Dim numReadWrite As Integer Dim t1 As System.Threading.Thread Dim stopThread As Boolean = False
Public Sub connect() '---port number for Bluetooth connection Dim inPort As Short = 8 Dim outPort As Short = 6
'---Opens the port for Bluetooth infileHandler = CreateFile("COM" & inPort & ":", _ &HC0000000, 0, 0, 3, 0, 0) Application.DoEvents() outfileHandler = CreateFile("COM" & outPort & ":", _ &HC0000000, 0, 0, 3, 0, 0) Application.DoEvents()
'---invoke the thread to receive incoming messages stopThread = False t1 = New Threading.Thread(AddressOf receiveLoop) t1.Start() End Sub
Public Sub disconnect() stopThread = True CloseHandle(infileHandler) CloseHandle(outfileHandler) End Sub
<DllImport("coredll.dll")> _ Private Shared Function CreateFile(ByVal lpFileName As String, _ ByVal dwDesiredAccess As Integer, _ ByVal dwShareMode As Integer, _ ByVal lpSecurityAttributes As Integer, _ ByVal dwCreationDisposition As Integer, _ ByVal dwFlagsAndAttributes As Integer, _ ByVal hTemplateFile As Integer) As Integer End Function
<DllImport("coredll.dll")> _ Private Shared Function ReadFile(ByVal hFile As Integer, _ ByVal Buffer() As Byte, _ ByVal nNumberOfBytesToRead As Integer, _ ByRef lpNumberOfBytesRead As Integer, _ ByRef lpOverlapped As Integer) As Integer End Function
<DllImport("coredll.dll")> _ Private Shared Function WriteFile(ByVal hFile As Integer, _ ByVal Buffer() As Byte, _ ByVal nNumberOfBytesToWrite As Integer, _ ByRef lpNumberOfBytesWritten As Integer, _ ByVal lpOverlapped As Integer) As Boolean End Function
<DllImport("coredll.dll")> _ Private Shared Function CloseHandle(ByVal hObject As Integer) As Integer End Function
Public Function send(ByVal message As String) As Integer '---send the message through the serial port Dim value As String = message & vbCrLf Dim retCode As Integer = WriteFile(outfileHandler, _ stringToByteArray(value), _ value.Length(), _ numReadWrite, _ 0) txtMessageLog.Text += value Return retCode End Function
Public Sub receiveLoop() '---receive the message through the serial port Dim inbuff(300) As Byte Dim retCode As Integer = ReadFile(infileHandler, _ inbuff, _ inbuff.Length, _ numReadWrite, _ 0) Application.DoEvents() While True If retCode = 0 Or stopThread Then 'MsgBox("Error reading message.") Exit While Else Dim updateDelegate As New _ myDelegate(AddressOf updateMessageLog)
updateDelegate.Invoke(byteArrayToString(inbuff)) ReDim inbuff(300) retCode = ReadFile(infileHandler, _ inbuff, _ inbuff.Length, _ numReadWrite, _ 0) Application.DoEvents() End If End While End Sub
Public Delegate Sub myDelegate(ByVal str As String)
Public Sub updateMessageLog(ByVal str As String) If str.Length > 0 Then txtMessageLog.Text += "-->" & str End If End Sub
The only thing I had to change was the port numbers to match the BT COM ports on my PDA. The Text box for receiving the incoming stream immediately becomes filled with repeated instances of -->, as updateMessageLog is apparently called repeatedly. I hope that there is a simple solution to this problem.
Daniel Strigl - 09 Aug 2007 08:17 GMT silverfox schrieb:
> Public Sub receiveLoop() > '---receive the message through the serial port [quoted text clipped - 32 lines] > End If > End Sub Why do you invoke your "updateMessageLog" method before you read the data from the port?
Try to move the invoke after the "ReadFile" part.
 Signature Daniel Strigl [daniel.strigl@gmx.takethisout.at, remove 'takethisout.'] Web: http://www.hh-system.com/danielstrigl Blog: http://geekswithblogs.net/dastblog
silverfox - 09 Aug 2007 20:55 GMT On Aug 9, 12:17 am, Daniel Strigl <daniel.str...@gmx.takethisout.at> wrote:
> silverfox schrieb: > [quoted text clipped - 44 lines] > Web:http://www.hh-system.com/danielstrigl > Blog:http://geekswithblogs.net/dastblog Well first, this is the code in the article, not mine. But if you look at the code you see that he precedes the loop with a read, so there is always a read preceding every call to updateMessageLog.
Dick Grier - 09 Aug 2007 17:04 GMT Hi,
Since you are using VS2005, why not use the built-in SerialPort object (data are read in a background thread)? In general, you will not need Application.DoEvents when using a thread, which will give you good overall performance -- and (IMO), you should buffer a reasonable amount of data before you log it.
I have a more complete source code example, that a number of people are using on Windows CE 4.2 systems in my book. I show two different methods for reading data using a threaded model. See below.
Dick
 Signature Richard Grier, MVP Hard & Software Author of Visual Basic Programmer's Guide to Serial Communications, Fourth Edition, ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March 2006. See www.hardandsoftware.net for details and contact information.
silverfox - 09 Aug 2007 22:55 GMT > Hi, > [quoted text clipped - 18 lines] > 2006. > Seewww.hardandsoftware.netfor details and contact information. Thanks, Dick. I guess I should buy your book!
silverfox - 09 Aug 2007 23:23 GMT > Hi, > [quoted text clipped - 18 lines] > 2006. > Seewww.hardandsoftware.netfor details and contact information. Well, I haven't purchased your book yet, but in my first experiment using a SerialPort object, I got an error on opening the output port. The stack trace showed an IOException thrown at SerialPort.open():SerialStream.setBufferSizes():SerialStream.checkResult():WinIOError()
The relevant code executed (in my prog) consists of only the following two lines:
System.IO.Ports.SerialPort serialOutputPort = New System.IO.Ports.SerialPort("COM8") serialOutputPort.open()
-- don
silverfox - 10 Aug 2007 00:09 GMT > > Hi, > [quoted text clipped - 32 lines] > > -- don Another interesting thing about this little exception is that the program that caused it cannot be stopped. Quit doesn't work and going to Settings:System:Memory:Running Programs:Stop doesn't stop it either. Only a reset killed that program. And this is when it is sitting at the error display page! This has to be a Microsoft bug.
<ctacke/> - 10 Aug 2007 03:42 GMT I doubt it's a Microsoft bug. It's pretty certain that MS tested such a simple scenario before releasing, and it's equally certain that the many people using the serial libraries would have found and reported this before you.
My bet is that it's a problem with the device's bluetooth driver. It didn't implement something (or didn't implement it right) that the serial classes are trying to initialize. The fact that your original test with what one would expect to be known-working code also exhibited strange behavior also points to this same thing.
Personally I'd try to set up a really simple C++ app that opens the driver and dumps incoming data to the console just to see if that works, thereby removing all managed code questions from the equation. If that's not an option, then using classes that you have source for all the way down to the P/Invoke would be useful so you could trace it to the driver interface boundary, again removing the possibility that it's your code (or the managed port class) causing the issue.
 Signature Chris Tacke, Embedded MVP OpenNETCF Consulting Managed Code in an Embedded World www.OpenNETCF.com
>> > Hi, >> [quoted text clipped - 42 lines] > either. Only a reset killed that program. And this is when it is > sitting at the error display page! This has to be a Microsoft bug. silverfox - 10 Aug 2007 05:26 GMT > I doubt it's a Microsoft bug. It's pretty certain that MS tested such a > simple scenario before releasing, and it's equally certain that the many [quoted text clipped - 67 lines] > > either. Only a reset killed that program. And this is when it is > > sitting at the error display page! This has to be a Microsoft bug. I haven't had a chance to do what you suggest and it will be more than a short gentle curve for me to figure out how. But are you saying that you think that the problem is with the Widcomm stack that HP ships with all its iPAQs? Isn't that equally unlikely?
<ctacke/> - 10 Aug 2007 13:29 GMT > I haven't had a chance to do what you suggest and it will be more than > a short gentle curve for me to figure out how. But are you saying > that you think that the problem is with the Widcomm stack that HP > ships with all its iPAQs? Isn't that equally unlikely? Since I know how OEMs tend to test, it's not as unlikely no. It's also possible that how they tested the ports differs from how you're trying to use them (I can pretty much guarantee they used native code to test). My guess is that the serial classes are trying to set up some parameter that makes sense in a real serial connection, but HP didn't implement or implemented incorrectly that same parameter and never bothered to test what happens when you try to change it. Good examples might be baud rate, flow control, parity, stop bits, timeouts, etc.
 Signature Chris Tacke, Embedded MVP OpenNETCF Consulting Managed Code in an Embedded World www.OpenNETCF.com
silverfox - 10 Aug 2007 17:46 GMT > > I haven't had a chance to do what you suggest and it will be more than > > a short gentle curve for me to figure out how. But are you saying [quoted text clipped - 15 lines] > OpenNETCF Consulting > Managed Code in an Embedded Worldwww.OpenNETCF.com Actually, I was originally referring to the inability to stop the program once the OS caught an IOException and reported the problem. I would have thought that the Quit button on the OS-generated dialog box would have worked at that point regardless of any problem with the driver. And barring that, the STOP running program in the System>Memory Running Programs dialog should work regardless of a problem with a third party driver. And when both of those things fail that seems like a bug in the OS to me. But maybe that's just me.
So, is it your opinion that HP is at fault here for including a BlueTooth stack that is incompatible with Windows CE, at least with the SerialPort API? The Widcomm stack is VERY widely used on PDAs running Windows CE, by the way, and I would be surprised to find that such an obvious application as serial communications was not tested at least to the point to see that the Open method didn't fail every time. But again, maybe that's just me.
Paul G. Tobey [eMVP] - 10 Aug 2007 17:57 GMT You don't know much about operating systems. What if the application isn't running application code at the time of the "stop"? What if it's in the middle of a driver call? Is the driver left in a bad state? Can the OS terminate the driver, too? What if another application is also in the middle of a call to that driver? What if the driver is for the display? It's not so simple to 'just' terminate an application.
The most-likely place for the bug is your code. I'm not convinced yet that you are the source of the problem. The second most-likely is in the .NET CF, hence the suggestion that you take that out of the loop by using native code. The third most-likely is the Bluetooth stack, as it was probably only tested for the standard communication tasks: headset, ActiveSync and maybe Bluetooth serial for GPS. The lest-likely is the operating system itself. It's certainly not bug-free, but it gets used in a lot more different scenarios than any individual program, driver, or framework.
Paul T.
>> > I haven't had a chance to do what you suggest and it will be more than >> > a short gentle curve for me to figure out how. But are you saying [quoted text clipped - 34 lines] > least to the point to see that the Open method didn't fail every > time. But again, maybe that's just me. silverfox - 12 Aug 2007 07:59 GMT On Aug 10, 9:57 am, "Paul G. Tobey [eMVP]" <p space tobey no spam AT no instrument no spam DOT com> wrote:
> You don't know much about operating systems. What if the application isn't > running application code at the time of the "stop"? What if it's in the [quoted text clipped - 51 lines] > > least to the point to see that the Open method didn't fail every > > time. But again, maybe that's just me.
>> You don't know much about operating systems. Ok, I admit it.
I don't really see how the problem can be in my code, however, since it consists of only the following two lines:
System.IO.Ports.SerialPort serialOutputPort = New System.IO.Ports.SerialPort("COM8") serialOutputPort.Open()
Upgrading to CF2 SP2 got past this problem, however, and as I mention in another post, it now hangs on the following line:
serialPort.Write(msg)
I
Paul G. Tobey [eMVP] - 13 Aug 2007 16:57 GMT OK, I've looked through the old messages and I don't see what the characteristics of 'msg' are that you are passing to that Write method. You might try, if msg is a large amount of data, sending something simple, like a ASCII string (the three bytes 65, 66, 67 would be 'ABC' in ASCII), and seeing if the other end receives that.
Paul T.
> On Aug 10, 9:57 am, "Paul G. Tobey [eMVP]" <p space tobey no spam AT > no instrument no spam DOT com> wrote: [quoted text clipped - 82 lines] > > I silverfox - 13 Aug 2007 19:45 GMT On Aug 13, 8:57 am, "Paul G. Tobey [eMVP]" <p space tobey no spam AT no instrument no spam DOT com> wrote:
> OK, I've looked through the old messages and I don't see what the > characteristics of 'msg' are that you are passing to that Write method. You [quoted text clipped - 94 lines] > > > I I am in fact sending three ascii characters plus a CR.
Paul G. Tobey [eMVP] - 13 Aug 2007 20:00 GMT And the result on the sending end is nothing. What is the result on the receiving end? It sure sounds like no connection is established.
Paul T.
> On Aug 13, 8:57 am, "Paul G. Tobey [eMVP]" <p space tobey no spam AT > no instrument no spam DOT com> wrote: [quoted text clipped - 115 lines] > > I am in fact sending three ascii characters plus a CR. <ctacke/> - 10 Aug 2007 19:55 GMT > Actually, I was originally referring to the inability to stop the > program once the OS caught an IOException and reported the problem. I [quoted text clipped - 4 lines] > problem with a third party driver. And when both of those things fail > that seems like a bug in the OS to me. But maybe that's just me. Yes, it's just you. In the first case it's quite possible that a thread is blocking in a system call (like maybe a serial read thread stuck on WaitCommEvent) and that thread cannot be terminated. When the parent pukes, it becomes a zombie, not owned by really anything but preventing the process from being cleaned up.
The Running Programs dialog only sends a WM_CLOSE to the window, so it's rarely going to shut down anything that isn't in a known, well-behaved state and that has a nice main window that's non-modal and that cleans up all of its threads when that window is closed. Basically that means it's pretty useless for a developer.
> So, is it your opinion that HP is at fault here for including a > BlueTooth stack that is incompatible with Windows CE, at least with [quoted text clipped - 3 lines] > least to the point to see that the Open method didn't fail every > time. But again, maybe that's just me. I'm not placing blame yet. Based on the evidence I do suspect it's the bluetooth serial driver interface (not the stack, I'd like to point out). The fact it's widely used by people, who mostly use it for things like audio, doesn't hold much sway with me. What percentage of devices have that stack? Maybe 10%? What percentage of users with that device use it for serial comms? Maybe 10%? What percentage of those are using the managed class to access it? Maybe 30%? If my junior high math is still correct 0.1 * 0.1 * 0.3 is a pretty small number.
I wouldn't consider it "obvious" by any stretch. I'm somewhat familiar with what an OEM might do for testing. I'm also vaguely familiar with the pressures they're under to ship a device, and how even if BT serial failed but all otehr tests passed how they still might be very highly inclined to ship due to that really small number above.
But maybe that's just me.
 Signature Chris Tacke, Embedded MVP OpenNETCF Consulting Managed Code in an Embedded World www.OpenNETCF.com
silverfox - 10 Aug 2007 20:41 GMT > > Actually, I was originally referring to the inability to stop the > > program once the OS caught an IOException and reported the problem. I [quoted text clipped - 47 lines] > OpenNETCF Consulting > Managed Code in an Embedded Worldwww.OpenNETCF.com Ok, you convinced me. I should not have come off sounding so haughty when I am such a newbie at this. Thanks for you feedback!
As to the percentage of devices using the Widcomm stack, I was under the impression that it was the majority of the Smart Devices out there, but I can't find the reference right now. And yes, bundled BT software on a PDA probably uses the Widcomm API to control the BlueTooth device rather than either of the two ways I tried.
So, all that aside, can you think of a solution to my problem? (Other than buying the Widcomm development kit, which costs $1495.)
<ctacke/> - 10 Aug 2007 20:53 GMT > As to the percentage of devices using the Widcomm stack, I was under > the impression that it was the majority of the Smart Devices out > there, but I can't find the reference right now. And yes, bundled BT > software on a PDA probably uses the Widcomm API to control the > BlueTooth device rather than either of the two ways I tried. Widcomm is used by a lot, so is Microsoft (and if you count Symbol, there's a third stack floating out there too).
> So, all that aside, can you think of a solution to my problem? (Other > than buying the Widcomm development kit, which costs $1495.) I doubt their SDK will be of much use (there's anotehr SDK that I can't recall the name of offhand that supports both the MS and Widcomm stuff, so if you end ep buying something, I'd get that instead). The first thing you need to do is try to see if that truly is where the problem lies. Either a native app or a managed app (the free OpenNETCF Serial stuff[1] has an identical interface, so the code swap should be trivial) but where you can run all the way to the API calls in the debugger would be very useful.
 Signature Chris Tacke, Embedded MVP OpenNETCF Consulting Managed Code in an Embedded World www.OpenNETCF.com
[1] http://www.opennetcf.com/FreeSoftware/OpenNETCFIOSerial/tabid/252/Default.aspx
Dick Grier - 10 Aug 2007 16:39 GMT I agree with Chris. I haven't seen this on my units.
So... I suspect a driver problem. These things are imposible for us as developers (from the outside looking in) to fiddle. Does the SerialPort object in CF2 suffer the same problem?
 Signature Richard Grier, MVP Hard & Software Author of Visual Basic Programmer's Guide to Serial Communications, Fourth Edition, ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March 2006. See www.hardandsoftware.net for details and contact information.
silverfox - 10 Aug 2007 17:31 GMT > I agree with Chris. I haven't seen this on my units. > [quoted text clipped - 10 lines] > 2006. > Seewww.hardandsoftware.netfor details and contact information. I am sorry, Richard, I don't know what you mean by the SerialPort object in CF2. This is my first development project using Visual Studio and the first for a Pocket PC so I am a little behind the curve. I searched the Object Browser for SerialPort and used the only one I found, which is System.IO.Ports.SerialPort.
<ctacke/> - 10 Aug 2007 19:40 GMT > I am sorry, Richard, I don't know what you mean by the SerialPort > object in CF2. This is my first development project using Visual > Studio and the first for a Pocket PC so I am a little behind the > curve. I searched the Object Browser for SerialPort and used the only > one I found, which is System.IO.Ports.SerialPort. Yes, that means you are using the CF 2.0 Serial Port object (CF 1.0 didn't have one, so that leads us to the conclusion you're using CF 2.0 and the namespace highly indicates you're using Microsoft's library, not one of the many otehrs available like the one from Dick, OpenNETCF, Franson, etc).
 Signature Chris Tacke, Embedded MVP OpenNETCF Consulting Managed Code in an Embedded World www.OpenNETCF.com
silverfox - 12 Aug 2007 07:40 GMT > I agree with Chris. I haven't seen this on my units. > [quoted text clipped - 10 lines] > 2006. > Seewww.hardandsoftware.netfor details and contact information. The original problem WAS with the CF2 SerialPort object. I just upgraded to CF2 SP2 and see some incremental progress. Now I get past the open() but it hangs on Write(). I don't know what the correct baud rate is supposed to be but I have tried 9600 (the default), 19,200, and 38,400 and 57,600. I attempted 115,200 but got an error message saying that 64K was the max allowable. I think the defaults are probably correct for data bits, stop bits, parity but I don't know how to find out what is correct.
<ctacke/> - 12 Aug 2007 15:42 GMT Bluetooth has no baud rate, partity, etc. Setting one is irrelevent, and I still think that the problem lies in the driver not properly handling these settings.
 Signature Chris Tacke, Embedded MVP OpenNETCF Consulting Managed Code in an Embedded World www.OpenNETCF.com
>> I agree with Chris. I haven't seen this on my units. >> [quoted text clipped - 20 lines] > are probably correct for data bits, stop bits, parity but I don't know > how to find out what is correct. silverfox - 12 Aug 2007 18:47 GMT > Bluetooth has no baud rate, partity, etc. Setting one is irrelevent, and I > still think that the problem lies in the driver not properly handling these [quoted text clipped - 30 lines] > > are probably correct for data bits, stop bits, parity but I don't know > > how to find out what is correct. Yeah, I knew that those settings are irrelevant to the BT transceiver, but I thought that maybe, as one other poster suggested, the interface between the SerialPort object and the BT stack might need these settings to be correct. I am groping in the dark here as there is so much that I do not know about how it all fits together. Just trying to puzzle it all out.
So, if it is the driver, does that mean that I am out of business? Honestly, I don't really understand the distinction between the stack and the driver. There is only one software version listed in the iPAQ's BT asset listing, and on my machine it is 1.4.1.75, which is variously referred to on the web as the stack version and as the driver version. I am still not sure which that version refers to.
Well, I just found this link (http://www.salling.com/forums/ viewtopic.php?p=21525) which is the first indication I have found that there is a newer stack version available. I think I will give it a try and see if it helps. Any other suggestions are welcome.
Dick Grier - 13 Aug 2007 18:13 GMT Hi,
With BT, the actual port speed is arbitrary. You can use anything that is supported, with exactly the same result. You would want to use 8 data bits, with no parity. If the code hangs on Output... I'm confused. CFSerialIO.dll (from my homepage) use SerialPort.Output(somemessage) syntax. The SerialPort object in Visual Studio uses SerialPort.Write(somemessage) syntax.
I have never seen a "hang," though the Output method in my dll is a blocking method. Thus, if data are not accepted by the serial driver (control must be returned from the WriteFile API call), then what you are seeing is what I'd expect. I guess. Windows CE does not support Overlapped IO, so any non-blocking call to WriteFile requires extra effort -- and I've never seen the need. If this is the situation, there would seem to be some underlying mechanism that is the source of the trouble. Just, IMO, from the outside looking in.
Dick
 Signature Richard Grier, MVP Hard & Software Author of Visual Basic Programmer's Guide to Serial Communications, Fourth Edition, ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March 2006. See www.hardandsoftware.net for details and contact information.
silverfox - 13 Aug 2007 21:08 GMT > Hi, > [quoted text clipped - 24 lines] > 2006. > Seewww.hardandsoftware.netfor details and contact information. Dick, I just sent you a vb file containing the simplest possible example that hangs my iPAQ on a SerialPort.Write( ). The PDA must be physically reset after the hang. The program does nothing but create a SerialPort object with the string "COM8", calls Open( ) on that object then calls Write("ABC") on it. The program contains calls to MsgBox( ) before all four operations and after the Write( ). The last MsgBox to display is the one before the Write( ). The final one never appears. If anyone would like me to send them a copy of this vb file, please let me know.
Dick Grier - 14 Aug 2007 20:36 GMT See my replies to your email.
 Signature Richard Grier, MVP Hard & Software Author of Visual Basic Programmer's Guide to Serial Communications, Fourth Edition, ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March 2006. See www.hardandsoftware.net for details and contact information.
silverfox - 15 Aug 2007 01:35 GMT > See my replies to your email. > [quoted text clipped - 6 lines] > 2006. > Seewww.hardandsoftware.netfor details and contact information. A few posts back someone said that the SerialPort problem I was experiencing was most likely due an error in my code. I replied that my program contained only three significant lines of code and I didn't see how there could be a problem there. Well, ahem, it seems that I did screw up one of those three lines of code. The PDA has two serial ports dedicated to the bluetooth device, one for input and one for output. And, you guessed it, I switched them. I tried to write to the input port. 40 years of programming should have taught me that no matter how small a program, I am capable of getting something wrong. Donald Knuth, I am not. So, I am sorry for all the bandwidth and time anyone might have spent reading about or thinking about my problems with SerialPort.Write( ) hanging my PDA. It works fine when you write to the output port instead of the input port. My attempts to get SerialPort.Read( ) to work (yes, on the input port) are still unproductive, but Richard Grier sent me some information on that problem and I hope to have the whole thing put to bed soon. Thank you for your patience and please accept my apologies. And Richard, thank you especially for your help.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|