Controlling a Motor With Your Computer Part III The Windows Application Side

This posting may be semi wrongly titled. It refers to a Windows Application as that is what I will detail, but the truth is you can use any application on any OS. If you prefer Linux, I imagine there are many ways to code your applications in this platform. I have only used PC based coded applications, so this is what I know at the moment. Like I explained on the first posting, you can use this technique with any platform that grants access to a serial port. As of today I have successfully used Visual Basic (both VB6 and VBNET), Lab View and C++ Builder. I also assisted a team to use my hardware with their Mat Lab implementation. Again, it is just serial packets!

This is the simplest aspect of the design and you will find this is mostly a copy paste effort. All you need to understand how to do the first one. Everything else will simply follow. Remember what we need to do is fill a five byte packet and then send it through the serial port. I will now teach you how to do this using Visual Studio’s Visual Basic of the 2010 release.

When it comes to building your VB Net application, you will need a few blocks: 

  1. A serial COM Port object
  2. A series of Text Box objects to hold the bytes to be sent
  3. A Button Command object to execute the action of stuffing the five bytes and sending them over the serial port.

 Here is how it looks on my typical startup application place holder:

Typical Windows Application Place Holder

 I have called my COM Port object Comillo (don’t ask me why…) and what it is, is an instance of the class System.IO.Ports.SerialPort. It will have all the properties relevant to a serial COM port such as number of data bits, start bits, stop bits, parity bits, etc, as well as the event handling necessary to the transmission of data.

When it comes to serial ports, there are a few things you need to do. First, you need to find the available COM ports. We do this, with this piece of code which runs during form loading (application startup):

 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim stringarray() As String = IO.Ports.SerialPort.GetPortNames

        Dim ComPortLocation As Integer

        For i = 0 To UBound(stringarray)

            cmbCOMPorts.Items.Add(stringarray(i))

            If stringarray(i) = “COM4” Then

                ComPortLocation = i

            End If

        Next

         cmbCOMPorts.SelectedIndex = ComPortLocation

        InitComplete = True

        CommError = False

 End Sub

Notice we have created an array of strings called stringarray which is meant to hold all the available COM ports on the computer. Each computer is unique, so we can not just assume a given COM Port resource will be available. The IO.Ports.SerialPort.GetPortNames method grabs the available COM Port resources and dumps the result on the array. We can then take this array and extract each element into a Combo Box object I have called cmbCOMPorts.

The idea behind this move is to make all available COM Ports so the user can select the one they want use for communications. Notice I have added some code to select the COM4 as default. This is just a personal decision as I always program all my modules to be COM4. Hence, I do not need to select from within the Combo Box object whenever the application is started.

Once you have selected the COM Port you will use, we must open the resource. Do note that before doing this you may want to configure all parameters such as start bits, stop bits, data bit width, parity and such. Since I always use the same parameters, I have hard coded them into the application. Its up to you whether you want to add this flexibility or not. We are ready to open up that COM Port, and for that I created a simple MENU item called CONNECT. Kind of a DUH!…

Private Sub ConnectToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuConnect.Click

        If mnuConnect.Text = “Connect” Then

            On Error Resume Next

            With Comillo

                .DataBits = 8

                .Parity = IO.Ports.Parity.None

                .StopBits = IO.Ports.StopBits.One

                .BaudRate = 9600

                .PortName = cmbCOMPorts.SelectedItem

                 If Err.Number <> 0 Then

                    MsgBox(“Please Select COM Port from Drop Down List” & vbCrLf & Err.Description)

                    Err.Clear()

                Else

                    Comillo.Open()

                    ‘Dim megatest() As String = Comillo.GetType

                     If Err.Number <> 0 Then

                        MsgBox(“Com” & Comillo.PortName & ” is not available.” & vbCrLf & Err.Description)

                        Err.Clear()

                    Else

                        mnuConnect.Text = “Disconnect”

                    End If

                End If

            End With

        Else

            Comillo.Close()

            mnuConnect.Text = “Connect”

        End If

    End Sub

Do not let this code scare you away. It is really not that complex. As you can see, what I am doing is configuring the Serial Port parameters as I explained before. I extract the actual COM Port name from the Combo Box and then we open the COM Port. There are some error checks to make sure we don’t send too much junk to the Open() method and if everything works OK (e.g. there is such a thing as the COM Port that you have specified), the resource is opened and made available for usage. Notice that when the COM Port is opened successfully, I change the caption of the menu item from “Connect” to “Disconnect”. This way I can use the same menu item for both opening and closing the serial port.

Dudes, we are SET!!! Now all we have to do is put stuff into the serial stream and watch those bits go.

Like I explained before, we have generated a series of place holders for the data to be sent. These are the txtBytex.Text text box objects. Now you may be wondering why actually create an object to hold this data and not just an internal array? When I show you what I do you may even feel compelled to call me Mega Dumb considering the Text Box contents are in fact transferred into an internal array before they are sent through the serial port. Ehh, WHAT???

Believe me, you will feel grateful the very first time you want to troubleshoot the application and see what on Earth you are sending through the serial port. Because it is super easy to assume you are sending the right thing but somehow you forgot to change from decimal to hex, and now nothing works. Thank god for those text boxes!

So here is an example of what I do. Notice the Start Motor button at the top left. Here is its code:

Private Sub cmnStartMotorCommand(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmnStartMotor.Click

        txtByte0.Text = Int2Hex(START_MOTOR)

        txtByte1.Text = Int2Hex(CInt((txtPWMDutyCycle.Text And &HFF00) / 256))

        txtByte2.Text = Int2Hex(CInt(txtPWMDutyCycle.Text And &HFF))

        txtByte3.Text = 0

        txtByte4.Text = 0

        btnSendCommand_Click_1(sender, e)

        If CommError Then

            CommError = False

            Exit Sub

        End If

        Exit Sub

TextBoxEmpty:

        MsgBox(“Text Boxes Can Not Be Empty”, vbOKOnly, “Data Error”)

    End Sub

End Class

When I press the Start Motor button, all I do is stuff the Text Box objects with the data that I want to send but in hexadecimal format. Notice the first byte will be the opcode, and the subsequent bytes are the parameters. Assuming the duty cycle is a 16 bit number, I must segregate it into two 8 bit numbers as shown above. The last two bytes will not be used, so I just put zeroes. Remember, they must still be sent!

Once the Text Box objects have been filled with the values I want to submit, now I call the Send Command Button function, for which we can see the code below:

Private Sub btnSendCommand_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendCommand.Click

        Dim i As Integer

        newMsg(0) = Convert.ToByte(Convert.ToInt32(txtByte0.Text.ToString, 16))

        newMsg(1) = Convert.ToByte(Convert.ToInt32(txtByte1.Text.ToString, 16))

        newMsg(2) = Convert.ToByte(Convert.ToInt32(txtByte2.Text.ToString, 16))

        newMsg(3) = Convert.ToByte(Convert.ToInt32(txtByte3.Text.ToString, 16))

        newMsg(4) = Convert.ToByte(Convert.ToInt32(txtByte4.Text.ToString, 16))

        On Error GoTo ButtonSendErrorHandler

        Comillo.Write(newMsg, 0, 5)

        On Error GoTo ReceiveErrorHandler

        Comillo.Read(buffer, 0, 3)

        Exit Sub

ButtonSendErrorHandler:

        Dim Response As Integer

        Response = MsgBox(“No COM Port Open.”, vbOKOnly, “Connect Error”)

        CommError = True

        Exit Sub

ReceiveErrorHandler:

End Sub

This is the function we will call every time we want to submit data through the serial port. The newMsg() array is filled with the bytes and then the entire array is offered into the Comillo’s Write() method. The five bytes are sent and 3 bytes should be received. If so, these bytes are placed inside Comillo’s read buffer and are extracted by means of its Read() method.

Do note that one of Comillo’s object parameter is the ReadTimeOut which I have configured to be 100 ms. If you make this infinite, the code may hang at this point as it will be forever waiting for bytes to be sent back.

On this application I do nothing with the bytes received from the serial communications but you can use them if you need them to.

And that’s it! You can now generate more commands using different Objects like Sliders, Check Boxes, etc. If there is interest, I can document what is the coding style for these objects. But we must now take a little bit of a look to the hardware, which I bet some people may be interested in studying.

Leave a Reply

Your email address will not be published. Required fields are marked *