Wednesday, April 23, 2008

Using PC Serial Port

Controlling and using PC serial port using Visual Basic programming is discussed. Many computers have a serial port. If your computer does not have one, you can buy a USB to RS232 converter.

There are three topics to be discussed here.
1. Using VB6
2. Using VB2005 (VB.NET2)
3. Serial Port as IO

Using VB6

MSComm ActiveX contorl can be used in VB6 to communicate through a serial port. Create a New project by selecting Standard Exe. Go to Project Menu and select Components command. Add Microsoft Comm Control 6.0 from Components dialog.

After OK has clicked, there will be MSComm control with a telephone icon in the Toolbox. Double click on this control to add it onto the Form. Its name will be "MSComm1" as shown below and you can change its settings in the Properties box near the bottom right corner.

In this example, its settings will not be changed in its properties box. But they will be changed in "Form_Load()" event. Double click on any blank space on the form to write in Form_Load() event as shown in the following code.

Private Sub Form_Load()
MSComm1.Settings = "9600,N,8,1"
MSComm1.RThreshold = 1
MSComm1.CommPort = 1
MSComm1.PortOpen = True
Text1.Text = ""
End Sub

The setting "9600,N,8,1" means that we will use Baud rate 9600, No parity, 8 data bit and 1 stop bit. RThreshold defines number of bytes in receive buffer to trigger receive event. In this example, Receive Event will be triggered even if there is only one byte in receive buffer. Comm port 1 of PC is used and opened here. A textbox is used to display the receive data. Another textbox and a Command button are added to the form to send data. Caption property of the Command button is changed to 'Send'.

Double click on that button and write the following code in its click event function.

Private Sub Command1_Click()
MSComm1.Output = "ABCD"
End Sub

Everytime the button is clicked, the data "ABCD" will be sent from the serial port. You can replace ABCD with any data you want to send. To receive data, OnComm event of MSComm control is used. Double click on MSComm control and write the following code in its event function. If OnComm Event is a data received event -comEvReceive, the Textbox will be updated with received data.

Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = comEvReceive Then
  Text1.Text = Text1.Text & MSComm1.Input
End If
End Sub

After that, program will be as shown in the following figure.

Try to run the program. Data will be sent when the Send button is clicked.

Using VB2005

In VB2005, using Serial port is easier because SerialPort control is already in the toolbox. Create a Windows Application from File Menu -> New Project command. Double click on SerialPort Control in the Toolbox to add it onto the form.

Select the control and change its properties in the properties box. In the example, Name will be SerialPort1, BaudRates will be 9600, Databits will be 8, Parity will be None and StopBits will be One. ReceivedBytesThreshold defines number of bytes in receive buffer to trigger receive event. In this example, Receive Event will be triggered even if there is only one byte in receive buffer. Therefore ReceivedBytesThreshold will be 1. Comm port 1 of PC is used and PortName will be set to COM1.

Double click on the Form and write the following code in the Form Load Event.

CheckForIllegalCrossThreadCalls = False

By doing so, the comm port will be opened at the program start. Normal Encoding of serial port control is ASCII. You can also change Encoding at the Form Load Event as follow.

SerialPort1.Encoding = System.Text.Encoding.Default

Add a Button to send data and a TextBox to display received data. Change Text property of the Button to Send. Double click on the Button and write the following code in its click event.


Everytime, the button is clicked, the data "ABCD" will be sent. You can replace ABCD with any data you want to send. To receive data, write the following code in the DataReceived event of SerialPort1.

TextBox1.Text &= SerialPort1.ReadExisting()

If you want to read the received data byte by byte, the following code can also be used.

Dim n As Int32
Dim i As Int32
Dim cmd As String
Dim c As String
n = SerialPort1.BytesToRead
For i = 1 To n
  c = Chr(SerialPort1.ReadChar())
  cmd &= c
TextBox1.Text &= cmd

After that, the program will be as follow.

Then, you can try the program to send and receive data.
Sending Binary Data
The example above is for character data. For binary data whose ASCII code number greater than 127 can be manipulated as follow.

Dim a(3) As Byte
a(0) = &H41
a(1) = &H31
a(2) = &HFF
a(3) = &H80
SerialPort1.Write(a, 0, 4)

ReadChar cannot be used to receive binary data. ReadByte can be used instead as in the following example.

Dim n As Int32
Dim i As Int32
Dim cmd As String = ""
Dim c As String
n = SerialPort1.BytesToRead
For i = 1 To n
c = Chr(SerialPort1.ReadByte())
cmd &= c
TextBox1.Text &= cmd

Getting Port List in Your PC
To list the all ports in your PC in a Combo box and to select the port number that had been saved in user setting, you can used the following code.

Dim ports As String() = SerialPort.GetPortNames()
Dim port As String
For Each port In ports
Next port
Dim index As Integer
index = cmbSerial.FindString(My.Settings.MCOM)
cmbSerial.SelectedIndex = index

Using Serial Port as IO

Besides Tx and Rx to send and receive data, there are two control outputs and four status inputs in a serial. RTS and DTR can be used as outputs. CTS, DSR, CD and RI can be used as inputs. If you don't need a lot of I/O in an application, serial port is a good choice for IO interface.

Related post:

Saturday, April 19, 2008

Asynchronous Serial Communication- RS232, RS422 and RS485

In serial communication, data bytes are sent bit by bit. Its advantage is that data can be sent using only one wire instead of using many parallel wires. But it needs a UART to convert data byte to serial bit stream.
UART not only converts data into serial bit stream, but it also format the bit stream into Asynchronous Serial Communication Protocol by inserting start bit, parity bit, stop bits, etc.

In idle state, a UART normally puts its output in 1. The receiving UART needs to differentiate whether the 1 is data to receive or idle state to ignore. Start bit is used to solve this problem. Normally, a UART ignore 1 as idle. After it received the first 0 as start bit, it accepts the following bits as data for predefined number of bits.

The rate of sending data unit is called Baud rate. For example, if the baud rate is 1 kHz, time period to send each data bit is 1/(1kHz)= 1 ms. A popular baud rate is 9600.

The number of data bits for sending UART and receiving UART must be the same. It can be from 5 bit data to 8 bit data. For example, ASCII data are normally sent with 7 bits. LSB is sent first. A popular number of data bits is 8.

Parity bit is used to check the integrity of the data. In even parity, the number of 1 in data bits and the parity bit itself is even. In odd parity, it is odd. Typically, parity bit is not used.

Stop bit is used to separate the consecutive data bytes. The number of stop bit can be 1,2, etc. 1 is used as a stop bit. Stop bits are sent after sending data bits and parity bits. A popular number of stop bit is 1.
The following example send the data byte 0x41 using 9600, 8N1. That means
Baud rate = 9600
Data bit = 8 bits
Parity = No parity (N= No parity, E= Even parity, O= Odd parity)
Stop bit= 1 stop bit
Since it is no parity, stop bit will come immediately after data bit without any parity bit.

Forms of UART

A UART can be in many different forms. The first one is in the form of a discrete IC. A popular IC is 16550. For CMOS, it will become 16C550, and so on. It has its own buffer and interrupt mechanisms. Therefore, it is easy to use. Serial data comes out from sout pin. Its basic configuration is as shown in the following diagram.

Another form of UART is built-in UART within a microcontroller. The last form of UART is software UART that uses IO pins to emulate it.


A UART uses 5V output to represent 1 and uses 0V output to represent 0. To connect to external devices, these output voltages are normally converted into suitable signaling levels by using a transceiver. A popular signaling standard is RS232. A RS232 transceiver outputs or inputs -10V for 1 and +10V for 0. Valid voltage range is from +/- 3V to +/-25V. A popular transceiver IC is MAX232. Its configuration is shown in the following diagram.

If you want to use smaller capacitor (0.1uF) and smaller IC, you can use MAX202. To use MAX202 with 16C550, connect sout pin of UART which produces 0V and 5V to its pin 11. Then Tx will come out from pin 14 as +10V and -10V. Similarly, +10V and -10V received from Rx line that is connected to pin 13 will come out as 0V and 5V from pin 12 which connects to sin of UART.
The following figure shows typical connection for RS232.

You can use a multimeter to differentiate Tx and Rx of opened RS232 lines. Typically, the voltage between Tx and Ground is -10V and there is no voltage between Rx and Ground. RS232 is said unbalanced lines.

In RS232 communication, besides data transmit line (Tx) and data receive line (Rx), there are also control and status lines for handshaking. Among Primary Communication lines, Tx and RTS are outputs and Rx and CTS are inputs. Among Status and Control lines, DTR is output while DSR and CD are inputs. They will be discussed further. When we talk about RS232 devices, DTE ( Data Terminal Equipment) refers to computer and DCE (Data Circuit-Terminating Equipment) refers to Modem or device.
RTS- Request To Send signal is requested by DTE to DCE. It is normally logic 1 (negative voltage) and when requested it becomes logic 0 (positive voltage).
CTS- Clear To Send signal is used by DCE to infrom DTE that it is ready to receive. It is normally logic 1 (negative voltage) and it becomes logic 0 (positive voltage) when asserted.
DSR- DCE Ready (Data Set Ready) is used by DCE (device) to inform DTE that it has turned on and is ready. It is normally logic 1 (negative voltage) and it becomes logic 0 (positive voltage) when asserted.
DTR- DTE Ready is asserted by DTE to inform DCE that it want to communicate. It is normally logic 1 (negative voltage) and it becomes logic 0 (positive voltage) when asserted.
CD- Carrier Detect (Received Line Signal Detector) is used when DCE is a modem. When this modem receives the answer tone of a modem at the other side of the telephone line, it asserts the computer with logic 0.
RI- Ring Indicator is asserted when a modem receives ring signal. It outputs logic 0 to the computer. It is positive only when there is ring signal. It is negative between ring signals and when there is no ring signal.
Let us continue to discuss about RS232 wire connectors.

As shown in the following figure, a computer (DTE) has Male DB9 connector for RS232 and a device (DCE) has Female DB9 connector. Pin connection for a male connector is shown.

pin 1 = CD- Carrier Detect (input)
pin 2 = Rx- Receive Data (input)
pin 3 = Tx- Transmit Data (output)
pin 4 = DTR- Data Terminal Ready (output)
pin 5 = GND- System Ground
pin 6 = DSR- Data Set Ready (input)
pin 7 = RTS- Request To Send (output)
pin 8 = CTS- Clear To Send (input)
pin 9 = RI - Ring Indicator (input)

Pin connection of a female connector is also shown below.

pin 1 = CD- Carrier Detect (output)
pin 2 = Tx- Transmit Data (output)
pin 3 = Rx- Receive Data (input)
pin 4 = DTR- Data Terminal Ready (input)
pin 5 = GND- System Ground
pin 6 = DSR- Data Set Ready (output)
pin 7 = CTS- Clear To Send (input)
pin 8 = RTS- Request To Send (output)
pin 9 = RI - Ring Indicator (output

RS422 and RS485

RS422 and RS485 function using the difference voltage between two wires. Transmit voltage is between +12V and -12V and they can receive even if the voltage difference is about 0.4V. The voltage between +Tx and -Tx is output voltage and the voltage between +Rx and -Rx is input voltage. They are called balance line because they don't use the voltage between ground and transmit line. They have more resistance to common mode noise. Therefore, they can communicate faster and can communicate over longer distance.

-200mV to +200mV = 0.4 V
-6V to +6V = 12V
Both RS232 and RS422 can have many receivers on a single bus line but they can have only one transmitter on a bus line. In RS485, transmit driver circuit can be enabled and disabled by using data enable line. As a result, it can have many receivers and transmitters on a bus line. Normally, RS422 uses two wires (+Tx, -Tx) for transmitting and another two wires (+Rx, -Rx) for receiving. Therefore, RS422 uses total of four wires. RS485 can communicate using only two wires for both transmitting and receiving in half duplex mode. RS485 can also be used in Full duplex mode using four wires. The following figure shows a typical connection for RS485 using MAX481 transceiver IC. It has only two wires to use in half duplex mode.

An example using MAX491 to connect RS485 in full duplex mode is shown below. If you connect +Tx and +Rx and at the same time -Tx and -Rx, it can be used in half duplex mode.

Actually, full duplex RS485 with four wires whose transmit driver circuit always enabled is same as RS422. RS422 is normally used to extend distance of RS232 communication. When the distance is too far to use RS232, RS422 converter can be used in transmitting side and receiving side can convert the signal back to RS232.
In case, you want to use RS422/RS485 input device with RS232 output device without converter, you can directly connect RS232 Tx output to RS422/RS485 -Rx and RS232 GND to +Rx line. I tried it once before and it was OK. RS422, RS485 half duplex and RS485 full duplex connections are shown below. The first one is RS422 which can be used for only one to one connection. There can be many receivers, but there can only be one transmitter in a bus line. We cannot control transmit driver.

Note that RS485 half duplex has driver enable and receiver enable. Typically, there can be up to 32 node in a bus line.

RS485 full duplex.

Thursday, April 10, 2008

Reverse Macro Ring

Macro lens for close up photos are expensive for me. There are some cheap converter lens, but I don't like to use them after trying a few shots. Later, I found a link about home-made reverse ring here. The followings are about my home made reverse ring. I didn't have an old filter. Therefore, I bought the cheapest body cover ( 5 SGD) and filter (10 SGD).
Then, I made a hole in the Body Cap. Filter was a new one and it was OK to leave as it was. But I thought it was better to remove the glass and I broke it using a hammer. To prevent the scattering of glass debris, you should pack it with a paper or a plastic or stick it with a piece of tape before you break it.

After putting them together, it became as shown. Take care, to put the thread outside. They must be glued at the sides that has no thread.

Lens can be fastened in reverse now. The smaller the mm, the bigger the magnification. You can push the aperture lever to get a bigger aperture. I think 50 mm prime lens may be the best to use with reverse ring.

Here are a few shots I tried with this reverse ring.

Tuesday, April 8, 2008

Parallel Port as IO

Parallel Port can be used to control some digital devices and sometimes, it can also be used as IO for simple projects. I even found some systems that uses parallel port of an Industry PC to control LCD module. In fact, a Parallel Port has a lot of I/O and they can be used together with Relays and Transistors to control motors and light bulbs, etc. Last time, I helped one of my friends to controls 24 running light bulbs using a parallel port and Solid State Relays. A Parallel Port can have maximum of 12 outputs ( 8 data lines and 4 control lines). But you can demultiplex them according to your needs. It has 5 Inputs lines. If you can also use 8 Data lines as inputs (in later parallel port), there can be up to 13 inputs. Parallel Port has 5 Modes and you can see more details at here. A PC normally has a Parallel Port. If you don't have one, you can easily buy an IO card with a parallel port.


The following figure shows a Female 25 DB connector of a PC.
Wire lines in a parallel port can be differentiated into three groups.
1. Data lines
2. Control lines
3. Status lines
They are controlled by their corresponding registers.
Control lines can be used as outputs and Status lines can be used as inputs. Data lines can be used as inputs and outputs. If you want to use data lines as inputs, you need to enable Bidirectional data transfer first. Set bit 5 -"Bidirectional" bit of the control register to enable it. See the following table for definition of each pin.

|Pin No |Signal Name |Direction |Register -bit |Inverted |
| 1.... | nStrobe....| Out......| Control-0....| Yes ....|
| 2.... | Data0......| In/Out...| Data-0.......| No......|
| 3.... | Data1......| In/Out...| Data-1.......| No......|
| 4.... | Data2......| In/Out...| Data-2.......| No......|
| 5.... | Data3......| In/Out...| Data-3.......| No......|
| 6.... | Data4......| In/Out...| Data-4.......| No......|
| 7.... | Data5......| In/Out...| Data-5.......| No......|
| 8.... | Data6......| In/Out...| Data-6.......| No......|
| 9.... | Data7......| In/Out...| Data-7.......| No......|
| 10... | nAck.......| In.......| Status-6.....| No......|
| 11... | Busy.......| In.......| Status-7.....| Yes.....|
| 12... | Paper-Out..| In.......| Status-5.....| No......|
| 13... | Select.....| In.......| Status-4.....| No......|
| 14... | Linefeed...| Out......| Control-1....| Yes.....|
| 15... | nError.....| In.......| Status-3.....| No......|
| 16... | nInitialize| Out......| Control-2....| No......|
| 17... | nSelect-Printer| Out..| Control-3....| Yes.....|
| 18-25 | Ground.....|-.........| - ...........| - ......|

IBM PC has defined IO addresses for data register, control register and status register. The following table lists their IO addresses.

| Register........| LPT1 | LPT2 |
| Data Register...| 0x378| 0x278|
| Status Register.| 0x379| 0x279| (baseaddress + 1)
| Control Register| 0x37A| 0x27A| (baseaddress + 2)
For example, if you write 0x00 at IO address 0x378, data register of LPT1 will be 0x00 and the pin number 2 to 9 of DB25 connector that is connected to the data register will output 0V. Similarly, if you write 0xFF to IO address 0x378, bit 0 to bit 7 of data register will become 1 and pin 2 to pin 9 will output +5V.
Pin 1, 14, 16, and 17 are connected to control register at IO address 0x37A. But pin 1, 14, 17 are inverted outputs and pin 16 is non-inverted outputs. For an inverted outputs, it will output +5V if you write 0 and it will output 0V if you write 1 to the corresponding bit.
Status register at IO address 0x379 is input and you can read the status of pin 10, 11, 12, 13 and 15. Pin 11 is inverted input and the rest are non-inverted inputs. For a non-inverted input, +5V at input pin will appear as 1 and 0V will appear as 0 in the status register.

Circuit Connection

A cable with a Male 25DB connector can be used to connect the PC with a parallel port and the other side of the cable can be used to connect inputs and outputs.
As an example, data pin 2 to 9 and control pin 1,14, 16, 17 will be used as outputs and status pin 10, 11, 12, 13 and 15 will be used as inputs. Therefore, outputs will connect to LEDs and inputs will connect to switches as shown in the following figure.
In the following figure, data pins are used as both inputs and outputs. For simplicity, they will be used as outputs only in our example.
You can use a multimeter to measure which pin connects to which wire. In some cables, all wires have same color. But for my cable, I found them as
1. Black
2. Black/white
3. Brown
4. Brown/white
5. Red
6. Red/white
7. Red/black
8. Orange
9. Orange/white
10. Orange/black
11. Pink
12. Pink/black
13. Yellow
14. Yellow/black
15. Green
16. Green/white
17. Green/black
18. Light Green
19. Blue
20. Blue/white
21. Magenta
22. Magenta/white
23. Grey
24. Grey/black
25. White
If you have set up LEDs and switches as above, you need to write a program to control them.


In Windows 98 and Windows Me, we can control the port directly using C program functions such as "InportB" and "OutportB" in Turbo C and Borland C, and "_inp" and "_outp" of VC++. They are defined in "conio.h". But for Windows NT/2000/XP, we cannot control directly and we need to use a library file such as "inpout32.dll". You can get it from And put the "inpout32.dll" file in "C:/windows/system32/" folder. This example is demonstrated for Windows XP using Visual Basic 2005. But it is essentially the same for Visual Basic 6 also.
At first, create a new project in VB2005 by clicking File Menu ->New Project... . Choose Windows Application and click OK. Then add a module by clicking Tools bar -> Add New Item -> Add Module ... . Declare the following two lines of code in that module.

'Inp and Out declarations for port I/O using inpout32.dll.
Public Declare Function Inp Lib "inpout32.dll" Alias "Inp32" (ByVal PortAddress As Short) As Short
Public Declare Sub Out Lib "inpout32.dll" Alias "Out32" (ByVal PortAddress As Short, ByVal Value As Short)
As in the following figure.
Add two buttons and two text boxes on the form.
To output the hexadecimal value in the text box to data pins when the first button is clicked, write the following code.

Out(&H378, Val("&H" & txtData.Text))
The first argument of the Out function is IO address. It uses IO address 0x378 to write to data register. The second argument is the value to write. To read the text box input as hexadecimal value, "&H" is appended in front of it.
When you click the second button, the value of the status pins will be read and displayed in the text box beside it. To read the status register at IO address 0x379, write the following code.

txtStatus.Text = Hex(Inp(&H379))

The argument of Inp function is the IO address to read. The read value is converted to hexa string using Hex function and is displayed in the text box.


Sunday, April 6, 2008


In an HDR (High Dynamic Range) photo, some parts of the photo are too bright and some parts are too dark so that all of them cannot be captured by a camera in a single exposure or cannot be displayed on a screen. In the following picture, the side of the lamp is too bright and the side of the lacquered box is too dark.

If you increase the exposure, the lacquered box side will be OK. But the lamp side will be too bright.
If you decrease the exposure, the lamp side will be just nice and the lacquered box side will be too dark to see properly.

We will use exposure bracketing to solve this problem. Take three exposures, one with normal exposure, another with +2 EV overexposed and the last one with -2EV underexposed. It is better to use a tripod and manual focus mode. Use fixed aperture to get same Depth of Field. After that, you need to put Exposure Blending Plug-in for GIMP.
You can download the plug-in from For GIMP 2.4.5, you need to put the file into C:\Program Files\GIMP-2.0\share\gimp\2.0\scripts. It can be vary according to your installed location. Then, open GIMP and click Xtns menu -> Photo -> Exposure Blend ... .
Insert the three pictures there.
You can use your preferred settings.Click OK. After that you will get an Exposure Blended picture.
If your pictures are not exactly the same, there is an auto align feature in some software such as Photoshop, PhotoMatix, etc. However, you need to align manually in GIMP. Go to Filters menu -> Photo -> Align Exposure Mode and you can adjust the layers using difference mode.
You can also go to layer windows and adjust opacity, layer mask and many others fine tunings of dark layer and bright layer.