Doctor Volt
Published © CC BY-SA

Interface VFD Tubes with an Arduino

VFD tubes are a good alternative to Nixie Tubes, especially in retro clock projects. Read about how they can be used with an Arduino.

IntermediateProtip3 hours9,310
Interface VFD Tubes with an Arduino

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
IV-11 VFD Tubes
×4
Breadboard (generic)
Breadboard (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
TBD62783
Transistor Array with 8 channels
×2
HEF 4017
Decimal counter
×1
Step-Up Voltage Regulator - 30V
×1
Step-Down Voltage Regulator 1.5V
For the filaments
×1

Software apps and online services

Visual Studio Code Extension for Arduino
Microsoft Visual Studio Code Extension for Arduino

Story

Read more

Schematics

Schematic

Code

vfdtubes.ino

Arduino
#include "vfd.h";

// The setup() function runs once each time the micro-controller starts
void setup()
{
  Serial.begin(115200);
  vfd_init();
}

void loop()
{
	vfd_write("12.41.34");
};

vfd.cpp

Arduino
/*This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. 
To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/deed.en 
	  _____
	 |  e  |
	c|     |f
	 |_____|
	 |  d  |
	b|     |g
	 |_____|
		a    .p  */

#include "vfd.h"
#define SEG_DP (1 << 7)
#define SEG_A (1 << 6)
#define SEG_B (1 << 5)
#define SEG_C (1 << 4)
#define SEG_D (1 << 3)
#define SEG_E (1 << 2)
#define SEG_F (1 << 1)
#define SEG_G (1 << 0)

const byte numbers[] = {
	SEG_D, //-
	0,0,
	SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G, //0
	SEG_F + SEG_G, //1
	SEG_A + SEG_B + SEG_D + SEG_E + SEG_F, //2
	SEG_A + SEG_D + SEG_E + SEG_F + SEG_G, //3
	SEG_C + SEG_D + SEG_F + SEG_G, //4
	SEG_A + SEG_C + SEG_D + SEG_E + SEG_G, //5
	SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_G, //6
	SEG_E + SEG_F + SEG_G, //7
	SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, //8
	SEG_A + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, //9
};

const byte letters[] = {
	SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G, //A - 10
	SEG_A + SEG_B + SEG_C + SEG_D + SEG_G, //b - 11
	SEG_A + SEG_B + SEG_C + SEG_E, //C -12
	SEG_A + SEG_B + SEG_D + SEG_G + SEG_F, //d - 13
	SEG_A + SEG_B + SEG_C + SEG_D + SEG_E, //E - 14
	SEG_B + SEG_C + SEG_D + SEG_E, //F - 15
};
uint8_t chrtable[127];

// Port mask for the 7 segments + decimal point D5
#define PORT_C_MASK 0x3f //A0..A5
#define PORT_D_MASK (1 << 4) + (1 << 5) //D4..D5
// Multiplex
#define RESET 6 //D6
#define CLK 7 //D7
#define MULTIPLEX_MASK (1 << RESET) + (1 << CLK) 

void vfd_init() {
	//serial.println("-->vfd_init");
	DDRC |= PORT_C_MASK; 
	DDRD |= PORT_D_MASK + MULTIPLEX_MASK; 
	memcpy(chrtable+45, numbers, 13);
	memcpy(chrtable+65, letters, 6);
}

//Set the Segments (val) and devimal point (dpoint)
void write(uint8_t val, bool dpoint) {
	val = toupper(val);
	//Serial.println(val);
	PORTC &= ~PORT_C_MASK;
	PORTC = chrtable[val] & PORT_C_MASK;
	PORTD &= ~(PORT_D_MASK + MULTIPLEX_MASK);
	PORTD |= (chrtable[val] >> 2) & PORT_D_MASK;
	dpoint ? PORTD += (SEG_DP >> 2) : PORTD;
}

//Perform the multiplexing
void vfd_write(const char *val) {
	static uint8_t strpos, tube_nr = 1;
	static uint32_t _mills;
	uint32_t mills = millis();
	write((uint8_t)val[strpos], val[strpos + 1] == '.');

	//Multiplex
	if(mills >= _mills + 1){
		_mills = mills;
		if(val[strpos + 1] == '.'){
			strpos++; //Skip decimal point
		}
		strpos++;
		if(tube_nr++ >= NUMBER_OF_TUBES){
			tube_nr = 1;
			strpos = 0;
			bitSet(PORTD, RESET); //Get back to first tube
		};
		bitSet(PORTD, CLK); //enable next tube
	}
}

vfd.h

Arduino
/*This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. 
To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/deed.en */

#ifndef VFD_H
#define VFD_H

#include <Arduino.h>

//Enter the number of tubes you have here
#define NUMBER_OF_TUBES 6

void vfd_init();
void vfd_write(const char *val);

#endif

Credits

Doctor Volt

Doctor Volt

18 projects • 123 followers

Comments