How to Code for RS232 in Visual Basic? Part 3 – Example

. Friday, October 23, 2009
6 comments

You can download the example program written in Visual Basic 6.0 from the following link:

MsCommSample.zip

Sample includes detailed explanations as comment lines, so I am not going to explaing details of coding in this post.

To test the software you need to have a null modem cable if you want to communicate two computers.

You can make your own cable by soldering pins of two female DB9 connectors as follows.

Connector 1                   Connector 2
Pin 2 <---------------------> Pin 3
Pin 3 <---------------------> Pin 2
Pin 5 <---------------------> Pin 5

If you just want to test how data is sent and received on your computer, you just need one connector; short circuit pin 2 and pin 3:

Connector 1
Pin 2 <--
        |
Pin 3 <--

Make the cables at your own risk, short circuiting any pins other than 2 and 3 may damage serial port of your computer.

By default, software opens the Com1 port in 9600 bauds, no parity, 8 data bits and one stop bit without handshaking protocol. You can change it in source codes.

You also need to have Visual Basic 6.0 software to edit, debug and recompile program.

How to Code for RS232 in Visual Basic? Part 2 – Getting Data From Serial Port

. Friday, August 7, 2009
3 comments


In this post, we are going to focus on OnComm event of serial port programming components. The most widely used serial port component is the MSComm.ocx of Microsoft, however it has some limited properties such as working up to COM16, you may also find more sophisticated components such as SAX Comm.

Also there was a TCommPort component for Delphi, also .Net has serial port support for 2005 and after. There are several alternatives to get data from serial port but the methods used for getting data is similar. So I want to explain this method in pseudo code in this post, and for the next post I want to give a real example with MsComm32.ocx and Visual Basic 6.0

There are two major methods to get data from serial port; polling method and event driven method. Polling method is the simplest, just place a timer on your form and continuously read the data from port. However with polling method you may get your data in partly, and you may need to write extra code to comb out different data packets received consecutively.

I want to focus on event driven method, which is more convenient, fast and less CPU consuming. 

Whatever the method used for reading, the first step is opening the port with proper communication parameters. Generally, I open the port on start up procedure of program, and do not close it until the end of program. You can't communicate with a closed port, so prefer to keep it always open. 

Some applications close the port when they do not need it, it may be useful especially in mobile devices to save power, but in desktop computers, it is better to keep always open, especially if your software is about industrial automation. 

I also get communication port settings from an ini file, because communication port parameters may depend on the device that you are communicating or the communication port limitations of the host computer, so remember to get the settings from an ini file, but this is optional, so say that it is the step zero of our pseudo code.

Setting up the port is easy, you must give following parameters:
- Communication speed
- Number of data bits; 7 or 8
- Type of parity; even, odd or none
- Handshake: Hardware handshake (RTS/CTS), software handshake (XON/XOFF) or none.

And if you prefer to use event driven method, you should also enable event triggering on data receive. For MSComm32.ocx it is set up by receive threshold value, you should set the number of bytes to trigger data received event.

Normally, I use 1 for receive threshold to get informed even a single byte received by comm port.  It should be better to set it to 1 if you receive variable length of data. In our examples, I am going to set it to 1.

With MSComm32.ocx, it is set up as follows:

MSComm1.RThreshold = 1

Then you can open the comm port. For MSComm32, it is opened as follows:

MSComm1.PortOpen = True

Sometimes, you may not be successful for opening the port, so it is strictly advised to code some error handling routines to catch any possible errors, otherwise your program may rise run time error and shutdown.  Most common errors are 'port already open / port already in use'  error and 'invalid port number'. There may be another software using your comm port, also another copy of your own software may block your port. To avoid blocking the comm port by the ghost of your software, it is better to check if another copy is already running on computer. 


We already have three steps of pseudo code including the optional one:

Step 0: Get communication port settings from ini file (Optional)
Step 1: Setup the port
Step 2: Open the port
  
Sending data is the simplest part, let's send 'Hello World' through comm port:

MSComm1.Output = "Hello World!"

If port is not open, you will probably get 'port not open / operation valid only when the port is open' error. So it is better to check if port is really open before sending data.

When data is received from a serial port, it is kept in a buffer until you read it. For MSComm32.ocx, you can get your data as follows:

Data = MSComm1.Input

If you put a timer on your form and continiously read the buffer, you get the data collected in buffer. This is called polling.

For event driven programming, you use the event triggered on receiving data. Here is the pseudo code for receiving a data by event driven programming:

Step 1: Continue if event is really triggered by received data.
Step 2: Disable event generation
Step 3: Wait for a while to get possible remaining bytes.
Step 4: Read and concatenate the data into a dummy static variable
Step 5: If expected data received completely (eg. received a terminator character), use it and clear the dummy static variable.
Step 6: Enable event generation


Now let's have a closer look into steps.

Step1: Some serial communication libraries use a single event for receiving. If you are using such kind of library, you don't need to check if event is triggered by received data. MSComm32 uses the same event for all communication port related events such as buffer owerflow, cts received etc. So it is necessary to check if event is triggered by received data:

Private Sub MSComm1_OnComm()
    If MSComm1.CommEvent = comEvReceive Then
        ' Do whatever you need
    End If
End Sub


Step2: If you don't disable event generation on data receiving, received byte(s) can break your already running flow, and if it happens before you flush the reading buffer, breaking events may flush them and you may get mis-ordered data. Altough its low probability, never forget that CPU can do millions of operations in a second and one in a million chance may hit in every seconds. So, disable event generation. For MSComm object, just assign a zero to receive threshold:

MSComm1.RThreshold = 0

Step3: Modern computers are faster than serial communication speeds. Taking a little breath in codes is adviced if you are using MSComm. There is a little bug I have noticed, if you poll MSComm objects buffer so frequently, it may not have a chance to flush its buffer and you may randomly get same bytes in your data. So, it is better to put some NOP code before reading buffer. There is a sleep API of Windows, however I am not satisfied with this API because I realised that it waits several lines of code after it has called, I know it sounds weird but I guess that sleep API is slowing down the Visual Basic interpreter, not the code interpreted. May be it works in compiled code but I am not happy to use it while debugging my source code. So I have my own subroutine which executes DoEvents in a loop.


Step 4: If your communication speed is so low, you may not receive it completely in a single event handler. If you see that you don't have the terminator character of your data package, you should keep your previously received data in a static variable. Example for MSComm:

Static DummyData As String 

...

DummyData = DummyData & MSComm1.Input


Step 5: If you receive the terminator character, use your data and clear static variable.Assuming that terminator character is carriage return:

If Right(DummyData,1= vbCrLf Then
    ' Data received completely
    ' Do some code to use for received data
  
    DummyData = vbNullString
End If


Step 6: If you don't re-enable the event generation, you can't get more data.

In our next post, we are going to have some practice, we are going to code a sample application in Visual Basic 6.0

How to Code for RS232 in Visual Basic? Part 1 – Serial Communication Basics

. Thursday, August 6, 2009
2 comments

In this post series, I would like to talk about receiving data from serial port. It is one of the FAQ of industrial automation forums, but it is difficult to find a proper code or advice. 


I am not going to talk about in details of a specific communication protocol, it may be a subject for another series of post. 


I only want to describe a sample method, and give an example by Visual Basic 6.0.  As I will talk about the method, you can apply it for .Net languages or any other programming languages such as Delphi.


We can choose a sample problem; I think reading data from a barcode scanner may be a right and simple example.


Now, let’s have a little bit theory about RS232 communications, it is designed to communicate for long distances without using many cables. RS232 defines the electrical signal levels, and those signals may be converted into other defined standards such as RS485 or RS422, so I am going to describe it with logical signal levels. 


Serial communication is just like a dialog between two people. Both of them have ears and mouths to listen and speak.


When Alice talks, Bob hears with his ears.


The RS232 port has a transmitting pin and a receiving pin. If you want to establish a communication between two RS232 devices, you must connect one device’s transmitting pin to other device’s receiving pin. Just as talking and listening. 


There is also one more pin which is used as a voltage reference, it is called ground. So only three cables are enough to make a serial communication. If communication should be done for one way only, two cables are enough, one for data and one for voltage reference.


When sending a byte, transmitting pin sends a single start bit signal to inform that a new byte is coming. 


Data bits sent after start bit, number of data bits can be 7 or 8 and it depends on the settings that you decide for communication.


It has information about number of logic 1 signals, even or odd numbers.


And finally stop bits come; number of stop bits can be 1 or 2. It can be considered as a guard time between data packages.


Most important parameter in serial communications is the baud rate, which is the number of bits per second. If you set your communication parameters as  8 data bits and 1 stop bit, you should use 11 bits for each byte packet (1 start + 8 data + 1 parity + 1 stop) and with the speed of 9600 baud, you can send up to 872 bytes per second.


In serial devices, an IC named UART makes the communication and buffers some amount of data inside. 


In next post, I am planning to tell a pseudo code for receiving data from serial port. 

Followers

Search This Blog

Comments

About Me

My photo
Automation engineer especially working on PC software development. Formerly I was coding on PLC, but now I am using mostly Visual Basic on PC.