ESP-01でFUTABA蛍光表示管(VFD)を表示する

#はじめに
FUTABAの6桁5x7ドットマトリクスの蛍光表示管(VFD)を購入したので使用方法をメモしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211703/0991fb9e-fec8-ec5f-848c-de607fb59315.png)

FUTABA 6桁5x7ドットマトリクスVFD管
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211703/09c931cd-537b-0933-14a6-91388be33e6f.png)

#仕様
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211703/85fcba7b-da27-ccf7-7592-a74ecfc7e325.png)

購入したページには何も記載がない。接続端子はGND, VCC, RESET, CS, CLK, DINの6こ、VCCに5Vを入力すればフィラメント電源と駆動電源は生成してくれる様だということしかわからない。
検索してみると仕様書(PTC PT6302)とプログラム例が出てきたのだが、仕様書でプログラムの情報が違う。プログラムは一応動作したのだが、これでは応用が効かない。特にCGRAMにデータを書き込んで任意の形状を表示したい。

[こちら](https://github.com/davll/futabavfd8)に[仕様書](https://raw.githubusercontent.com/davll/futabavfd8/master/datasheet.pdf)があるのを発見。これでプログラムを組める。

#接続

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211703/e33f6c0e-559b-5790-5f4d-fa75f7efb42e.png)

#プログラム


```ESP-01_VFD.ino

///////////////////////////////////////////////////////////////////////
// 2021/10/09
// VFD 表示テスト
///////////////////////////////////////////////////////////////////////
// VFD FUTABA 6 DIGIT VFD MODULE
//
// 1  GND
// 2  5V
// 3  RST  -- TX PIN
// 4  CS   -- RX PIN
// 5  CLK  -- IO2 PIN
// 6  DIN  == IO0 PIN
//
// SPEC SHEET (FOR 8 DIGITS)
// https://github.com/davll/futabavfd8/blob/master/datasheet.pdf
//
///////////////////////////////////////////////////////////////////////
//
// 参照コード
// https://github.com/hexesdesu/ESP32VFDClock
//
///////////////////////////////////////////////////////////////////////

#define IO0   0
#define TX    1
#define IO2   2
#define RX    3

uint8_t din   = IO0;
uint8_t clk   = IO2;
uint8_t cs    = RX;
uint8_t Reset = TX;

const unsigned char CG0[] = {
  0b00010001,
  0b00010010,
  0b00010100,
  0b00011000,
  0b00010000,
  0b00010000,
  0b00010000,
};
const unsigned char CG1[] = {
  0b00010000,
  0b00001000,
  0b00000100,
  0b00000010,
  0b00000001,
  0b00011111,
  0b00010101,
};

unsigned char bright_level = 128;
void FVFD_send(unsigned char w_data)
{
  unsigned char i;
  for (i = 0; i < 8; i++)
  {
    digitalWrite(clk, LOW);
    if ( (w_data & 0x01) == 0x01)
    {
      digitalWrite(din, HIGH);
    }
    else
    {
      digitalWrite(din, LOW);
    }
    w_data >>= 1;
    digitalWrite(clk, HIGH);
  }
}

void FVFD_write_cmd(unsigned char command, unsigned char data)
{
  digitalWrite(cs, LOW);
  FVFD_send(0xe4);     // select the mimming data set
  delayMicroseconds(5);
  FVFD_send(data); // 0 - 255 but level is capped up to 240 (max);
  digitalWrite(cs, HIGH);
  delayMicroseconds(5);
}

void FVFD_DispON(void)
{
  digitalWrite(cs, LOW);
  FVFD_send(0xe8);
  digitalWrite(cs, HIGH);
}

///////////////////////////////////////////
// Set dim level
void FVFD_Brightness(char dim_level)
{
  FVFD_write_cmd( 0xe4, dim_level);
  bright_level = dim_level; // save current level
}
///////////////////////////////////////////
// get dim level
unsigned char FVFD_GetBrightnessLevel()
{
  return bright_level;
}
///////////////////////////////////////////
// Set number of Grid output used
void FVFD_DispTiming(char digit, char universal)
{
  // "universal" is serverved paratemer
  universal = 0;
  FVFD_write_cmd( 0xe0, universal << 8 + digit );
}
///////////////////////////////////////////
// Disp light ON/OFF (ALL SEG ON/OFF)
// onoff : 0:all off, 1: all ON
// NOTE : ALL OFF is not : non fanctionable
void FVFD_alldispON(char onoff)
{
  if ( 1 == onoff) // going to ON
  {
    FVFD_write_cmd( 0xe8 | 0x00, 0 ); // 0x02 ALL OFF=same sa reset state, 0x00 normal
    FVFD_standby(0);  // set brigtness for active
  }
  else  // OFF
  {
    FVFD_write_cmd( 0xe8 | 0x02, 0 ); // ON
  }

}

///////////////////////////////////////////
// Disp module standby
// onoff : 0:normal, 1: standby
void FVFD_standby(char active)
{
  if ( 1 == active )
    FVFD_write_cmd( 0xec | 0x01, 0 ); // Active = standby
  else
  {
    // to setbock from stanby, set brightness
    FVFD_Brightness( FVFD_GetBrightnessLevel() );
  }
}

///////////////////////////////////////////
// VFD inital sequence
// onoff : 0:all off, 1: all ON= non use(spec not avail. in this module)
void FVFD_init()
{
  // reset
  digitalWrite(Reset, LOW);
  delayMicroseconds(5);
  digitalWrite(Reset, HIGH);

  // set number of characters for display;
  FVFD_DispTiming( 6, 0); // 6 digits

  // set brightness;
  FVFD_Brightness(128); // 0-240

  // Display ON
  FVFD_alldispON( 1 ); // normal operation
}

//////////////////////////////////////////////////////////////////
// CGRAM DATA WRITE
// for Send display sigle charactor
// dispPos : 0 - 7
// chr : display ascii code
void FVFT_WriteChar(unsigned char dispPos, unsigned char chr)
{
  digitalWrite(cs, LOW);
  FVFD_send(0x20 + dispPos);
  FVFD_send(chr);
  digitalWrite(cs, HIGH);
  FVFD_DispON();  // UPDATE
}
//////////////////////////////////////////////////////////////////
// DCRAM DATA WRITE (set Disp char)
// dispPos : 0 - 32 (X4-X0)
// chr : display ascii code
void FVFT_WriteStr(unsigned char dispPos, char *str)
{
  digitalWrite(cs, LOW);
  FVFD_send(0x20 + dispPos);
  while (*str)
  {
    FVFD_send(*str); // ascii
    str++;
  }
  digitalWrite(cs, HIGH);
  FVFD_DispON();  // UPDATE
}

///////////////////////////////////////////
// Set CGRAM (CUSTOM CHAR)
void FVFD_write_CGRAM(unsigned char addr, const unsigned char* data)
{
  unsigned char submit;

  digitalWrite(cs, LOW);
  delayMicroseconds(5);
  FVFD_send(0x40 + addr);
  for (int i = 4; i >= 0; i--)
  {
    unsigned char bitpos = 0x01 << i;
    submit = 0;
    submit |= (( bitpos & data[0] ) ? 1 : 0) << 0;
    submit |= (( bitpos & data[1] ) ? 1 : 0) << 1;
    submit |= (( bitpos & data[2] ) ? 1 : 0) << 2;
    submit |= (( bitpos & data[3] ) ? 1 : 0) << 3;
    submit |= (( bitpos & data[4] ) ? 1 : 0) << 4;
    submit |= (( bitpos & data[5] ) ? 1 : 0) << 5;
    submit |= (( bitpos & data[6] ) ? 1 : 0) << 6;
    delayMicroseconds(5);
    FVFD_send(submit);
  }
  delayMicroseconds(5);

//FVFD_send(0xff);
//FVFD_send(0x00);
//FVFD_send(0xff);
//FVFD_send(0x00);
//FVFD_send(0x66);
digitalWrite(cs, HIGH);
}

void setup()
{
  // initialize pin output setting
  pinMode(clk, OUTPUT);
  pinMode(din, OUTPUT);
  pinMode(cs, OUTPUT);
  pinMode(Reset, OUTPUT);

  FVFD_init();

}

void loop()
{
  FVFD_Brightness( 255 );
    // TEST 01 : bright test 0 - 255
    FVFT_WriteStr(0, "TEST01");
    delay(2000);
    for (unsigned char i = 0; i < 255; i += 3)
    {
      FVFT_WriteStr(0, "BRT: ");
      char lev[50];
      sprintf(lev, "%02X", i);
      FVFT_WriteStr(4, lev );
      // set brightness;
      FVFD_Brightness( i );
      delay(100);
    }
  
    ///////////////////////////////////////
    // TEST 02 : ON OFF
    FVFT_WriteStr(0, "TEST02");
    delay(2000);
    for (unsigned char i = 1; i < 5; i++)
    {
      if ( i % 2)
      {
        FVFT_WriteStr(0, "GO OFF");
        delay(300);
        FVFD_alldispON( 0 ); // ON/OFF
      }
      else
      {
        FVFD_alldispON(1); // ON
        FVFT_WriteStr(0, "ALL ONY");
        delay(500);
      }
  
      delay(1000);
    }
  
    ///////////////////////////////////////
    // TEST 03 : STNBY
    FVFT_WriteStr(0, "TEST03");
    delay(2000);
    FVFT_WriteStr(0, "STNDBY");
    delay(1000);
    for (unsigned char i = 1; i < 5; i++)
    {
      if ( i % 2)
      {
        FVFT_WriteStr(0, "GOSTBY");
        delay(300);
        FVFD_standby(1);  // go to stanby mode
      }
      else
      {
        FVFT_WriteStr(0, "RECVRY");
        FVFD_standby(0);  // recover from stanby mode
        delay(500);
      }
  
      delay(1000);
    }

  FVFT_WriteStr(0, "START");
  delay(3000);
  ///////////////////////////////////////
  // TEST 04 : CUSTMOM CHAR
  FVFD_write_CGRAM(0, CG0);
  FVFD_write_CGRAM(1, CG1);

  FVFT_WriteChar(0, 'A');
  FVFT_WriteChar(1, 0x00);
  FVFT_WriteChar(2, 0x01);
  FVFT_WriteChar(3, 'A');
  FVFT_WriteChar(4, 'A');
  FVFT_WriteChar(5, 'A');

  delay(4000);

}

```

初期化、表示、表示OFF、任意図形のサンプルで、VFD制御の基本を組み込みました。STM32にも移植したいと思っているのでC++のクラスにしていません。
NTP接続や温度入力などのアプリケーションは、ここでは割愛します。