The Challenge: Sending Non-Standard Characters to Customer Displays

When developing applications for Point of Sale (POS) hardware, such as the PartnerTech CD7220 Customer Display, you often need to send specific command bytes (hex codes) or special currency symbols (like the British Pound sign £).

If you are using the standard SerialPort.WriteLine() method in VB.Net, you might find that special characters are replaced with question marks (?) or garbled text. This happens because .NET defaults to UTF-8 or ASCII encoding, which translates characters outside the standard 127-character ASCII set into multi-byte sequences or unsupported placeholders.

In this article, we will look at the two best ways to solve this: writing raw hex bytes directly, and configuring the correct encoding on your serial port.

Solution 1: Send Raw Hex Bytes Directly (Recommended)

The most reliable way to send commands or specific character codes (like &HBC for the £ symbol on your display) is to bypass string encoding entirely and write a raw byte array directly to the serial port.

Here is how you can write a helper function to send raw bytes in VB.Net:

Imports System.IO.Ports

Public Sub SendHexToDisplay()
    Dim mySerialPort As New SerialPort("COM3", 9600, Parity.None, 8, StopBits.One)
    
    Try
        mySerialPort.Open()
        
        ' Define your text as a byte array using ASCII for standard text
        Dim line1 As Byte() = System.Text.Encoding.ASCII.GetBytes("Total Price: ")
        
        ' Define your hex code for the GBP symbol (£ is 0xBC / &HBC on the CD7220)
        Dim gbpSymbol As Byte() = {&HBC}
        
        Dim price As Byte() = System.Text.Encoding.ASCII.GetBytes("19.99")
        Dim lineEnding As Byte() = System.Text.Encoding.ASCII.GetBytes(vbCrLf)
        
        ' Write everything sequentially to the port
        mySerialPort.Write(line1, 0, line1.Length)
        mySerialPort.Write(gbpSymbol, 0, gbpSymbol.Length)
        mySerialPort.Write(price, 0, price.Length)
        mySerialPort.Write(lineEnding, 0, lineEnding.Length)
        
    Catch ex As Exception
        MessageBox.Show("Error: " & ex.Message)
    Finally
        If mySerialPort.IsOpen Then
            mySerialPort.Close()
        End If
    End Try
End Sub

Solution 2: Change the Serial Port Encoding

If you prefer to continue writing strings directly using mySerialPort.Write("£"), you must configure the SerialPort.Encoding property to match the character set (Code Page) configured on your customer display.

Most customer displays use an OEM code page like Code Page 850 (Western European) or Code Page 437 (US). If your display uses Code Page 850, where the £ symbol maps to 0xBC, you can initialize your port like this:

Dim mySerialPort As New SerialPort("COM3", 9600, Parity.None, 8, StopBits.One)

' Register the code pages provider if using .NET Core / .NET 5+
' System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance)

' Set the encoding to Code Page 850
mySerialPort.Encoding = System.Text.Encoding.GetEncoding(850)

mySerialPort.Open()
' Now you can send the string directly, and .NET will automatically encode "£" as 0xBC
mySerialPort.WriteLine("Total: £19.99")
mySerialPort.Close()

Bonus: Proper Display Control (Clearing & Formatting)

Instead of sending blank spaces to clear the screen, you can send the official ESC/POS commands supported by the CD7220. According to the manual, the command to clear the screen and home the cursor is CLR (Hex 0x0C).

Here is a clean, robust implementation using these practices:

Public Sub UpdateDisplay(line1Text As String, line2Text As String)
    Dim mySerialPort As New SerialPort("COM3", 9600, Parity.None, 8, StopBits.One)
    mySerialPort.Encoding = System.Text.Encoding.GetEncoding(850) ' Matches display character map
    
    Try
        mySerialPort.Open()
        
        ' Send Clear Screen Command (Hex 0x0C)
        Dim clearCmd As Byte() = {&H0C}
        mySerialPort.Write(clearCmd, 0, clearCmd.Length)
        
        ' Send formatted lines (truncated to 20 characters)
        mySerialPort.WriteLine(line1Text.PadRight(20).Substring(0, 20))
        mySerialPort.WriteLine(line2Text.PadRight(20).Substring(0, 20))
        
    Catch ex As Exception
        ' Handle connection errors
    Finally
        mySerialPort.Close()
    End Try
End Sub

Conclusion

By either switching to byte array writes or setting the correct Code Page encoding on your SerialPort object, you can seamlessly send any hex command or international currency symbol to your hardware peripherals without compatibility issues.