Introduction: Arduino and the Noritake 24x6 VFD Module (Vacuum Fluorescent Display)

First I would like to thank Noritake for the VFD Module I think it is pretty cool I asked them for one to work with and they gave it to me.

http://www.noritake-elec.com/default.htm

VFDs (Vacuum Fluorescent Display’s) were and are used in a large rage of high end consumer electronics. I got my VFD module from Noritake-itron it is model SCK-Y100-2406-N14, it is a very flexible 24×6 character VFD module in the same form factor of a 20×4 character LCD module. It is a member of Noritake’s CU-Y series VFDs.

I couldn’t find a lot of websites on Arduino and VFD modules so I am making this Instructable using Arduino and the Noritake-itron VFD module. Noritake made using their VFD modules with Arduino very easy.

Step 1: Noritake VFD Module Overview

Noritake sent:
A 24x6 VFD module
A blue acrylic color filter
A six pin serial jumper with five wires
A set of six jumper pins for my circuit board
And the Overviews of the VFD and the Acrylic Filter

The VFD module features:
24x6 character display
5V supply voltage
serial (asynchronous and synchronous) and 8-bit parallel communication
CMOS signal and RS-232 (+-15V) voltage compatible
jumper-selectable baud rate: 9600, 19200, 38400(default), 115200.
extensive built-in character sets: USA, European, Japanese (Katakana only), Multilingual – various fonts and symbols, Canadian and French, Nordic, WPC1252 – european fonts and symbols, Cyrillic, Latin, Portuguese, PC858 – european fonts and symbols
adjustable brightness
locally selectable brightness for highlighting (useful for implementing menus)
double width, and double width & height characters

Step 2: Arduino

I got my Arduimo as a kit I was tired of building a new tester every time I got my hands on something new to play with and Arduino drives everything I have used it to test.

Mind you it had a little trouble at the M.T.O. (Ministry of Transportation of Ontario ;-)

This one is many of the clone Arduino UNO that are available on the market it works the same as all the others so if yours looks different, don’t worry.

Step 3: Step 1 of Hooking the VFD Module Up to Arduino

The 10-pin  jumper block on the top center is used for configuration, and the 14-pin jumper block on the bottom right is used only for parallel mode.

The VFD comes pre-configured to operate in async serial mode at 38400 baud. It isn’t necessary to use a UART to talk to the VFD; any GPIO pins will suffice. A minimum of 2 pins are needed, for SIN (input) and SBUSY (output). A third GPIO pin can be connected to RESET (input).

The writing speed of this VFD is very fast. Running in async serial mode on an Arduino UNO at 38400 baud, I was able to output 120 characters in a mere fraction of a second.

For this I used the serial jumper that came with the 24x6 VFD module.

Step 4: Step 2 of Hooking the VFD Module Up to Arduino

I hooked mine up to an Arduino UNO as follows:
Pin 1 VCC to 5 Volts
Pin 2 SIN to D2
Pin 3 GND to GND
Pin 4 SBUSY to D3
Pin 5 NC
Pin 6 RESET to D4

Step 5: Using the Noritake VFD Module With Arduino

To use the Noritake VFD with Arduino, first download the Arduino code library.

To download the Arduino Libraries go to this sight:

http://www.noritake-elec.com/arduino-code-library-quick-start-guide.php

Follow the instructions to download the CU-U, CU-Y, or the GU-7000 Arduino zip file and save it.

Once you save the file open it and move the file to Arduino’s Library.

From the Arduino IDE’s pull-down menu select Open, then Library then CU-U, CU-Y, or GU-7000 and pick the sketch like Brightness or Hello.

Step 6: Where’s the Any Key

Ok one day I walk into my local computer store and my buddy Dave is talking to another computer programmer about customers calling in and asking, “Where’s the any key?” They were mocking them and I didn’t like it so I took out my car keys and pushed them saying, “Ok that is any key so why isn’t it working? That is any key.”

It is also assumptive English.

I learned programming in college and “Any key” is a common term used in college so I know what it means however that doesn’t mean someone just learning programming does. Many of the people just learning Arduino are learning without the benefit of a teacher to get them through the lax English used by programmers.

I really didn’t find any big Any Key problems however “Uncomment” was close.

// ****************************************************
// ****************************************************
// Uncomment one of the communication interfaces below.
//
//CUY_Serial_Async interface(38400,3, 5, 7); // Baud rate,SIN,BUSY,RESET
//CUY_Serial_Sync interface(3, 5, 6, 7); // SIN,BUSY,SCK,RESET
//CUY_Parallel interface(8,9,10, 0,1,2,3,4,5,6,7); // BUSY,RESET,WR,D0-D7
//
// ****************************************************
// ****************************************************

For those that are new to Arduino that means to remove the backslashes in front of the line of code you want.

For my Arduino I changed this line:

//CUY_Serial_Async interface(38400,3, 5, 7); // Baud rate,SIN,BUSY,RESET

To:

CUY_Serial_Async interface(38400,2, 3, 4); // Baud rate,SIN,BUSY,RESET

Adding my pin outs 2, 3, 4.

#include <CUY_Interface.h>
#include <CUY_Parallel.h>
#include <CUY_Serial_Async.h>
#include <CUY_Serial_Sync.h>
#include <Noritake_VFD_CUY.h>

// ****************************************************
// ****************************************************
// Uncomment one of the communication interfaces below.
//
//CUY_Serial_Async interface(38400,3, 5, 7); // Baud rate,SIN,BUSY,RESET
//CUY_Serial_Sync interface(3, 5, 6, 7); // SIN,BUSY,SCK,RESET
//CUY_Parallel interface(8,9,10, 0,1,2,3,4,5,6,7); // BUSY,RESET,WR,D0-D7
//
// ****************************************************
// ****************************************************

Noritake_VFD_CUY vfd;

void setup() {
  _delay_ms(500);      // wait for device to power up
  vfd.begin(20, 2);    // 20x2 character module
  vfd.interface(interface); // select which interface to use
  // Enter the model class
  // E.g. Y1A for CU24043-Y1A
  // Applicable model classes:
  //   Y1A
  //   YX1A
  //   Y100
  //   YX100
  vfd.isModelClass(Y1A);
  vfd.CUY_init();      // initialize module
  vfd.print("Noritake"); // print Noritake on the first line
}

void loop() {
}

Step 7: Hello

If you adjust the code right this is what you should see when you upload the sketch.

Make sure the following headers are in your sketch:

#include <CUY_Interface.h>
#include <CUY_Serial_Async.h>
#include <Noritake_VFD_CUY.h>

Two classes need to be instantiated:

CUY_Serial_Async interface(38400,2, 3, 4); // SIN,BUSY,RESET

Noritake_VFD_CUY vfd;

Here is what initialization looks like:

void setup() {
  delay(500);          // wait for device to power up
  vfd.begin(24, 6);    // 24x6 character module
  vfd.interface(interface); // select which interface to use
  vfd.isModelClass(Y100);
  vfd.CUY_init();      // initialize the module
}

Note that Noritake chose to implement only partial compatibility with the LiquidCrystal library.  So while vfd.print(s) is supported, vfd.setCursor(x,y) is not; one has to instead call vfd.CUY_setCursor(x,y). The Noritake_VFD_CUY class methods are declared in Noritake_VFD_CUY.h. Noritake includes a few sample sketches, which you can access from Arduino’s menu via File->Examples->CUY.

Step 8: Menu

Try the Menu sketch making the same changes you made to the Hello sketch. This module does not support brightness boost so you can just leave these lines of code as is or delete them.

  // Uncomment if the target module supports brightness boost
  //vfd.brightnessBoost(); // module has brightness boost 

Menu

#include <CUY_Interface.h>
#include <CUY_Serial_Async.h>
#include <Noritake_VFD_CUY.h>
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>

#define SCREEN_BRIGHTNESS       200     // Maximum character brightness
#define LOW_BRIGHTNESS          14      // Normal character brightness (between 0% and SCREEN_BRIGHTNESS%)
#define HIGH_BRIGHTNESS         200     // Highlight character brightness (between 0% and SCREEN_BRIGHTNESS%)
#define MENU_CATEGORIES         5       // Number of categories in a menu
#define MENU_SPLIT              (vfd.cols>=24? 12: 10) // Width of first column

CUY_Serial_Async interface(38400,2, 3, 4); // SIN,BUSY,RESET

Noritake_VFD_CUY vfd;

// These details will be displayed when a category is selected
class DetailMenuCategory {
public:

  const char  *name;          // Category name
  const char  *caption[2];    // Caption
  int16_t     value[2];       // Sample value
  char        fill[2];        // Pads numbers on the left: ' ' or '0'
  const char  *unit[2];       // Measurement units

  DetailMenuCategory() {
    name = 0;
    caption[0] = caption[1] = 0;
    value[0] = value[1] = 0;
    fill[0] = fill[1] = ' ';
    unit[0] = unit[1] = "";
  }

  DetailMenuCategory(const char *name,
  const char *caption1, const char *unit1,
  const char *caption2, const char *unit2) {
    this->name = name;
    this->caption[0] = caption1;
    this->caption[1] = caption2;
    this->value[0] = this->value[1] = 0;
    this->unit[0] = unit1;
    this->unit[1] = unit2;
    fill[0] = fill[1] = ' ';
  }

};

// Menu class
class DetailMenu {
  void leftAlign(const char *txt, int width, uint8_t styleAfter) {
    int len = strlen(txt);
    vfd.print(txt, width<=len? width: len);
    vfd.CUY_setCharStyle(styleAfter);
    while (width-->len)
      vfd.print(' ');
  }

  void rightAlign(const char *txt, int width) {
    int len = strlen(txt);
    int i = width-len;
    while (i-->0)
      vfd.print(' ');
    vfd.print(txt, width<=len? width: len);       
  }

  // Print a number with 4 digits and one fractional digit.
  void number(int16_t n, char pad) {
    bool zeros = true;
    bool neg = n < 0;

    if (neg)
      n = -n;
    else
      vfd.print(' ');

    for (int16_t i = 10000; 10<=i; i/=10) {
      uint8_t d = n/i%10;
      if (!d && zeros) {
        if (i==10 && neg) vfd.print('-');
        vfd.print(i==10? '0': pad);
      }
      else {
        if (zeros) {
          if (neg) vfd.print('-');
          zeros = false;
        }
        vfd.print("0123456789"[d]);
      }
    }
    vfd.print('.');
    vfd.print("0123456789"[n % 10]);
  }

public:
  DetailMenuCategory  category[MENU_CATEGORIES];   // Categories
  Noritake_VFD_CUY    &vfd;                   // The VFD to display to
  uint8_t             selected;               // Which category is selected

    DetailMenu(Noritake_VFD_CUY &vfd):
  vfd(vfd), selected(0) {
  }

  void draw();
};

void DetailMenu::draw() {
  DetailMenuCategory *cat;

  vfd.CUY_setCharStyle(NoStyle);
  vfd.CUY_setFontStyle(NoFontStyle);
  vfd.CUY_setCharBrightness(LOW_BRIGHTNESS*100/SCREEN_BRIGHTNESS);

  vfd.CUY_home();
  leftAlign("MAIN MENU:", MENU_SPLIT, NoStyle);

  // Print each category
  for (int i = 0; i < MENU_CATEGORIES && i < vfd.lines-1; i++) {
    vfd.print("\r\n"); // Move to the next line

    // Center selected line
    if (this->selected < (vfd.lines-1)/2)
      cat = this->category + i;
    else {
      int j = i + this->selected - (vfd.lines-1)/2;
      if (this->selected > MENU_CATEGORIES - (vfd.lines-1))
        j = i + MENU_CATEGORIES - (vfd.lines-1);
      if (MENU_CATEGORIES <= j) {
        leftAlign("", MENU_SPLIT, NoStyle);
        continue;
      }
      cat = this->category + j;
    }

    uint8_t charset = vfd.charset;
    vfd.CUY_setCharBrightness(HIGH_BRIGHTNESS*100/SCREEN_BRIGHTNESS); // Highlight brightness
    vfd.CUY_setCharset(1);          // Select Katakana table       
    vfd.print("\xe8");              // Print arrow
    vfd.CUY_setCharset(charset);    // Restore user's character set

      // Set style based on whether the category is selected
    // and print the category name.
    if (cat == this->category + this->selected)
      vfd.CUY_setCharStyle(vfd.charStyle + UnderlineStyle);
    else
      vfd.CUY_setCharBrightness(LOW_BRIGHTNESS*100/SCREEN_BRIGHTNESS);           
    leftAlign(cat->name, MENU_SPLIT-1, NoStyle);
  }

  cat = this->category + this->selected;

  // Captions
  vfd.CUY_setCharBrightness(LOW_BRIGHTNESS*100/SCREEN_BRIGHTNESS);
  vfd.CUY_setCursor(MENU_SPLIT,0);
  leftAlign(cat->caption[0], MENU_SPLIT, NoStyle);
  if (vfd.lines > 2) {
    vfd.CUY_setCursor(MENU_SPLIT,(vfd.lines >= 6)? 3: 2);
    leftAlign(cat->caption[1], MENU_SPLIT, NoStyle);
  }

  // Values
  if (vfd.lines >= 6)
    vfd.CUY_setFontStyle(vfd.fontStyle + TallFont);

  vfd.CUY_setCharBrightness(HIGH_BRIGHTNESS*100/SCREEN_BRIGHTNESS);

  vfd.CUY_setCursor(MENU_SPLIT,1);
  number(cat->value[0], cat->fill[0]);
  vfd.print(' ');
  rightAlign(cat->unit[0], 4);

  if (vfd.lines > 2) {
    vfd.CUY_setCursor(MENU_SPLIT,(vfd.lines >= 6)? 4: 3);
    number(cat->value[1], cat->fill[1]);
    vfd.print(' ');
    rightAlign(cat->unit[1], 4);
  }
}

void setup() {
  delay(500);          // wait for device to power up
  vfd.begin(24, 6);    // 24x6 character module
  vfd.interface(interface); // select which interface to use
  vfd.isModelClass(Y100);
  vfd.CUY_init();      // initialize the module
  // Uncomment if the target module supports brightness boost
  //vfd.brightnessBoost(); // module has brightness boost 
}

void loop() {

  vfd.CUY_setScreenBrightness(SCREEN_BRIGHTNESS);
  vfd.CUY_setCursorStyle(NoCursor);
  vfd.CUY_setCharset(2);

  DetailMenu menu(vfd);

  menu.category[0] = DetailMenuCategory(
    "PRESSURE",
    "chamber: 01", "PSI",
    "chamber: 02", "PSI");
  menu.category[0].value[0] = 5000;
  menu.category[0].value[1] = 4560;

  #if MENU_CATEGORIES > 1
    menu.category[1] = DetailMenuCategory(
      "RPM",
      MENU_SPLIT<12? "gen: 01": "generator:01", "RPM",
      MENU_SPLIT<12? "gen: 02": "generator:02", "RPM");
    menu.category[1].value[0] = 20000;
    menu.category[1].value[1] = 19800;
  #endif

  #if MENU_CATEGORIES > 2 
    menu.category[2] = DetailMenuCategory(
      "MAX FLOW",
      "pipe: 01", "m\xfc/s",
      "pipe: 02", "m\xfc/s");
    menu.category[2].value[0] = 4030;
    menu.category[2].value[1] = 7200;
  #endif

  #if MENU_CATEGORIES > 3
    menu.category[3] = DetailMenuCategory(
      MENU_SPLIT<12? "TTL TIME": "TOTAL TIME",
      "chamber: 01", "hr",
      "chamber: 02", "hr");
    menu.category[3].value[0] = 120;
    menu.category[3].value[1] = 220;
  #endif

  #if MENU_CATEGORIES > 4
    menu.category[4] = DetailMenuCategory(
      "CURRENT",
      "total AMP", "mA",
      "voltage", "V");
    menu.category[4].value[0] = 503;
    menu.category[4].value[1] = 56;
  #endif

  // Cycle through each category
  for (int i=0; ; i++) {
    menu.selected = i % MENU_CATEGORIES;
    menu.draw();
    _delay_ms(2000);
  }
}

Step 9: Play With the Code

Play with the code and see what you can do with it, don’t worry it didn’t blow up when I did and it is the only way to find out what the display will do.

Noritake also provides a Handy Host Program called CUE-Y: Y Series Evaluation Software, which lets you configure and test the display without a microcontroller.

http://www.noritake-elec.com/cue-y.html

To use the program, connect the VFD to a PC running Microsoft Windows via a Serial->USB adapter, such as an YTDI cable. Using the Serial->USB adapter opens up the possibility of using the VFD  as a USB auxilliary display for a PC.

http://www.sparkfun.com/products/9718

I am planning to make my own USB connector and try the program in another Instructable.

Full Spectrum Laser Contest

Participated in the
Full Spectrum Laser Contest

Gadget Hacking and Accessories Contest

Participated in the
Gadget Hacking and Accessories Contest

Arduino Contest

Participated in the
Arduino Contest