What is the best way to access a serial port from VBA?
I have a need for some of our sales reps to be able to send a simple string over the serial port from an action button in PowerPoint. I don't commonly use VBA, especially for anything like this. Normally I would turn it into an application of some sort, but I actually don't think the idea is that bad. It will be a handy tool for them to demo this device with while on a projector and talking to other sales guys and non technical people. Also, this sales guy will have no problem making small modifications to the VBA or PowerPoint presentation, but would not do as well with recompiling a .NET application.
I know we could do it through a batch file run from the presentation on the action, but that doesn't make me very happy. I figure we could probably access a COM object and run from there, but again I am not real up on the latest and greatest libraries to use in VBA, and it would also be nice to get a quick little primer in how to easily open, send and close the connection.
Since this will need to be run on multiple people's computers, it would be nice if it would be easily transportable to other machines. I should be able to say it has to run on Office 2007 and Windows XP. Compatibility with anything else would be a nice bonus though.
How should I go about handling this? Any good tips or tricks? Library recommendations?
Click the Client Device tab. Select the Override Parent's Settings or Override Global Settings check box. To enable access to serial ports, select the Enabled check box. To disable access to serial ports, deselect the Enabled check box.
1) Click Start. 2) Click Control Panel in the Start menu. 3) Click Device Manager in the Control Panel. 4) Click + next to Port in the Device Manager to display the port list.
By looping the transmit and receive pins, you can test serial cable port communication by checking if the serial ports connections transmit and receive valid information. This is called a loopback test and can be used to test rs232 communication. Use a screwdriver to loop pins for testing.
The Win32 API handles the serial port as a file. You can access the serial ports directly by calling these API functions from within VBA. I had to do this for an old .NET application but VBA is no different.
Rather than hash it out for you on this site, here's a reference I've hung onto over the years. How to perform serial port communications in VBA
Sub Stinky()
Dim COM_Byte As Byte
Dim Received_Lines As Long
Dim Input_Buffer As String
Dim Output_Buffer As String
Dim Chars2Send As Long
Dim CharsRemaining As Long
Dim lfsr As Long
Open "COM7:9600,N,8,1" For Random As #1 Len = 1
Input_Buffer = ""
CharsRemaining = 0
Do
Get #1, , COM_Byte
If COM_Byte Then
If COM_Byte = 13 Then ' look for CR line termination
Debug.Print Input_Buffer, Now ' print it
Input_Buffer = "" ' and clear input buffer
' generate some output (9 characters)
lfsr = &H3FFFFFFF - 2 ^ (Received_Lines And 15)
Output_Buffer = "?@@@@@@@@"
Chars2Send = 9
CharsRemaining = 9
For j = 0 To 2
Mid(Output_Buffer, 2 + j, 1) = Chr(Asc(Mid(Output_Buffer, 2 + j, 1)) + (31 And Int(lfsr / 32 ^ (2 - j))))
Next j
Debug.Print Output_Buffer
' show what I generated
Received_Lines = Received_Lines + 1 ' keep track of received line count
Else
Input_Buffer = Input_Buffer & Chr(COM_Byte) ' assemble output buffer
' process any characters to send
If CharsRemaining Then
CharsRemaining = CharsRemaining - 1
COM_Byte = Asc(Mid(Output_Buffer, Chars2Send - CharsRemaining, 1))
Put #1, , COM_Byte
End If
End If
End If
DoEvents
Loop
Close
End Sub
This works for me. I'm not sure if the OPEN actually sets up the Baud rate, as I first used TeraTerm. My COM port is a USB connection to a BASYS3 prototyping kit. It is spewing characters at 9600, records of 36 characters ending with CR. I can randomly send commands of 9 characters. In the above code, I generate these command strings every time I have received a new line. The way I chose which character to send is a little clunky: perhaps a better way is to have a character pointer and a number of characters, and when those go equal to set them both to zero.
Here is a brief module of VBA code that can send and receive messages on a PC serial port. This is not very elegant, but it is simple and should work on modern versions of Excel and Windows.
You are left on your own to expand the functionality and store or parse the messages. This just shows the low-level stuff to deal with the serial port.
The first 5 lines declare the millisecond "Sleep" library function (based on Excel version).
The SerialPort() subroutine outlines the steps to open the port, transmit some data, receive some data, try again to receive some data (to show that it really does not run afoul of the "end of file" error), and close the port.
#If VBA7 Then ' Excel 2010 or later
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal Milliseconds As LongPtr)
#Else ' Excel 2007 or earlier
Public Declare Sub Sleep Lib "kernel32" (ByVal Milliseconds As Long)
#End If
Public Sub SerialPort()
' open a COM port, transmit a message, gather results, close the port.
' open the COM port as file #1
Debug.Print "Open COM port 4"
Open "COM4:115200,N,8,1" For Binary Access Read Write As #1
transmit$ = Chr(2) + "Hello, World." + Chr(13)
receiveDummy$ = "~~~"
' transmit a message
Put #1, , transmit$
Debug.Print "Message sent."
' wait a bit for a response
Sleep 100
' check for received message
Debug.Print "Look for incoming message."
On Error Resume Next
Do While True
receive$ = receiveDummy$ 'dummy value
Input #1, receive$
If receive$ = receiveDummy$ Then Exit Do 'the string didn't change, so move on
Debug.Print receive$
Loop
On Error GoTo 0
' do it again to show that the empty input queue doesn't stop the flow
Debug.Print "Look again for incoming message (should not stop on error)."
On Error Resume Next
Do While True
receive$ = receiveDummy$ 'dummy value
Input #1, receive$
If receive$ = receiveDummy$ Then Exit Do 'the string didn't change, so move on
Debug.Print receive$
Loop
On Error GoTo 0
' close the serial port
Debug.Print "Close COM port."
Close #1
Debug.Print "Done."
End Sub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With