In the figure above, the Internet allows one PC (called a client) to control hardware (like motors and relays) installed on another PC (called a server). In other words, you can remotely control or monitor devices. Since the Internet is just a medium for computers to "talk" to each other, it enables you to perform applications like automating your home (e.g. turn on/off air-conditioning) and data acquisition (e.g. measure temperatures). This tutorial shows you how to get started.
The photos depict what will be used for on/off control
of an LED over the Internet. An 8255 PC interface card
will be installed in the Server PC's ISA bus. The card is
interfaced to eight LEDs (a 9V battery is just shown for
scale) via a 34-pin cable and Terminal Expansion Board (TEB).
The Client PC then connects to the server via the
Internet. Through the client, you can turn on/off the LEDs.
The LEDs could be replaced with motors, relays or other
types of peripherals you'd like to control or monitor.
The 8255 PC interface card could be replaced with other
interface circuitry like a parallel port.
Readers of this tutorial would be motivated by ideas like:
The following links are Boondog tutorials that may be useful if the above is overly assumed:
Simple LEDs are controlled just to illustrate the programming concepts. Other devices like relays, DC and stepper motors and keypads can also be controlled over the Internet. Links to these are given below, in the Final Words section. The rest of the tutorial is presented as follows:
The Winsock component shown in the lower left corner (named tcpClient isn't part of the standard VB toolbox. Rather it is added using the following steps:
Click Project then Components and select Microsoft Winsock Control 6.0. You should be seeing the following screen shot
Clicking OK will then export the Winsock Component to the VB toolbox as shown below. You can click and drag the component into your VB form like any other VB component.
The components and relevant properties are highlighted in the following table:
Component | Property | Value |
Form | Name | frmTCPClient |
BackColor | Yellow | |
Caption | Simple TCP Client | |
Button | Name | cmdSend |
Caption | Send Text | |
Text Box | Name | txtSend |
Text Box | Name | txtOutput |
Winsock | Name | tcpClient |
Protocol | 0 - sckTCPProtocol | |
' FILE: tcpClientDemo.frm ' DATE: 01/15/00 12:45 ' AUTH: P.Oh Boondog Automation ' DESC: A Simple TCP Client ' REFS: Deitel p. 829 Fig. 19.12 Option Explicit Private Sub cmdSend_Click() ' Send data to server Call tcpClient.SendData("Client >>> " & txtSend.Text) txtOutput.Text = txtOutput.Text & _ "Client >>> " & txtSend.Text & vbCrLf & vbCrLf txtOutput.SelStart = Len(txtOutput.Text) txtSend.Text = "" End Sub Private Sub Form_Load() cmdSend.Enabled = False ' Set up local port and wait for connection tcpClient.RemoteHost = InputBox("Enter the remote host IP Address", _ "IP Address", "localhost") If tcpClient.RemoteHost = "" Then tcpClient.RemoteHost = "localhost" End If tcpClient.RemotePort = 5000 ' server port Call tcpClient.Connect ' connect to RemoteHost address End Sub Private Sub Form_Resize() On Error Resume Next Call cmdSend.Move(ScaleWidth - cmdSend.Width, 0) Call txtSend.Move(0, 0, ScaleWidth - cmdSend.Width) Call txtOutput.Move(0, txtSend.Height, ScaleWidth, _ ScaleHeight - txtSend.Height) End Sub Private Sub Form_Terminate() Call tcpClient.Close End Sub Private Sub tcpClient_Close() cmdSend.Enabled = False Call tcpClient.Close ' server closed, client should too txtOutput.Text = txtOutput.Text & "Server closed connection." & vbCrLf txtOutput.SelStart = Len(txtOutput.Text) End Sub Private Sub tcpClient_Connect() ' When connection occurs, display a message cmdSend.Enabled = True txtOutput.Text = "Connected to IP address: " & _ tcpClient.RemoteHostIP & vbCrLf & vbCrLf End Sub Private Sub tcpClient_DataArrival(ByVal bytesTotal As Long) Dim message As String Call tcpClient.GetData(message) ' get data from server txtOutput.Text = txtOutput.Text & message & vbCrLf & vbCrLf txtOutput.SelStart = Len(txtOutput.Text) End Sub Private Sub tcpClient_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) ' If the client fails to connect to server, then this code executes Dim result As Integer result = MsgBox(Source & ": " & Description & vbCrLf & "Doh! Can't connect to server!", _ vbOKOnly, "TCP/IP Error") ' Source variable is the control (winsock in this case) causing the error ' Description variable cites the error message ' vbOKOnly is the control button ' TCP/IP Error is the MsgBox caption End End Sub
When tcpClientDemo.exe first executes, Form_Load is launched; an input box prompts the user to enter the server's IP address. By default it uses localhost which will be explained later. Next, tcpClient.RemotePort uses the value 5000 and is called a port number. This number can range from 1024 to 65535 (typically port numbers less than 1024 are reserved for system services). However, the port numbers of the client and server must match. The corresponding server code will also use 5000 as you'll see later. Clicking OK after entering an IP address will attempt a client-server connection by calling tcpClient_Connect() which then enables the Send Text command button.
If the connection succeeds, the user can then type a message in the txtSend text box. Clicking the Send Text, command button, will then execute the procedure cmdSend_Click() which calls tcpClient_SendData.
tcpClient_SendData sends the string Client >>> " plus whatever message you typed in the txtSend text box. It also prints whatever you typed into the txtOutput text box, along with some carriage returns and line feeds (vbCrLf).
Any messages sent from the server are handled by the tcpClient_DataArrival() procedure. GetData is a property of the Winsock control. Recall that you named this control tcpClient in your VB form. As such tcpClient.GetData collects any text messages sent from the server into the string variable message. The string is then printed in the txtOutput text box.
Killing the program will execute the tcpClient_Close() procedure. It greys out the Send Data button, shuts down the client and prints out the message Server closed connection. Form_Terminate also closes the client's Winsock control using a tcpClient.Close call.
tcpClient_Error() handles any errors. A common error might be a mistyped IP address. Form_Resize handles any attempts to resize the GUI.
The components and relevant properties are highlighted in the following table:
Component | Property | Value |
Form | Name | frmTCPServer |
BackColor | Blue | |
Caption | Simple TCP Server | |
Button | Name | cmdSend |
Caption | Send Text | |
Text Box | Name | txtSend |
Text Box | Name | txtOutput |
Winsock | Name | tcpClient |
Protocol | 0 - sckTCPProtocol | |
' FILE: tcpServer ' DATE: 01/15/00 12:30 ' AUTH: P.Oh (Boondog Automation) ' DESC: A Simple TCP Server ' REFS: Deitel p. 826 Fig. 19.10 Option Explicit Private Sub cmdSend_Click() ' Send following text data to the client Call tcpServer.SendData("Server >>> " & txtSend.Text) ' Repeat text data in server's txtOutput.Text window txtOutput.Text = txtOutput.Text & "Server >>>" & txtSend.Text & _ vbCrLf & vbCrLf ' Clear the txtSend.Text window" txtSend.Text = "" txtOutput.SelStart = Len(txtOutput.Text) End Sub Private Sub Form_Load() cmdSend.Enabled = False ' Set up local port and wait for connection tcpServer.LocalPort = 5000 Call tcpServer.Listen End Sub Private Sub Form_Resize() On Error Resume Next Call cmdSend.Move(ScaleWidth - cmdSend.Width, 0) Call txtSend.Move(0, 0, ScaleWidth - cmdSend.Width) Call txtOutput.Move(0, txtSend.Height, ScaleWidth, _ ScaleHeight - txtSend.Height) End Sub Private Sub Form_Terminate() Call tcpServer.Close End Sub Private Sub tcpServer_Close() cmdSend.Enabled = False Call tcpServer.Close ' client closed, server should too txtOutput.Text = txtOutput.Text & "Client closed connection." & vbCrLf & vbCrLf txtOutput.SelStart = Len(txtOutput.Text) Call tcpServer.Listen ' listen for next connection End Sub Private Sub tcpServer_ConnectionRequest(ByVal requestID As Long) ' Ensure that tcpServer is closed ' before accepting a new connection If tcpServer.State <> sckClosed Then Call tcpServer.Close End If cmdSend.Enabled = True Call tcpServer.Accept(requestID) ' accept connection ' Display following message on server application: txtOutput.Text = "The connection from IP Address: " & _ tcpServer.RemoteHostIP & " is successful" & vbCrLf & _ "Port #: " & tcpServer.RemotePort & vbCrLf & vbCrLf End Sub Private Sub tcpServer_DataArrival(ByVal bytesTotal As Long) Dim message As String Call tcpServer.GetData(message) ' get data from client txtOutput.Text = txtOutput.Text & message & vbCrLf & vbCrLf txtOutput.SelStart = Len(txtOutput.Text) End Sub Private Sub tcpServer_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) Dim result As Integer result = MsgBox(Source & ": " & Description, _ vbOKOnly, "TCP/IP Error") End End Sub
Messages from the client are handled by tcpServer_DataArrival and are displayed in the txtOutput text box. If someone on the server types a message in the txtSend text box and hits the Send Text command button, then the subroutine cmdSend_Click() is executed. Here, the typed message is appended to Server >>> and is also displayed in the txtOutput text box. Error handling and form resizing are handled in the same way as described in the Client Program.
where 216.178.66.74 is the server's IP address. Of course your PC will have different numbers separated by three decimal points. If your server PC is running WinNT, then type ipconfig in a DOS prompt for getting the IP address.
On another Internet-connected PC running tcpClientDemo.exe will prompt a pop-up input box where you can type the server's IP address as shown below. Although the address 216.178.67.154 is shown in the figure, you should type the IP address you found using winipcfg.
Once you click OK, you can chat by typing messages and click Send Text on the Server or Client. If you don't have two PC's available, you can run both programs on the same PC. If you do you'll get a screen shot shown below. You'll observe that messages you type are exchanged between client and server.
The photo above shows the 8255 PC Interface Card installed in the server PC. This card has 24 digital I/O lines (three 8-bit ports).
The photo above features the LED circuit. It is connected to the 8255 with a 34-pin cable tethered to a Terminal Expansion Board (TEB). The LED circuit has eight LEDs which will be turned on/off from the client via the Internet.
Turning on/off LEDs with the 8255 card is rather simple. You just need to set the 8255's control word for output and then issue 8-bit data (in decimal) to turn on/off LEDs. The hyperlink above gives a full tutorial on building your own 8255 card and programming it to turn on/off LEDs and reading switches. Programming the 8255 in Visual Basic requires a DLL (dynamically linked library) to mimic Quick Basic's (DOS) OUT and IN or Turbo C's outportb() and inportb() functions. The hyperlink gives a full tutorial on writing DLL's. The compiled version, 8255.dll can be freely downloaded if you rather not write your own DLL.
A screen shot of the LED control program running on the client PC called ledClient.exe is shown above. You can download ledClient.exe or the VB source: frmLEDClient.frm, ledClient.vbp and ledClient.vbw if you wish.
Rather than show the VB code explicitly, view frmLEDClient.frm. It resembles the Client Chat program tcpClientDemo.exe. The key changes made are (1) the Send Text command button is replaced with eight command buttons. Each button represents the decimal number to light up the LEDs in binary (2) the txtSend text box has been removed.
Clicking a button in tcpClientDemo.exe will issue an ASCII string to the server. For example, the subroutine associated with clicking the 6 button is:
Private Sub cmdSix_Click() ' Send six to server Call tcpClient.SendData("6") txtOutput.Text = txtOutput.Text & _ "Client clicked 6" & vbCrLf txtOutput.SelStart = Len(txtOutput.Text) End Sub
As you can see, tcpClient.SendData issues the ASCII character 6. The txtOutput text box prints Client clicked 6 and then a carriage return and linefeed. Subroutines for the other seven command buttons are very similiar.
A screen shot of the LED control program running on the server PC called ledServer2_0.exe is shown above. You can download ledServer2_0.exe or the VB source: frmLEDServer2_0.frm, ledServer2_0.vbp and ledServer2_0.vbw if you wish.
The 8255 PC Interface card is installed in the Server PC's ISA bus. The 8255 is a common digital I/O card. If you aren't familiar with it, read the 8255 Tutorial which gives complete information on building your own 8255 Card.
Recall that VB doesn't provide input/output functions like the DOS QBasic's IN and OUT or Turbo C's inportb() and outportb. However using a DLL, one can perform read/write to an address. The complete tutorial on DLL's should be read if you don't know how to implement DLLs for such purposes.
The complete code for frmLEDServer2_0.frm is not listed here, but can be viewed and downloaded. The key points are described as follows.
First, in the form's General Declarations are the lines
Private Declare Function Out8255 Lib "8255.dll" (ByVal PortAddress As Integer,_ ByVal PortData As Integer) As Integer Private Declare Function In8255 Lib "8255.dll" (ByVal PortAddress As Integer)_ As Integer
which load the DLL for reading (In8255()) and writing (Out8255()) to addresses in VB.
Form_Load, in addition to setting up the server PC's localhost, also assigns the 8255's base address (608 in this case) and the addresses for Ports A, B, C and Control Word (Cntrl). The 8255 is configured for digital output on all three ports. The LEDs are interfaced on Port A.
The rest of the ledServer2_0.exe looks and operates like tcpServerDemo.exe. The server PC waits for connection requests from the client. Once a connection is established, it awaits for messages from the client. Recall that ledClient.exe described above, you clicked on 6 to light up 6 in binary on the LEDs. tcpServer_DataArrival handles string messages. The string "6", sent by the client, is converted into a numerical value using
numericValue = Val(messageFromClient)
Next, this numeric value is written to the 8255 using
Dummy = Out8255(PortA, numericValue)
The net result is that 6 lights up (in binary) the LEDs and status text messages are displayed in the client and server's txtOutput text boxes
mpegLedClientServer.mpg (352KB) is an MPEG showing the client controlling the LEDs. The client and server PC's happen to be in the same room, but they are each connected to the Internet on a ethernet hub.
I'm a robotics/mechatronics professor at Drexel University (Philadelphia USA) in the Mechanical Engineering Deparment. Along with my research I developed a GUI-Based Control course. A complete 10 week (30 hours) notes and syllabi are freely available to view. Teaching notes are available to other educators. If interested, please email me. My students applied the tutorial's concepts to control relays, motors, keypads and digital-to-analog converters. Links are available from the above course's web page. Their successes can be mimicked using their comprehensive tutorials and code. If you find them useful, please email and let me know!
Future potential work derived from this tutorial includes using a web server to display data acquired from sensors interfaced to the server PC. Clients would be thus able to monitor data remotely over the Internet. Webcams can also be attached to the server so that Clients can get visual feedback on whether the remote server indeed actuate your peripheral. Some of these concepts are cited in the Course's web page. In the big picture, the building blocks for controlling and monitor hardware over the Internet can be used for home or industrial automation, robotics and data acquisition. In turning on/off an LED you really can light up the world!
Click here to email me