An 8 digit VFD for the ESP32

I got hold of a Vacuum Fluorescent Display module from Aliexpress. It comes in two versions : one with an SPI interface, one without. I went with the SPI interface version. The display reminded me of a clock radio I had growing up so it was natural to put it to work as a clock. I wired it to an ESP32-CAM module as shown below:

Details about how the display is programmed were found over here. I wanted to use the SPI hardware interface instead of bit-banging the data and so developed the following program using Arduino for ESP32:

#include <SPI.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <HTTPClient.h>

/*
  ESP32 based clock.
  Uses Vacuum Fluourescent Display (VFD)
  Gets time from an NTP server
*/

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

const char* ssid = "***********";
const char* password =  "****************";

class VFDisplay
{
  public:
    VFDisplay() {};
  void begin()
  {     
    SPI.begin(SCK,MISO,MOSI,SS);
    pinMode(Reset,OUTPUT);
    pinMode(CS,OUTPUT);
    digitalWrite(Reset, LOW);
    delayMicroseconds(5);
    digitalWrite(Reset, HIGH);
    
    setDigitCount(8);
    setBrightness(127);    
    Serial.printf("VFD_init\n");
  }  
  void putChar(unsigned char x, char chr)
  {
    digitalWrite(CS, LOW); 
    writeDisplay(0x20 + x); 
    writeDisplay(chr);
    digitalWrite(CS, HIGH); 
    show();    
  }
  void printString(char *str)
  {
    int x = 0;
    while(*str)
    {
      putChar(x++,*str++);
    }
  }      
  private:
  void setDigitCount(uint8_t count)
  {
      digitalWrite(CS, LOW);
      writeDisplay(0xe0);
      delayMicroseconds(5);
      writeDisplay(count-1);
      digitalWrite(CS, HIGH);
      delayMicroseconds(5);  
  }
  void setBrightness(uint8_t brightness)
  {
    digitalWrite(CS, LOW);
    writeDisplay(0xe4);
    delayMicroseconds(5);
    writeDisplay(brightness);
    digitalWrite(CS, HIGH);
    delayMicroseconds(5);
  }
  void show()
  {    
    digitalWrite(CS, LOW);
    writeDisplay(0xe8);     
    digitalWrite(CS, HIGH); 
  }
  void writeDisplay(uint8_t b)
  {
    SPI.beginTransaction(SPISettings(1000000, LSBFIRST, SPI_MODE0));
    SPI.write(b);
    SPI.endTransaction();
  }

  uint8_t Reset=15;
  uint8_t CS = 12;
  uint8_t SCK = 4;
  uint8_t MOSI = 2;
  uint8_t MISO = 1;
  uint8_t SS = 12; // not actually used - see CS above

};

VFDisplay vfdisplay;
void setup() {
    
  Serial.begin(115200);  
  vfdisplay.begin();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    vfdisplay.printString("WifiWait");    
    delay(1000);    
  }
  vfdisplay.printString("WifiDone");
  timeClient.begin();
  timeClient.setTimeOffset(3600);
  timeClient.update();
  timeClient.setUpdateInterval(5*60*1000); // update from NTP only every 5 minutes  
}

void loop() {
  timeClient.update();     // This will only go to the Internat if the update interval has passed (set to 5 minutes above)
  String timeString = timeClient.getFormattedTime();
  char TimeCharArray[20];
  timeString.toCharArray(TimeCharArray,19);
  vfdisplay.printString(TimeCharArray);
  delay(100);
}

The system appears to work well and could be extended to include a Bluetooth interface to set an alarm time or time zone etc.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s