I wanted a "never set" clock, so I made one using a VFD and Ethernet NTP.

Similar projects worth following
So I always get annoyed with clocks. They NEVER do what I want. Either they need setting too often because of drift, or they don’t know Daylight savings time or they are not very readable. NONE of them fit my needs.

For a screen I am using a salvaged VFD from an old Fruit Machine. 16 character 14 segment display with serial input, this has since been upgraded to a 96x8 matrix display (still VFD).
Main control board is an ardiuno clone from eBay, this has since been upgraded to a Spark Core.
Connectivity is via a WizNet5100 board, this was removed as not needed with WiFi.
There is also a Dallas 1-wire Temperature probe because why not?
A Bluetooth audio module with built in amp connects to 2 small speakers and the controller so I can use it for playback at night. It has a sleep timer and media controls which are accessed via a web page or SNMP.

The Box was laser cut from a web service in the UK, I used red mahogany wood stain (only one poorly applied coat in the photo) to darken the wood from it's almost white state when it arrived. There are no interlocking tabs and simple wood glue was used to hold it together.

The VFD is a 96x8 matrix VFD which was salvaged from an old gambling machine. In theory there is a direct graphics mode but I haven't got it working yet.

The main control board is a Spark Core (The "WiFi Arduino") so that I could make the clock wireless.

Power is via a normal 12v supply which goes into a dc2dc board. This provides a nice clean 5v supply and also has a 3.3v LDO which powers the Bluetooth audio module. The amp is onboard (and low power).

The 5v feed also goes to the QI charging module which is glued to the inside of the lid of the clock. I can charge the phone simply by placing it on top now.

  • 1 × Spark Core WiFi Arduino compatible micro board
  • 1 × 96x8 Noritake VFD matrix Salvage from old gambling machine display
  • 1 × BT Audio module OVC3860 based module with onboard amp
  • 1 × DC2DC PSU 12v in, 5v and 3.3v out
  • 2 × 32ohm .25watt Speaker Cheap ebay special small 5cm speakers

View all 6 components

  • Code snippets

    Pyrofer08/01/2014 at 09:23 1 comment

    So a few people have been asking about getting these working. I can tell you it was a nightmare as they DON'T follow the datasheet for the normal Noritake display.

    They come with custom firmware to make them emulate the older controllers used on the Bell Fruit machines.

    One problem is that I think they use inverted data/clock/reset etc lines compared to the datasheet specs. You will NEVER get any response if you are accidentally holding it in reset all the time :)

    Here are the sendbyte and reset routines I used,

    void sendbyte(uint8_t d_chr)


    unsigned char bit_cnt;

    for(bit_cnt=0; bit_cnt<8; bit_cnt++)


    if(d_chr & 0x80) digitalWrite(VFD_Data,HIGH);

    else digitalWrite(VFD_Data,LOW);

    d_chr <<= 1;





    void Reset_VFD(void)


    digitalWrite ( VFD_Reset, HIGH );


    digitalWrite ( VFD_Clock, HIGH);

    digitalWrite ( VFD_Reset, LOW );



    Here are the commands I have worked out so far, these will enable almost full control of the screen. You first have to enable extended commands, then turn on the extra font. After this user defined chars and full graphics mode should work but I haven't decoded how to do these yet.

    #define REVERSE_SCROLL 0xa3

    #define FORWARDS_SCROLL 0xa2

    #define REVERSE_NOSCROLL 0xa1

    #define FORWARDS_NOSCROLL 0xa0

    #define CLEAR_SCREEN 0xb1 // b3

    #define FLASH_SCREEN 0xd1 // contents stay flashing new chars dont

    #define FLASH_OFF 0xd2

    #define FLASH_LASTCHAR 0xd8 // make last char sent flash

    #define SCREEN_OFF 0x80 // Doesn't clear contents

    #define SCREEN_ON 0x81 // contents re-display

    #define BRIGHTNESS 0x84 // followed by brightness byte (0==full 7=lowest) needs extended commands

    #define ENABLE_EXTENDED 0x85 // turn on extra commands

    #define ENABLE_LOWERCASE 0xbc // turn on extended font

    #define USER_DEFINED_SUMMIT 0xa8 //  (for making user defined char)

    #define SCROLL_FROM_0 0xe0

    #define SCROLL_FROM_1 0xe1

    #define SCROLL_FROM_2 0xe2

    #define SCROLL_FROM_3 0xe3

    #define SCROLL_FROM_4 0xe4

    #define SCROLL_FROM_5 0xe5

    #define SCROLL_FROM_6 0xe6

    #define SCROLL_FROM_7 0xe7

    #define SCROLL_FROM_8 0xe8

    #define SCROLL_FROM_9 0xe9

    #define SCROLL_FROM_10 0xea

    #define SCROLL_FROM_11 0xeb

    #define SCROLL_FROM_12 0xec

    #define SCROLL_FROM_13 0xed

    #define SCROLL_FROM_14 0xee

    #define SCROLL_FROM_15 0xef

    #define POS_1 0x90

    #define POS_2 0x91

    #define POS_3 0x92

    #define POS_4 0x93

    #define POS_5 0x94

    #define POS_6 0x95

    #define POS_7 0x96

    #define POS_8 0x97

    #define POS_9 0x98

    #define POS_10 0x99

    #define POS_11 0x9a

    #define POS_12 0x9b

    #define POS_13 0x9c

    #define POS_14 0x9d

    #define POS_15 0x9e

    #define POS_16 0x9f

  • Firmware improvements

    Pyrofer07/30/2014 at 10:53 0 comments

    So I have spent quite a bit of time working on the firmware.

    After linking the BT Audio module via serial to the Spark Core I put in the ability to control it via SNMP, this is not the most convenient method of skipping a song however.

    Using the Spark Core API I made a web page that calls routines in the core, this lets me send play/skip and volume controls etc via the web, much easier.

    I also added a "sleep" timer mode, I can activate a timer with 15,30,45 and 60 minute intervals that will issue the "stop" and "disconnect" commands to the BT Audio module at the end. This means I can put on a LONG playlist or an internet radio as the source and have it stop after an hour (when I am asleep) rather than keep playing all night.

    The next stage is an "Alarm" that activates the BT link and plays a song at a set time to wake me up. This sadly requires the song is pre-queued on the phone because I can't control the track that is played over the BT audio link.

  • QI Wireless Charger

    Pyrofer07/30/2014 at 10:49 0 comments

    after "completing" The clock I decided that I wanted it to also have a wireless charger. I ordered a QI module (unboxed board and coil only) to install.

    The 5v dc2dc provides enough current to run the clock and charger so I split the internal 5v out to the QI module as well as the clock, this prevents needing multiple inputs or a second 5v regulator off the 12v input.

    The charge coil was glued to the lid of the box on the inside and aligned so that my phone would sit neatly on top of the clock, after drying I checked alignment and reassembled the box.

    DANGER! It turns out that the QI charger generates a LOT of heat. The phone gets hot but also the heat builds up inside the clock. I didn't provide vents or airflow because I used the box as a sealed speaker cavity. This is a mistake.

    When charging the whole thing gets too hot inside and causes problems, not the least of which being the BT audio module "crashing" and needing a power cycle to reset.

    For now I am not using the QI charger but the solution is to somehow cool the components while not breaking the "seal" for the speaker. Maybe some kind of heat pipe to a heat sink on the back?

  • Finishing the box

    Pyrofer07/30/2014 at 10:43 0 comments

    After the whole thing is assembled and dried I applied red mahogany wood stain. This turns out to be a mistake in ordering.

    The glue that soaks into the wood prevents the wood stain applying evenly. My advice is to apply wood stain to the wooden parts before fixing the box together in future. The 3mm Plywood is also quite good at soaking up the stain so a second coat after drying really gives it a great look.

    I think a darker stain may be nicer on future boxes.

  • Laser cut Box

    Pyrofer07/30/2014 at 10:40 0 comments

    The box for the clock was designed with Inkscape and uploaded to The finished parts posted back it was simply a matter of gluing them together.

    Unlike a lot of laser cut boxes I didn't use interlocking tabs as I don't like the look they give the finished box. Normal wood glue on the edges forms a good enough bond to hold the whole thing together.

View all 5 project logs

Enjoy this project?



MileStorm wrote 06/04/2019 at 13:58 point

Hi there. Is there any way to view the entire arduino code? Do you have it on github or something? I'm interested in the VFD driving... I have a similar VFD, but I dunno how to connect it properly, but more important how to debug it. How to send some characters to the display. Thanks :)

  Are you sure? yes | no

Matt wrote 08/05/2015 at 21:10 point

Hi Technics, great project and thanks for the info!

 I am trying to get one of these displays working, it's a GU96x8M-K630C1 I can't seem to find any info on it. It has the 11 pin (one missing from the 12) connector fitted.
It's from an old fruit machine (not sure which one, it's an ebay find). Have you had any dealings with these?

The pins "Bell-out" in the following way....
6 Pin con.          12 Pin con.

     1  VCC              1+2

 2  CLK               8

 3  VCC             1+2

 4  DIN                9

 5  RST              10

 6  GND            11+12

 I will give your code snippets a go and let you know how I get on ;)

Matt :)

  Are you sure? yes | no

Technics wrote 07/31/2014 at 18:45 point
Can I get the pin-out of the display module? I have the exact same one. I have had some similar ones running (they were SPI) but code for those doesn't work with this module and I can't find a data sheet.

  Are you sure? yes | no

Pyrofer wrote 07/31/2014 at 20:13 point
If your display came from the same source as mine (Gambling machine salvage) the Datasheet is useless as they are loaded with custom firmware.
Search for GU96x8M etc made by Noritake.
The pinout should be (for mine)
3 VCC (pin usually missing as key pin)

  Are you sure? yes | no

Technics wrote 07/31/2014 at 21:29 point
Your display is exactly identical to the displays I have which I picked up on eBay and apparently came from fruit machines. The pin-out you've given matches the pin-out of some other displays I have but they have a different model numbers and didn't come from fruit machines. They are identical to the GU96x8M-K606C1 in terms of protocol and I've managed to get text and graphics going on those. So it must be down to the protocol/custom firmware difference.

  Are you sure? yes | no

Pyrofer wrote 08/01/2014 at 09:15 point
It actually works on a similar protocol as the older 14segment "starburst" VFD screens, They are in "Emulation" mode for these displays and that protocol works. You have to send extra command codes to enable "new" functionality. On powerup you get the restricted upper case only font for example!
I am going to add some code snippets to the project that should hopefully help you get this working.

  Are you sure? yes | no

Technics wrote 08/03/2014 at 11:53 point
I've managed to dump the firmware out of one of the displays (I have a few of these with weak/worn out phosphor) . I also noticed some other commands are documented in the BFM emulator source code in MAME. I have found there are quite a few more commands available than the ones listed here or in MAME but I'm yet to determine what they all do.

Command 0x8C seems to do quite a lot but it expects quite specifically formatted data and I haven't fully decoded it's purpose. The disassembler I used doesn't do labels well. When I have more time I'll track down a better disassembler and hopefully get a simulator going. In addition to 0x8C the other undocumented commands I have looked at are 0x86 0x87,. These set and clear a flag respectively. Don't know what the flag does yet. While command 0x88 toggles another flag.

The following commands exist but haven't been looked at yet - 0xA4, 0xA5, 0xA6, 0xAC, 0xAD, 0xAE, 0xB0-0xB4, 0xB8, 0xD0-0xD4, 0xD8-0xDA and 0xDC. So there's quite a bit more going on with these.

I may attack it from the other end and have a look at the code that updates the display so I can determine the location of the frame buffer. This would probably make it easier to work out if any of the commands directly manipulate the display data.

  Are you sure? yes | no

Technics wrote 08/03/2014 at 16:30 point
Okay the firmware reverse engineering effort has paid off. I have figured out graphics mode.

To display an image send the following:

0x85 - Enable extended commands.
0x86 - Enable graphics mode commands. Note send 0x87 to graphics mode off.
0xA6 - Send graphics command.
Send 96 bytes of graphics, vertical strips, MSB of each byte = top pixel.
0xA4 - Display the image you just sent.

Also note that command 0xA5 clears the graphics ram.

I have tested it here and it works so I hope that helps with your project.

  Are you sure? yes | no

Technics wrote 08/03/2014 at 20:24 point
Found another handy graphics command for partial screen updates.

Send the following after enabling extended commands and graphics (0x85, 0x86):

0xAE - Partial graphics write.
X1 - Start x position.
X2 - End x position.
Bytes to be written between the two positions.

Still analysing other commands in the firmware. 0xAC does a funky animation to clear the screen (graphics mode needs to be enabled first).

  Are you sure? yes | no

Pyrofer wrote 08/04/2014 at 10:47 point
@technics1979, That is some amazing work! Thanks for all that. I haven't had a chance to test it yet but sounds great. :) Very happy now.
There is a "live" graphics output mode where the 96bytes appear as you type them. I accidentally hit it while playing but have no idea how I did. Maybe just sending the "display graphics" byte before the send graphics byte? Don't know.
Did you see anything on the User Defined characters?
I think these are based around the command byte 0xA8 and then 7 more bytes, one for the target address and 6 data bytes. I couldn't get consistent correct output from it though.
Maybe we should put up a wiki page on these displays somewhere and document all this properly?

  Are you sure? yes | no

Technics wrote 08/04/2014 at 16:21 point
I haven't tried sending 0xA4 before writing the screen yet but it will probably work that way. If it doesn't then the partial write does update the screen as each byte is entered and you could always use it to update the entire screen. I will have a look at the custom characters function and let you know what I find once I have some more time to work on this.

It would certainly be good to have some documentation for these somewhere. My current notes made while looking at the firmware are a mess. I'll try and tidy them up and put somethng together once I've finished attempting to work out what the last few commands do.

Command 0xA7 expects another byte to follow but I havent figured out what it does with the data. Command 0xAD also expects another byte and uses the two least significant bits to set a pair of flag bits. I haven't figured out the purpose of the flags yet though.

I was hoping to find a command that would shift the enire display one pixel (left or right) and insert a single vertical strip so the display could be scrolled in graphics mode but I haven't seen anything like that.

  Are you sure? yes | no

Pyrofer wrote 08/04/2014 at 17:07 point
Thanks, amazing work with the firmware there :)
They are pretty much completely usable for all features now :)
Tested the graphics mode and got bytes on screen as expected so all good!

  Are you sure? yes | no

Technics wrote 08/04/2014 at 20:09 point
You're welcome. I has been a fun challenge. I have some more information. Sending 0xA7 followed by some text causes the text to be displayed as a scrolling marquee. To exit this mode send 0x00 (This will finish scrolling the entered text and then accept new input) or 0xAF (This will abort the scrolling if it isn't complete and accept new input immediately).

Sending 0xAD followed by a value from 0x00 to 0x03 adjusts the speed of the scrolling.

  Are you sure? yes | no

Technics wrote 08/04/2014 at 22:14 point
The custom characters work as follows:

0xA8 - Custom character
0x00-0x0F there are 16 slots available
0x?? ascii code. I.e. 0x41 here would replace 'A' with the new character
followed by 6 bytes of character data

Unfortunately to character data is not a 1 to 1 mapping of bits to pixels. I haven't decoded the mapping but it could be found by trial and error.

  Are you sure? yes | no

Adam Fabio wrote 07/06/2014 at 05:02 point
Now that's an awesome clock! Thanks for entering it in The Hackaday Prize! I may need to build one of these - what sort of gambling machine did you find your VFD display in?
Keep the updates coming as you progress, and don't forget about the videos!
Good luck!

  Are you sure? yes | no

Pyrofer wrote 07/24/2014 at 08:36 point
Old 90's machines from Bell Fruit, Barcrest etc tend to have them. They normally have 4 mechanical reels and a top panel covered in lights. You can find them on ebay if you search for Bell fruit and Barcrest.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates