Arduino Micro & Noritake VFD

Stéphane Lenclud

Founder
Staff member

Purpose & Scope

Provide information about Arduino Micro as we attempt to use such a board to interface with a Noritake GU256x64D-3900 VFD module from a Windows PC over a USB HID connection.
Software engineering skills and basic electronics knowledge are assumed.

Motives

After attempting to interface our VFD module from a PC over parallel port we came to the conclusion that it would be faster and cheaper to use a GPIO solution such as the one offered by Arduino Micro.

Prerequesites

In the following article we make use an Arduino Micro board and a Noritake GU256x64D-3900B VFD module. On top of that we will be needing a breadboard, jumper wires and an assortments of LEDs and resistors to be able to carry out our experiments.

Getting started

  • Download the latest Arduino IDE from Arduino Software page.
  • Plug your Arduino Micro to one of your computer USB port.
  • Open Arduino IDE:
    • Go to menu Tools > Board and select Arduino/Genuino Micro.
    • From that same Tools menu select the Port you board is connected to.
    • Go to menu File > Examples > 01.Basics > Blink
Congratulation you are now ready to start developing for your Arduino Micro board.
Go do some reading about that Blink example you are looking at or just Upload it to your board and see what happens.

upload_2017-6-5_13-52-42.png


Arduino development is done using AVR language.
See also that neat getting started guide.

Digital I/O

From the above Blink example you should be able to set your pins high and low as you wish and visualise the results using LEDs on your breadboard.
Here are the Arduino functions involved with controlling Digital I/O on Arduino:
Those APIs offer individual pin level control and will provide best code portability across various Arduino hardware.
However for our VFD application we will need our micro-controller to pass on significant amount of data from the USB host to the Noritake hardware.
Doing that communication one bit at a time would be rather inefficient so we will need a solution to upload our data one byte at a time as both our hardware are 8-bit.
Luckily Arduino provides means to do port manipulations and tap directly into our ATmega32U4 8-bit registers.

Port manipulation

Looking at the ATmega32U4 to Arduino Micro pin mapping you'll notice that only two ports offer full byte control: port B and port D.
We decided to use port B for our data byte. Here is how the port B pins are laid out on the Arduino Micro PCB.

ArduinoMicroPinoutPortB.png


Here is our breadboard test circuit using 560 Ohm resistors:

ArduinoMicroPortBCircuit.jpg

We modified the Blink example as follow to validate our cabling:
C:
byte offset=0;
int blinkPeriodInMs = 250;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  // Set port B pins as output
  DDRB = B11111111;
}

// the loop function runs over and over again forever
void loop() {
  // Set the one bit corresponding to current offset in our port register
  PORTB = B00000001 << offset;
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(blinkPeriodInMs);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(blinkPeriodInMs);                       // wait for a second
  offset++; // Increase our offset making sure we light up the next LED
  offset%=8; // Keep it between 0 and 7
}
We are now satisfied that our data lines can be conveniently written to using our port B register. We still also need another 2 pins to implement our VFD module protocol.
  • An output pin, called /WR, to signal data has been written and is ready for the display module to read.
  • An input pin, called RDY. The VFD module will use it to notify when it's ready, high or busy, low.
Here again since we care more about efficiency than portability for this project we will use a port rather than the Digital I/O APIs to control those 2 pins.
We decided to use port C for that purpose since it has only two lines available anyway.
PC6 controls Digital Pin 5 and will be used for /WR.
PC7 controls Digital Pin 13 and will be used for RDY.

Arduino to VFD communication

We upgraded our circuit to connect the /WR and RDY pins and we hooked in our VFD module.
We implemented an AVR Sketch to exercise and debug our communication protocol between our micro-controller and our VFD module.
Without the call to delayMicroseconds() we would lose characters in the traffic and get the following result:
bad-vfd-timing.jpg
Once we solved our timing issue our output remains aligned:
good-vfd-timing.jpg

C:
/*
 * Noritake GU256x64D-3900B
 * Character writting test
 * By Stéphane Lenclud
 */

const byte KRdyOffset = 7;
const byte KWrOffset = 6;

/*
 * Send a single byte to our VFD module
 */
void sendByte(byte aByte)
  {
  // Write data
  PORTB = aByte;
  // Bring /WR down to tell our display data is ready
  PORTC &= B10111111;
  // Make sure we wait long enough for our display to kick in
  // This very is important otherwise some characters will be lost
  // 108us was not long enough, characters would get lost.
  // 109us seems very reliable
  delayMicroseconds(109);
  // Set /WR high up again
  PORTC |= 1 << KWrOffset;
  }

/*
 * Clear VFD module screen
 */
void clearScreen()
  {
  sendByte(0x0C);
  }

/*
 * The setup function runs once when you press reset or power the board
 */
void setup()
  {
  // Set port B pins as output
  DDRB = B11111111;
  // Set /WR pins as output
  DDRC = DDRC | B01000000;
  // Set RDY as input
  DDRC = DDRC & B01111111;
  // Clear our screen and wait a bit for it to be noticeable as we come online
  clearScreen();
  delay(1000);
  }

/*
 * The loop function runs over and over again forever
 */
void loop()
  {
  sendByte('O');
  sendByte('K');
  sendByte('-');
  }

Those timing issues could also have been caused by our usage of Serial port logs as we found out later Serial usage would corrupt our HID traffic it seems.

PC to Arduino communication using HID over USB

For high speed communication from PC to Arduino we need to use generic HID also known as raw HID.
HID is basically the protocol that enables your mice, keyboards and joysticks.
Raw HID is a subset of that same protocol typically used for application specific devices such as our display module for instance.
For Arduino to use raw HID you need to setup that HID-Project library in your IDE.
Go to Sketch > Include Library > Manage Libraries then search and install HID-Project library.
It comes with examples that should get you started.

We were not able to send HID reports larger than 64 bytes. So we need to send multiple reports to push a whole frame to our display.
This 64 bytes limitation was detailed in a GitHub issue.
Other than that the implementation was rather straight forward. You can find details in our GitHub repository, look for .ino files if you are interested in the Arduino source code.

Graphic DMA mode

The above testing were done using the VFD module normal command mode. However for better performance we had to switch to Graphic DMA command mode.
DMA mode allows you to tap directly into the display RAM thus gaining access to its frame buffers, on-screen and off-screen ones.

To enable DMA mode you need to toggle the switch number 6 on the DIP of the PCB. That DIP features below in the bottom left corner of that picture.

Noritake-GU256x64D-3900-DIP-switch.jpg

Conclusion

We were able to squeeze a stable 30 FPS driving that Noritake GU256x64D-3900 from our PC over an Arduino Micro.
It's two to three times as fast as devices like the Futaba GP1212A0x and their built-in USB interface.
We are confident performance could be improved further. Given enough time and resources it would be interesting to see how the Arduino raw HID stack could be improved.
Alternatively the Arduino Micro could be replaced by a Teensy 3.2 to see if that boosts performance.

One issue remains, when running sustained high frame rate, we noticed rare occurrence single pixel noise similar to what was caused by using Arduino Serial.write() as explained above.
We are pretty sure this is caused by some Arduino core library somehow. It would be nice to fix but is not a show stopper.

We will most certainly deploy that solution in a production environment at some point to see how stable it is.
Noritake-GU256x64-39xx-and-Arduino-Micro.jpg


References

 
Last edited:

ChesLans

New Member
Hi...in my case my pins are not labeled like in any Noritake/Arduino tutorial/project I could find.I am at this point unsure if I can or can not power it using the arduino's 5v and gnd on pins 2 and 1, and what the other 3 pins mentioned would be on mine. I am guessing RS is reset, and R/W is read write, but am lost with sbusy.

seo expert
 
Last edited:

Stéphane Lenclud

Founder
Staff member
@ChesLans Could you get it working?
I'm not quite sure what you are trying to achieve and which hardware you are using.
I seriously doubt you can power up such a display with any Arduino power output.
That GU256x64D-3900 needs 5V and 850mA.
While developing I used a Molex Power supply. For the final solution it's mounted in a PC and draws power from an ATX PSU via Molex too.
 

Stéphane Lenclud

Founder
Staff member
Can a ESP32 be used?
I don't see why not. You may want to check that the voltage on your pins are compatible with your display.
Having said that I'm not familiar with that ESP32. Does it support Arduino like the Teensy does or is it a different tool chain?
Are you working with that same Noritake display?
 

JulianTT

New Member
I don't see why not. You may want to check that the voltage on your pins are compatible with your display.
Having said that I'm not familiar with that ESP32. Does it support Arduino like the Teensy does or is it a different tool chain?
Are you working with that same Noritake display?
The ESP32 logic level is 3.3V and I end up get a logic level converter. Then I noticed that the display works with a logic level between 0.3 and 5v. I have GU256x128d-3000 (not the B Gen). there is a new update that make it easy to connect the esp32 with the Arduino ide. The reason I want to use the esp32 is the WIFI feature and I’m also not too familiar with it. It has Dual core 32-bit MCU, Frequency 160 MHz, and SRAM 512 KB. Im pretty new to how electrons work, so Im not sure what all this mean.
 
Top