Programmable VFD Display & Ticker

This is a project I’ve been working on for a while now, and it’s finally progressed to the point where I feel comfortable sharing it. The goal was to make a small programmable display so I can quickly check the current Bitcoin or Dogecoin price, see the time, weather, etc as I walk into my room. The display also had to look cool – I tried to make it steampunkish / hipster if you will. I am also contemplating the marketability of a reprogrammable display of this nature. If there is enough interest, I may improve it a bit (laser cut acrylic or wood base, etc…) and try to sell it. Price would likely be between 50$ & $100. Of course it would be open source so anyone could build their own or or modify to their liking.

The whole thing is really just a large VFD (Vacuum Fluorescent Display) and a Raspberry Pi, both of which I mounted to a bent metal plate as a stand. There is also a PIR motion sensor which I have setup to put the display to sleep after a set amount of time with no motion in the room. There are green LEDs between the metal plate and the back of the VFD to create a green glow around the edge. The Raspberry Pi is running it’s default debian distro (Raspbian?) and auto connects to wifi on boot, and a Python script controls the VFD through the Raspberry Pi’s serial port.


This project all started when I purchased a large VFD (Vacuum Fluorescent Display) from a surplus electronics store (Skycraft - greatest surplus store in Orlando) a year or two ago. I found out this display actually accepts serial data. The connector was RS232 voltage level, but there was a MAX232 chip on the back converting the +-12v signal to TTL (+5v) for the onboard controller. I spliced into the 5 volt input to the controller chip and the display happily sprung to life as I sent it simple serial print commands from an Arduino.

To power the Raspberry Pi, I rigged up a LM7805 5v voltage regulator on the back of the metal plate. I’ll hopefully be replacing this with a 5v switching regulator though because the LM7805 heats up the whole metal plate. The PIR sensor is connected directly to one of the I/O pins on the Raspberry Pi, and it triggers an interrupt in the Python script when motion is detected. I may add a photoresistor so the display turns off after a certain amount of time without light (when I go to bed). The last major detail is a small transistor controlling the green leds…I can actually use the Raspberry Pi to PWM the leds to vary the green glow brightness, but this isn’t implemented yet.

More pics:

Here’s the Python Script:

I tried to comment as much as I could, but I’m not a good programmer. Let me know if you have questions about anything.

#working programmable display code woohoo!

import sys, serial, time, requests, json, glob
from time import sleep, strftime
from subprocess import *
from datetime import datetime
global serialport
import RPi.GPIO as GPIO

sensorPin = 7

GPIO.setmode(GPIO.BOARD) #I/O connector layout config
GPIO.setup(sensorPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

global timeTest #this is used for the interrupt
timeTest = 38 #display function takes 16 seconds to run so 38*16 = 608s or about 10m until display goes to sleep after motion stops.

LCD = serial.Serial('/dev/ttyAMA0',19200) #seup serial port
cmd = "ip addr show wlan0 | grep inet | awk '{print $2}' | cut -d/ -f1" #get IP address

def run_cmd(cmd): #get IP address fnc.
 p = Popen(cmd, shell=True, stdout=PIPE)
 output = p.communicate()[0]
 return output

#def getBitcoinPriceStr(): #Screw Mt. Gox
# URL = 'http://data.mtgox.com/api/2/BTCUSD/money/ticker_fast'
# r = requests.get(URL)
# priceStr = "$" + "{0:.2f}".format(float(json.loads(r.text)['data']['last']['value'])) + "/Doge"
# return priceStr

def getDogePriceStr():
 URL = 'http://api.vaultofsatoshi.com/public/recent_transactions?order_currency=doge&payment_currency=usd&count=1' #fetches data I want
 r = requests.get(URL)
 priceStr = "$" + "{0:.6f}".format(float(json.loads(r.text)['data'][0]['price']['value'])) + "/Doge" #uses json to parse text to find price value
 return priceStr

def getBitcoinPriceCampBX():
 URL = 'http://campbx.com/api/xticker.php'
 r = requests.get(URL)
 priceStr = "$" + "{0:.2f}".format(float(json.loads(r.text)['Last Trade'])) + "/BTC"
 return priceStr

def displayStuff():
 LCD.write('\x0E\x0C') #clears display
 ipaddr = run_cmd(cmd)
 LCD.write(datetime.now().strftime('%b %d %H:%M:%S\n'))
 LCD.write('\x10\x0D') #2nd line on display
 LCD.write('IP %s' % ( ipaddr ))
 time.sleep(8) #pause 8 seconds

outStringDoge = getDogePriceStr()
 outStringCampBX = getBitcoinPriceCampBX()
 LCD.write(outStringDoge + " VoS")
 LCD.write(outStringCampBX + " CampBX")

 print "Error"

def resetTimeTest(self): #function called by interrupt in another thread (requires timeTest to be global to still use here?)
 global timeTest
 timeTest = 38
 #print "hello"

LCD.open() #initialization stuff
LCD.write('\x0E\x0C') #clears display \x0C #LCD.write("whatever")
LCD.write("hello & welcome lostengineer")

GPIO.add_event_detect(sensorPin, GPIO.RISING, callback=resetTimeTest, bouncetime=40) #interrupt for PIR sensor

while 1:

 if(timeTest > 0):
 displayStuff() #display isn't asleep until time runs out. time is reset to 10m (38) or whatever by PIR sensor if motion is detected


timeTest = timeTest - 1
 sleep(1) #this main loop runs on a 1s basis with displayStuff() taking 16s during every call.


There are a couple other things you need to do to make everything work.

  1. Make Python executable with $ sudo chmod +x pythonscript.py
  2. Run script as root or it can’t access the serial port $ sudo ./pythonscript.py
  3. Disable boot crap output on serial port on startup
  4. Setup script to autorun on startup

Leave a Reply



  1. swordfish6975

    I wrote something similar over on hack a day comments

    This was my take – http://imgur.com/a/yxR8d

    Feel free to make a folio on cryptofolio.info and use the API

  2. Herman

    I am a software guy. Circuits have to be pretty basic for me to follow.

    I am hacking one of these displays right now. (I bought at least three a while back when Skycraft had them) When you tapped into the line after the MAX232, did you leave the RS-232 functionality or did you cut the line/chip? I attempted to add a wire to pin 12 on the DS14C232 chip (MAX232) and attempted to connect that to my Arduino (and connected the grounds together) but since the line was already at 5V before connecting it, I doubt it would be able to drop the voltage if I don’t cut out the output from pin 12.

    I’m using an Arduino with the ATMEGA328 chip removed as a USB-TTL port and just typing characters in Putty. I use a similar method to program a ESP8266.

    • coyt

      Ahh yeah I did tap the line after the MAX232 but I don’t remember what pins I used off the top of my head. Going real quick off the DS14C232 datasheet, You should connect pin 12 to the TX line on the arduino and connect pin 10 or 11 (not sure) to the RX on Arduino. As you said, you do need ground connected. This should work just as if you were connecting to an ESP8266… although this display will need a slower baud rate.

      Here’s a site i used for some info that doesn’t seem to be online anymore: https://web.archive.org/web/20150208200011/http://technet.147120.com/wiki/index.php/Vacuum_Florescent_Display

    • coyt

      I’ll check my connections for you when I get home and can examine the VFD again.

Next ArticleScore of the Year! Free Multi-kW HF Linear Amplifier!