RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Discover a New Frontier for .NET Development: Program an LCD Display : Page 2

Personal computers aren't the only place where applications can run. As we look toward the future, the possibilities are limitless for creating applications that manipulate other types of displays. Get started with this sample .NET application that controls an LCD display.

Testing the Connections
If you did your connections correctly, you can now power up the LCD display. When connected properly, the screen should look as shown in Figure 7.

Programming the LCD
The 4x20 Serial LCD (LK204-25) display is a text-only LCD. However, its built-in character font (ASCII) includes some extended characters (see Figure 8) as well.

Figure 7. The LCD displays this opening screen, when powered up correctly.
Figure 8. The character set of the LK204-25 LCD display is shown. You can use it to expedite commands in your application.

In addition, you can define up to eight custom characters. This is useful for defining your own logo, or smileys. It also supports drawing of vertical and horizontal bar graphs.

Programming the LK204-25 is straightforward. The following sections summarize the things you need to know to program the LK204-25 using the SerialPort class in .NET 2.0.

Issuing Commands
To issue commands to the LCD, such as clearing the screen, send a byte array containing the following: 254, [command]. For example, to clear the screen, the command is 254, 88.

In .NET, you can send the command to the LCD by setting a byte array to:

_data = New Byte() {254, 88}
serialPort.Write(_data, 0, _data.Length)
The number 254 and 88 are expressed in decimal. Alternatively, you can also express them in hexadecimal:

_data = New Byte() {&HFE, &H58}
serialPort.Write(_data, 0, _data.Length)
You can also express the command using its corresponding ASCII character, in this case 'X':

_data = New Byte() {254, Asc("X")}
serialPort.Write(_data, 0, _data.Length)
Notice how the character X corresponds to column 5 and row 8 in Figure 8. (Note: The list of commands for the 4x20 Serial LCD can be found at http://www.parallax.com/dl/docs/prod/audiovis/LK204-25-2.x.pdf .)

Displaying Text
To send a string to the display, simply write the string directly to the SerialPort object:

Displaying Special Characters
To print out a particular character in the character set (this is especially useful for special characters), use the following format:

_data = New Byte() {&HEF}
serialPort.Write(_data, 0, _data.Length)
where EF is the character in column E and row F of the character table.

One noteworthy point is that the characters displayed by my LCD do not match those listed in Figure 8, possibly because some characters were changed in the ROM. Hence, it would be best if you print out the character set of your LCD. You can do so by using the following code snippet:

        Dim num As Integer = &H0 '---start from 0
        For i As Integer = 0 To 255
            _data = New Byte() {num}
            serialPort.Write(num & " - ")
            serialPort.Write(_data, 0, _data.Length)
            num += 1
Defining Your Own Characters
For the LK204-25, you can define up to eight custom characters. Each character is made up of eight bytes. To help you create your own custom character, you can download the LCD Character Creator utility from Parallax. As shown in Figure 9, each character is made up of 40 pixels in a five column by eight row configuration. Each pixel has a binary value of either 1 for shaded or 0 for unshaded.

Figure 9. Here I've created a smiley face using the LCD Character Creator utility.
The hexadecimal number on each line corresponds to the value of each line. To programmatically define the character, simply set the 8-byte arrays as shown below:

        Dim ch as Integer = 0
        Dim bytes(7) As Byte
        bytes(0) = &H0
        bytes(1) = &HA
        bytes(2) = &HA
        bytes(3) = &H0
        bytes(4) = &H11
        bytes(5) = &HE
        bytes(6) = &H6
        bytes(7) = &H0
        _data = New Byte() {254, 78, _
                ch, bytes(0), bytes(1), bytes(2), _
                bytes(3), bytes(4), bytes(5), _
                bytes(6), bytes(7)}
        serialPort.Write(_data, 0, _data.Length)
Creating Your Application
Now that you have the basic workings of the LK204-25, you can proceed to create a useful application to make use of its display capabilities. The sample application for this article has the following capabilities (see Figure 10):
  • Display the CPU usage
  • Display the current time
  • Display RSS feeds
Figure 10. The three functions of the sample application are shown.

Packaging the LCD Functionalities into a Class Library
Before writing the sample application, I want to package all the core functionalities of the LCD display into a class library. Thus, if you have the LK204-25 serial LCD, you can simply program it by calling the relevant methods exposed by the class library.

Using Visual Studio 2005, create a new Windows application and name it C:\LCD. Add a new class to the project and name it as LCD.vb.

First, define the following enumerated types:

'---used for defining custom characters---
Public Enum CustomChar
    ch0 = 0
    ch1 = 1
    ch2 = 2
    ch3 = 3
    ch4 = 4
    ch5 = 5
    ch6 = 6
    ch7 = 7
End Enum

'---used for setting the direction of horizontal bar graph---
Public Enum Direction
    left = 1
    right = 0
End Enum
Declare the following constant, member variables and events within the LCD class:

Public Class LCD
    '---define the width of the bar graph---
    Const BARGRAPH_WIDTH As Integer = 20
    '---store the values of the bar graph---
    Private _values(BARGRAPH_WIDTH) As Integer
    '---keep track of the current index of the bar graph---
    Private _index As Integer = 0

    '---data received from the LCD---
    Public Event DataFromLCD(ByVal str As String)

    '----create the serial port---
    Private WithEvents serialPort As New IO.Ports.SerialPort

    '---data to send to the LCD---
    Private _data() As Byte

    '---parameters used by the other functions---
    Private _col, _row As Integer
    Private _c As Integer ' 0 to 7
    Private _cBytes() As Byte
    Private _lengthofVBar As Short
    Private _lengthofHBar As Short
    Private _d As Short = 0        '---0 is right 1 is left
    Private _digit As Short        '---0 to 9
    Private _minutes As Integer    '---0 or a number
    Private _contrast As Integer   '---0 to 255
In the constructor of the LCD class, initialize the array used for storing the values in a bar graph:

    '---initialize the bar graph---
    Public Sub New()
        For i As Integer = 0 To BARGRAPH_WIDTH - 1
            _values(i) = 0
    End Sub
Define the Connect() subroutine to open the serial port that is connected to the LCD display. You must set the BaudRate property to 19200, otherwise you may not be able to communicate with the LK204-25 LCD display.

    '---connect to the LCD using serial port---
    Public Sub Connect(ByVal PortNo As String)
        If serialPort.IsOpen Then
        End If
            With serialPort
                .PortName = PortNo
                .BaudRate = 19200
                .Parity = IO.Ports.Parity.None
                .DataBits = 8
                .StopBits = IO.Ports.StopBits.One
                .Handshake = IO.Ports.Handshake.None
            End With
        Catch ex As Exception
        End Try
    End Sub
The DataReceived event will be fired when incoming data is received from the serial port. It will in turn fire off the DataFromLCD event to notify the calling routine that there is incoming data from the LCD display:

    '---data received from the LCD---
    Private Sub DataReceived( _
       ByVal sender As Object, _
       ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
       Handles serialPort.DataReceived
        Dim str As String = serialPort.ReadExisting
        '---cause the event on the caller to fire---
        RaiseEvent DataFromLCD(str)
    End Sub
The Write() subroutine will send a string to the LCD display via the serial port. It supports delayed sending of data, and hence will send individual characters to the LCD at a delay of 100 milliseconds per character.

    '---display text with optional delay---
    Public Sub Write(ByVal text As String, ByVal delay As Boolean)
        If delay Then
            For i As Integer = 0 To text.Length - 1
        End If
    End Sub
To simplify communicating with the LCD, the Command() subroutine will take in a command identifier and send the appropriate commands to the LCD (see Listing 1).

For example, to clear a screen, you would call Me.Command("X") and the subroutine will do the work of sending the correct command to the LCD display. Notice that this subroutine is only visible within the class, as you do not want the user to directly call the commands.

To make it easier for users to send the appropriate commands to the LCD, define the subroutines in Listing 2 (their use is self explanatory).

Finally, define the DrawBarGraph() subroutine to draw a moving bar graph:

    '---draw a bar graph---
    Public Sub DrawBarGraph(ByVal value As Integer)
        '---assign the value into the array---
        If _index > BARGRAPH_WIDTH Then
            '---shift all the values 1 position up
            For i As Integer = 1 To BARGRAPH_WIDTH - 1
                _values(i) = _values(i + 1)
            _values(BARGRAPH_WIDTH) = value
            _values(_index) = value
        End If
        _index += 1

        '---draw the bars in the graph
        For i As Integer = 1 To BARGRAPH_WIDTH
            Me.DrawVertBarGraph(i, (_values(i) / 100) * 32)
        '---display some text---
        Me.SetCursorPosition(1, 7)
        Me.Write("CPU Usage: " & value.ToString & "%  ", False)
    End Sub
Testing the Library
Now it's time to test the library you just created. Populate the default Form1 with the following controls (see Figure 11):
  • Button controls
  • CheckBox control
  • Label control
  • TrackBar control

Figure 11. Populate Form1 with the controls shown.
In the code-behind of Form1, import the following namespaces:

Imports System.Management
Imports System.Net
Imports System.IO
Imports System.Xml
Imports System.Threading
Declare the following member variables:

Public Class Form1
    '---create an instance of the LCD class---
    Private WithEvents LCD_Display As New LCD
    '---true when form is finished loading---
    Private FormLoaded As Boolean = False
    '---threads for asynchronous execution---
    Private t1, t2, t3 As Thread
When the form is first loaded, open a connection to the serial port connecting to the LCD display:

    Private Sub Form1_Load( _
       ByVal sender As System.Object, _
       ByVal e As System.EventArgs) _
       Handles MyBase.Load
        FormLoaded = True
    End Sub
Here, I am assuming that the COM3 is used to connect your PC to the LCD display.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date