AvBrand Exploring Technology
AvBrand Exploring Technology
All Projects Car PC Thermostat Power Monitor Toilet Dog Dish PopCARD Cheapo Power Dance Floor 

Old LED Sign Technical Details

The specific sign I was using is the NS-500UA from AffordableLED. You can buy it here for $229. Affordable LED NS-500UA

The features it has that make it the right sign for the job:

The Serial Protocol

I used the included software and a serial port sniffing application to reverse-engineer the protocol that the NS-500UA uses. I've included it on this page. If you find this useful, please be sure to give me credit. The code below is in Visual Basic 6 language.

Private Sub setSignText(inTxt As String)

    Dim i As Long
    
    On Error Resume Next
    
    ' Set the com port to the sign's port.
    Form1.COM3.CommPort = Val(readConfigValue("ledsign", "comport"))
    
    ' Attempt to open the com port

    If Not Form1.COM3.PortOpen Then Form1.COM3.PortOpen = True
    If Err.Number <> 0 Then

        addToLog "[LEDSIGN]", "COM Port error:", Err.Description
        Exit Sub ' Error opening port
    End If
    
    
    With Form1.COM3 ' Select the com port.

    
        
        ' Send the initialization bytes

        .Output = Chr(&H0)
        .Output = Chr(&HFF)
        .Output = Chr(&HFF)
        .Output = Chr(&H0)
        .Output = Chr(&HB)
        
        ' Next, the sign seems to expect bytes 0 to 127 to be sent.
        For i = 0 To 127
            .Output = Chr(i)
        Next

        
        ' Some more init bytes.
        .Output = Chr(&H0)
        .Output = Chr(&HFF)
        
        ' Start of message?
        ' This byte seems to indicate what to do:
        ' 1 : Program sign file <- that's the one we care about

        ' 2 : Schedule
        ' 5 : Hourly alarm
        ' 8 : Set time and date
        .Output = Chr(&H1)
        
        ' Which file to use.
        ' We just want to overwrite what's on the sign, 
        so we're going to send file 01.
        .Output = "01"
         
        ' Set to default color and font
        .Output = Chr(&HEF) & Chr(&HB0) & Chr(&HEF) & Chr(&HA2)
        
        ' Send the actual text to display, replacing any control codes 
        with their binary equivalents
        .Output = fixText(inTxt)
        
        ' End of message
        .Output = Chr(&HFF) & Chr(&HFF) & Chr(&H0)
        
    End With

End Sub


Private Function fixText(s As String) As String ' Replace control codes in the string to the bytes the sign is expecting. Dim sC As String Dim eC As String ' Default color and font sC = Chr(&HFF) ' Control byte eC = Chr(&HEF) & Chr(&HB0) & Chr(&HEF) & Chr(&HA2) s = Replace(s, "\n", Chr(&HFF)) ' Line break s = Replace(s, "<CYCLIC>", sC & Chr(&H1) & eC) s = Replace(s, "<IMMEDIATE>", sC & Chr(&H2) & eC) s = Replace(s, "<OPENFROMRIGHT>", sC & Chr(&H3) & eC) s = Replace(s, "<OPENFROMLEFT>", sC & Chr(&H4) & eC) s = Replace(s, "<OPENFROMCENTER>", sC & Chr(&H5) & eC) s = Replace(s, "<OPENTOCENTER>", sC & Chr(&H6) & eC) s = Replace(s, "<COVERFROMCENTER>", sC & Chr(&H7) & eC) s = Replace(s, "<COVERFROMRIGHT>", sC & Chr(&H8) & eC) s = Replace(s, "<COVERFROMLEFT>", sC & Chr(&H9) & eC) s = Replace(s, "<COVERTOCENTER>", sC & Chr(&HA) & eC) s = Replace(s, "<SCROLLUP>", sC & Chr(&HB) & eC) s = Replace(s, "<SCROLLDOWN>", sC & Chr(&HC) & eC) s = Replace(s, "<INTERLACE1>", sC & Chr(&HD) & eC) s = Replace(s, "<INTERLACE2>", sC & Chr(&HE) & eC) s = Replace(s, "<COVERUP>", sC & Chr(&HF) & eC) s = Replace(s, "<COVERDOWN>", sC & Chr(&H10) & eC) s = Replace(s, "<SCANLINE>", sC & Chr(&H11) & eC) s = Replace(s, "<EXPLODE>", sC & Chr(&H12) & eC) s = Replace(s, "<PACMAN>", sC & Chr(&H13) & eC) s = Replace(s, "<STACK>", sC & Chr(&H14) & eC) s = Replace(s, "<SHOOT>", sC & Chr(&H15) & eC) s = Replace(s, "<FLASH>", sC & Chr(&H16) & eC) s = Replace(s, "<RANDOM>", sC & Chr(&H17) & eC) s = Replace(s, "<SLIDEIN>", sC & Chr(&H18) & eC) s = Replace(s, "<AUTO>", sC & Chr(&H19) & eC) ' Effects 1D-1F : nothing ' Unknown 00-0F ' Unknown 10-1F ' Unknown 20-2F ' Unknown 30-3F ' Unknown 40-4F ' Unknown 50-5F ' Symbols 60-7D s = Replace(s, "<SUN>", Chr(&HEF) & Chr(&H60)) s = Replace(s, "<CLOUDY>", Chr(&HEF) & Chr(&H61)) s = Replace(s, "<RAIN>", Chr(&HEF) & Chr(&H62)) s = Replace(s, "<CLOCK>", Chr(&HEF) & Chr(&H63)) s = Replace(s, "<PHONE>", Chr(&HEF) & Chr(&H64)) s = Replace(s, "<SPECS>", Chr(&HEF) & Chr(&H65)) s = Replace(s, "<FAUCET>", Chr(&HEF) & Chr(&H66)) s = Replace(s, "<ROCKET>", Chr(&HEF) & Chr(&H67)) s = Replace(s, "<BUG>", Chr(&HEF) & Chr(&H68)) s = Replace(s, "<KEY>", Chr(&HEF) & Chr(&H69)) s = Replace(s, "<SHIRT>", Chr(&HEF) & Chr(&H6A)) s = Replace(s, "<CHOPPER>", Chr(&HEF) & Chr(&H6B)) s = Replace(s, "<CAR>", Chr(&HEF) & Chr(&H6C)) s = Replace(s, "<DUCK>", Chr(&HEF) & Chr(&H6D)) s = Replace(s, "<HOUSE>", Chr(&HEF) & Chr(&H6E)) s = Replace(s, "<TEAPOT>", Chr(&HEF) & Chr(&H6F)) s = Replace(s, "<TREES>", Chr(&HEF) & Chr(&H70)) s = Replace(s, "<SWAN>", Chr(&HEF) & Chr(&H71)) s = Replace(s, "<MBIKE>", Chr(&HEF) & Chr(&H72)) s = Replace(s, "<BIKE>", Chr(&HEF) & Chr(&H73)) s = Replace(s, "<CROWN>", Chr(&HEF) & Chr(&H74)) s = Replace(s, "<STRAWBERRY>", Chr(&HEF) & Chr(&H75)) s = Replace(s, "<ARROWRIGHT>", Chr(&HEF) & Chr(&H76)) s = Replace(s, "<ARROWLEFT>", Chr(&HEF) & Chr(&H77)) s = Replace(s, "<ARROWDOWNLEFT>", Chr(&HEF) & Chr(&H78)) s = Replace(s, "<ARROWUPLEFT>", Chr(&HEF) & Chr(&H79)) s = Replace(s, "<CUP>", Chr(&HEF) & Chr(&H7A)) s = Replace(s, "<CHAIR>", Chr(&HEF) & Chr(&H7B)) s = Replace(s, "<SHOE>", Chr(&HEF) & Chr(&H7C)) s = Replace(s, "<GLASS>", Chr(&HEF) & Chr(&H7D)) ' 7E : Blank ' 7F : Blank ' Time & Date 80 - 83 s = Replace(s, "<TIME>", Chr(&HEF) & Chr(&H80)) s = Replace(s, "<DATE>", Chr(&HEF) & Chr(&H81)) s = Replace(s, "<TEMP>", Chr(&HEF) & Chr(&H82)) ' Doesn't work on the NS-500UA ' 90-97: Cartoons s = Replace(s, "<MERRYXMAS>", Chr(&HEF) & Chr(&H90)) s = Replace(s, "<HAPPYNEWYEAR>", Chr(&HEF) & Chr(&H91)) s = Replace(s, "<4THJULY>", Chr(&HEF) & Chr(&H92)) s = Replace(s, "<HAPPYEASTER>", Chr(&HEF) & Chr(&H93)) s = Replace(s, "<HALLOWEEN>", Chr(&HEF) & Chr(&H94)) s = Replace(s, "<DONTDRINKDRIVE>", Chr(&HEF) & Chr(&H95)) s = Replace(s, "<NOSMOKING>", Chr(&HEF) & Chr(&H96)) s = Replace(s, "<WELCOME>", Chr(&HEF) & Chr(&H97)) ' 98-9F: same graphics again ' A0-A6: Fonts s = Replace(s, "<FONT1>", Chr(&HEF) & Chr(&HA0)) ' Small s = Replace(s, "<FONT2>", Chr(&HEF) & Chr(&HA1)) ' Boxy s = Replace(s, "<FONT3>", Chr(&HEF) & Chr(&HA2)) ' Normal s = Replace(s, "<FONT4>", Chr(&HEF) & Chr(&HA3)) ' Pretty Fat s = Replace(s, "<FONT5>", Chr(&HEF) & Chr(&HA4)) ' Fat s = Replace(s, "<FONT6>", Chr(&HEF) & Chr(&HA5)) ' Super fat s = Replace(s, "<FONT7>", Chr(&HEF) & Chr(&HA6)) ' Small fonts ' A7-AF: Missing fonts, mem glitches ' B0-BF: Colors ' The NS-500UA supports only one color s = Replace(s, "<COLOR1>", Chr(&HEF) & Chr(&HB0)) s = Replace(s, "<COLOR2>", Chr(&HEF) & Chr(&HB1)) ' C0-C7: Speeds s = Replace(s, "<SPEED0>", Chr(&HEF) & Chr(&HC0)) ' Fastest s = Replace(s, "<SPEED1>", Chr(&HEF) & Chr(&HC1)) s = Replace(s, "<SPEED2>", Chr(&HEF) & Chr(&HC2)) s = Replace(s, "<SPEED3>", Chr(&HEF) & Chr(&HC3)) s = Replace(s, "<SPEED4>", Chr(&HEF) & Chr(&HC4)) s = Replace(s, "<SPEED5>", Chr(&HEF) & Chr(&HC5)) s = Replace(s, "<SPEED6>", Chr(&HEF) & Chr(&HC6)) s = Replace(s, "<SPEED7>", Chr(&HEF) & Chr(&HC7)) ' Slowest ' C8-CF: Pauses s = Replace(s, "<PAUSE1>", Chr(&HEF) & Chr(&HC8)) s = Replace(s, "<PAUSE2>", Chr(&HEF) & Chr(&HC9)) s = Replace(s, "<PAUSE3>", Chr(&HEF) & Chr(&HCA)) s = Replace(s, "<PAUSE4>", Chr(&HEF) & Chr(&HCB)) s = Replace(s, "<PAUSE5>", Chr(&HEF) & Chr(&HCC)) s = Replace(s, "<PAUSE6>", Chr(&HEF) & Chr(&HCD)) s = Replace(s, "<PAUSE7>", Chr(&HEF) & Chr(&HCE)) s = Replace(s, "<PAUSE8>", Chr(&HEF) & Chr(&HCF)) ' D0-D7: More graphics ' D8-DF: These graphics s = Replace(s, "<CITYSCAPE>", Chr(&HEF) & Chr(&HD8)) s = Replace(s, "<TRAFFIC>", Chr(&HEF) & Chr(&HD9)) s = Replace(s, "<TEAPARTY>", Chr(&HEF) & Chr(&HDA)) s = Replace(s, "<TELEPHONE>", Chr(&HEF) & Chr(&HDB)) s = Replace(s, "<SUNSET>", Chr(&HEF) & Chr(&HDC)) s = Replace(s, "<CARGOSHIP>", Chr(&HEF) & Chr(&HDD)) s = Replace(s, "<SWIMMERS>", Chr(&HEF) & Chr(&HDE)) s = Replace(s, "<MOUSE>", Chr(&HEF) & Chr(&HDF)) ' Beep E0 - E2 s = Replace(s, "<BEEP1>", Chr(&HEF) & Chr(&HE0)) ' 3 beeps s = Replace(s, "<BEEP2>", Chr(&HEF) & Chr(&HE1)) ' 3 short beeps s = Replace(s, "<BEEP3>", Chr(&HEF) & Chr(&HE2)) ' Short beep s = Replace(s, "<BEEP4>", Chr(&HEF) & Chr(&HE3)) ' More beeps s = Replace(s, "<BEEP5>", Chr(&HEF) & Chr(&HE4)) ' Short beep s = Replace(s, "<BEEP6>", Chr(&HEF) & Chr(&HE5)) ' Long beep s = Replace(s, "<BEEP7>", Chr(&HEF) & Chr(&HE6)) ' More beeps s = Replace(s, "<BEEP8>", Chr(&HEF) & Chr(&HE7)) ' Continuous beeping long s = Replace(s, "<BEEP9>", Chr(&HEF) & Chr(&HE8)) ' Continuous beeping short s = Replace(s, "<BEEP10>", Chr(&HEF) & Chr(&HE9)) ' Beeps s = Replace(s, "<BEEP11>", Chr(&HEF) & Chr(&HEA)) ' Really long beep fixText = s End Function

Here are some examples of the messages you see on my sign:

setSignText "<OPENFROMRIGHT>< < < < < <"
setSignText "<OPENFROMLEFT>> > > > > >"
setSignText "<OPENFROMCENTER>< < < > > >"
setSignText "<FLASH>Backing Up<IMMEDIATE>Backing Up<PAUSE8>"

setSignText "<OPENFROMCENTER>Thank you!<PAUSE4><OPENFROMCENTER>  <PAUSE8>"
setSignText "<FLASH>Sorry!<IMMEDIATE>Sorry!<PAUSE8>"
setSignText "<IMMEDIATE>Go Around Me<PAUSE8>"

setSignText "Please turn off your highbeams!            "
setSignText "<IMMEDIATE>Nice Car!<PAUSE8>"
setSignText "<SCROLLUP>Traffic Ahead<SCROLLUP>     Use Alternate Route                    "

setSignText "I'm listening to: " & realCurrSong & "                     <PAUSE8>"

setSignText "<FLASH>ALERT!<SLIDEIN>Your LEFT HEADLIGHT is Broken!                     <PAUSE8>"
setSignText "<FLASH>ALERT!<SLIDEIN>Your RIGHT HEADLIGHT is Broken!                     <PAUSE8>"

setSignText "<FLASH>SLOW DOWN<SLIDEIN>This isn't a race!                     <PAUSE8>"
setSignText "<FLASH>Follow Me!<IMMEDIATE>Follow Me!<PAUSE8>"
		
copyright © 2017 AvBrand.com - sitemap