Menu

Driving a large VFD serial display.

mkstevo
2021-04-17
2021-04-18
  • mkstevo

    mkstevo - 2021-04-17

    A friend recently upgraded the cash registers in his shop to iPad based ones and had two surplus displays. These were decently sized 2x20 Vacuum Fluorescent Displays (VFD) which appeared to be driven by serial data.

    I was able to take a copy of a demonstration program (for Windows) from the original PC that they connected to and with the help of my super cheap Chinese logic probe was able to determine the data packets sent to the displays. This then greatly assisted me in creating a simple program to drive the displays. I duplicated the sequence of the commands as sent by the demonstration program, and reported by the logic probe. I may be that some of the steps are not required but as I couldn't turn up a datasheet for the display, I simply recreated the sequence of commands sent by the demo program. If they look odd, sorry, I just copied the original.

    The demonstration program can be seen working in a YouTube video. https://youtu.be/hPBVKtx01Us

    The displays originally were powered at (what I thought I measured at) 5V. This needs to be at a minimum of 1A, I found the displays wouldn't power up below around 5.5V, but that could be decoupling issues on my breadboard.

    When powered up with no serial data, the displays announce themselves as:
    CD5220 9600 N-8-1
    U.S.A. /PC437(V1.H)

    This then clears and the displays go blank.

    As soon as serial data is presented, the displays show the supplied data.

    I don't give any warranty regarding the robustness of the program, but it may at least give a start to anyone else trying to use similar displays.

    The displays seem to have a display buffer of 48 bytes (which were sent by the original program each time) the last eight bytes should be null (0x00). The display shows the last 40 characters sent, if there are characters in the last eight bytes, the first eight bytes will be lost.

    'A program to drive a serial Vacuum Fluorescent Display.
    '(c) MkStevo, Mark Stevenson, MkEDS 2021
    '
    'The displays require a 5.5V supply, at a minimum of 1A
    '
    'When powered up the display identified itself as:
    '
    'CD5220 9600 N-8-1
    'U.S.A. /PC437(V1.H)
    '
    'The display has a 2x20 character display.
    '
    'Printing to the display beyond the line length limits causes the text to wrap onto the next line,
    'or back to line 1.
    '
    'There are 20 "Cursors" below line 2 which can individually be turned on or off.
    '
    'The baud rate is 9600, 8bits, 1 stop bit, Inverted polarity. The polarity is inverted with the
    'command:
    'Let SCKP=1
    '
    'Each command to the display seems to be sent as eight bytes.
    'All eight bytes appear to be needed to be sent.
    '
    'The subroutine "SendOctet" has eight parameters, any parameters not passed are sent as
    'zero value bytes. This is how the original program sent the serial data and I simply
    'duplicated the same sequence.
    '
    'To send the command for turning one of the bottom arrow (cursors) on the original serial sequence was:
    '
    '0x1F,0x23,0x01,0x06,0x00,0x00,0x00,0x00
    '            |   |
    'Turn on cursor  |
    'Cursor number six
    '
    'To send the same command, call "SendOctet"
    '
    'SendOctet(0x1F,0x23,0x01,0x06)
    'The trailing four "0x00" bytes are automatically sent, they do not need to be added to the call.
    '
    'The display buffer appears to be 48 bytes long. All 48 bytes were sent by the original program.
    'Again, I have duplicated this sequence.
    '
    'The final eight display bytes should be null (0x00). If they have character values in them, they will be
    'printed, with the first eight bytes truncated.
    '
    'The array "DisplayArray" can be filled with null characters by calling "ClearBuffer"
    '
    'The display can be cleared by calling "ClearDisplay". This also sets the cursor to line 1, character 1.
    '
    'If the buffer has not been cleared, when it is next printed using VFDString, "old" characters not cleared
    'or updated will still remain in the buffer and will be written to the display.
    '
    'Null characters in the display may not be written, merely skipped over.
    '
    'It is possible to move the cursor to a specific position on the display.
    'The position of the top most, left most character is at co-ordinates 1, 1.
    '
    'The position of the right most, bottom most character is 2, 20.
    '
    'Call "SetPosition(2, 10)" to move to the middle of line 2.
    
    
    
    #Chip 12F1840,32
    #Option Explicit
    
    Dim DisplayArray As String * 48
    Dim ArrayPos     As Byte
    Dim DataPos      As Byte
    Let ArrayPos = 1
    Dim CntDown      As Long
    
    #Define StartValue 1000
    
    #Define SerTX   PortA.0  'Pin7
    #Define SerRX   PortA.1  'Pin6
    
    
    Dir     SerTX   Out
    Dir     SerRX   In
    
    #Define USART_BAUD_RATE 9600
    #Define USART_TX_BLOCKING
    #Define USART_DELAY 0
    Let SCKP=1 'Inverted serial
    
    ClearBuffer
    ClearDisplay
    CursorZero
    
    Do
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "  Hello VFD Display         World! "
        VFDString
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = " Thanks Sam for the       Displays "
        VFDString
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "   Hello Great Cow  Basic from MkStevo.."
        VFDString
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "Move to 2,19"
        VFDString
        SetPosition(2,19)
        ClearBuffer
        Wait 750 mS
        Let DisplayArray = "@"
        VFDString
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "                    Move to 1,17"
        VFDString
        SetPosition(1,17)
        ClearBuffer
        Wait 750 mS
        Let DisplayArray = "@"
        VFDString
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "Cursor 7 On"
        VFDString
        Wait 750 mS
        SetBottomArrow(7,1)
        Wait 2000 mS
        CursorZero
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "Cursor 3 On"
        VFDString
        Wait 750 ms
        SetBottomArrow(3,1)
        Wait 2000 mS
        CursorZero
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "Cursor 3 Off"
        VFDString
        Wait 750 mS
        SetBottomArrow(3,0)
        Wait 2000 mS
        CursorZero
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "Cursor 7 Off"
        VFDString
        Wait 750 mS
        SetBottomArrow(7,0)
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    
       Let CntDown = StartValue
    '    Let CntDown = 1000000
    '                       12345678901234567890x2345678901234567890
        Let DisplayArray = "Time to armageddon.."
        VFDString
        Do
            SetPosition(2,1)
            If CntDown < 1000000 Then
                HSerSend(48) '0
            End If
            If CntDown < 100000  Then
                HSerSend(48)
            End If
            If CntDown < 10000   Then
                HSerSend(48)
            End If
            If CntDown < 1000    Then
                HSerSend(48)
            End If
            If CntDown < 100     Then
                HSerSend(48)
            End If
            If CntDown < 10      Then
                HSerSend(48)
            End If
            HSerPrint CntDown
            Let CntDown = CntDown - 1
        Loop Until CntDown > StartValue
        Wait 2000 mS
        ClearBuffer
        ClearDisplay
    Loop
    
    Sub ClearDisplay
        SendOctet(0x0C)
        Repeat 20
            SendOctet(0x1F,0x23,0x00,DataPos)
            Let DataPos = DataPos + 1
        End Repeat
    End Sub
    
    Sub CursorZero
        SendOctet(0x1B,0x6C,0x01,0x01)
        SendOctet(0x18)
        SendOctet(0x1B,0x6C,0x01,0x01)
    End Sub
    
    Sub VFDString
        Let ArrayPos = 1
        Repeat 48
            HSerSend(DisplayArray(ArrayPos))
            Let ArrayPos = ArrayPos + 1
        End Repeat
    End Sub
    
    Sub SendOctet(Optional D1 As Byte = 0, Optional D2 As Byte = 0, Optional D3 As Byte = 0, Optional D4 As Byte = 0, Optional D5 As Byte = 0, Optional D6 As Byte = 0, Optional D7 As Byte = 0, Optional D8 As Byte = 0)
        HSerSend(D1)
        HSerSend(D2)
        HSerSend(D3)
        HSerSend(D4)
        HSerSend(D5)
        HSerSend(D6)
        HSerSend(D7)
        HSerSend(D8)
    End Sub
    
    Sub SetPosition(In LinePos As Byte, In CharPos As Byte)
        If LinePos > 2 Then
            Let LinePos = 1
        End If
        If LinePos < 1 Then
            Let LinePos = 1
        End If
        If CharPos > 20 Then
            Let CharPos = 1
        End If
        If CharPos < 1 Then
             Let CharPos = 1
        End If
        SendOctet(0x1B,0x6C,0x01,LinePos)
        If CharPos > 1 Then
            Let CharPos = CharPos - 1
            Repeat CharPos
                SendOctet(0x1B,0x5B,0x43)
            End Repeat
        End If
    End Sub
    
    Sub ClearBuffer
        Let ArrayPos = 1
        Repeat 48 'Fill Buffer with null characters
            Let DisplayArray(ArrayPos) = 0
            Let ArrayPos = ArrayPos + 1
        End Repeat
    End Sub
    
    Sub SetBottomArrow(In ArrowPos As Byte, In ArrowOn As Byte)
        If ArrowPos > 20 Then
            Let ArrowPos = 1
        End If
        If ArrowPos < 1 Then
            Let ArrowPos = 1
        End If
        If ArrowOn > 1 Then
            Let ArrowOn = 0
        End If
        SendOctet(0x1F,0x23,ArrowOn,ArrowPos)
    End Sub
    
     
  • Anobium

    Anobium - 2021-04-17

    Brilliant. Video is great!

     
    • mkstevo

      mkstevo - 2021-04-17

      Thanks. I know you like a video!

       
  • Chris Roper

    Chris Roper - 2021-04-17

    It may be worth looking up the VT100 terminal codes, they are the most commonly used for serial displays.

     
    • mkstevo

      mkstevo - 2021-04-17

      Needless to say, I had no idea regarding the VT100 codes. That might have been easier than reverse engineering with a logic probe.

      You live and learn.

      Mind you, I've got the text on the display, I can move to a specific point and can clear the display. For re-purposing into a clock, that's all I'll need. I felt quite smug to have got that done so didn't go any further. Don't want to push my luck.

       
  • stan cartwright

    stan cartwright - 2021-04-17

    2 x 20...why bother? Get a 320 x 240 glcd supported and have fun with using graphics.
    Bit of imagination and display anything.

     
    • Chris Roper

      Chris Roper - 2021-04-17

      Repurpose rather than Repurchase Stan.
      It is not about saving money it is about being creative and saving the Planet.

       
    • mkstevo

      mkstevo - 2021-04-18

      Why bother?

      I was given the displays, I thought I could do something with them.
      It was a challenge.
      I like a challenge.
      It kept me entertained.
      I'll be able to make a clock that has room to show the full day, date, year and time and still read from across the room.
      I might make something else.
      Who knows.

      I accepted the challenge.
      Used my cheap Chinese logic probe.
      Decoded the protocol all by myself.
      Wrote a program that emulates that protocol which worked.

      Challenge defeated.

      You never know, it might also help someone else get to grips with similar displays.

       

      Last edit: mkstevo 2021-04-18
  • David Stephenson

    I managed to get a 8 digit 7 segment working driving it from a 16F887 (with the help of transistors - 17 if I recall correctly).
    They are fascinating as essentially they are cathode ray tubes, but we are looking down at the anode coated with a phosphor through the grid and cathode. As with all CRTs you need to heat the cathode so there is a low voltage (high-ish current) supply for the heater which ideally should be a.c. with d.c. one end would be at a lower voltage and so the display less bright( at that end).
    If you ever messed with vacuum tubes you will also know that you need a grid bias voltage - these displays are no exception (I did it with a zener). The other thing is you need at least 30V on the anode (relative to the cathode, with the grid, in an off state, pulled a further 5V below below the cathode).

     
    • mkstevo

      mkstevo - 2021-04-18

      As luck would have it, these displays are entirely self contained with the inverter for the HV and heaters all running from a single 5-6V supply. They also have the full driver/decoder built in making their use so much easier.

      I've also got a much smaller unit that Noritake Itron sent me as a sample that was suggested could be a replacement as the standard 20x2 LCD character displays. While it is a similar size to a 1602 (or 2002) LCD, they are so much more expensive I never got any further than powering up the sample. It is a lovely display, no doubt, but not worth paying in the region of ten times the cost of a Winstar LCD equivalent (£71 + £14 VAT from Farnell!).

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.