Sponsored links

All the numbers were displayed by dynamically lighting them with the beautiful and transparent VFD display tube IV-27M

Sponsored links

In the previous article, I displayed only one digit, but this time I would like to dynamically light up and display all digits. Here is the previous article.

Sponsored links

Program

#include <SPI.h>
#define SPI_FREQ 3300000
#define STROBE_PIN 5

const int GRID_NUM = 14;
long long IV27DispData[GRID_NUM];

const int GRID[GRID_NUM] = { 0 , 1, 5, 6, 4, 2, 3, 20, 21, 22, 23, 24, 34, 33};

//                    a   b   c   d   e   f   g  dp
const int SEG[8] = { 25, 27, 30, 31, 29, 26, 28, 32};
const int SEG_NUM = 8;

//                            a  b  c  d  e  f  g
const bool CHAR[18][7] =   { {1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 0, 1},
  {0, 1, 1, 0, 0, 1, 1}, {1, 0, 1, 1, 0, 1, 1}, {1, 0, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0},
  {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1}, {1, 1, 1, 0, 1, 1, 1}, {0, 0, 1, 1, 1, 1, 1},
  {0, 0, 0, 1, 1, 0, 1}, {0, 1, 1, 1, 1, 0, 1}, {1, 0, 0, 1, 1, 1, 1}, {1, 0, 0, 0, 1, 1, 1},
  {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1}
};

//Task Handles
TaskHandle_t taskHandle[10];
enum task { dispVFDTask };

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("start");

  initHV5812();

  //DispVFD task start
  xTaskCreatePinnedToCore(dispVFD, "dispVFD", 4096, NULL, 20, &taskHandle[dispVFDTask], 0);

}

void loop() {

  char charMasterData[] = "0123456789ABCDEF";
  char dispData[] = "                    ";
  for ( int j = 0 ; j < sizeof(charMasterData) - 1 ; j++ )
  {
    for ( int i = 0 ; i < sizeof(dispData) - 1 ; i++ )
    {
      dispData[i] = charMasterData[ ( j + i ) % (sizeof(charMasterData) - 1) ];
    }
    setString( dispData, sizeof(dispData) );
    delay(100);
  }

}

//Tasks
void dispVFD( void* arg )
{
  long long data = 0;
  while (1)
  {
    for ( int i = 0 ; i < GRID_NUM ; i++ )
    {
      data = IV27DispData[i];
      data |= (long long)1 << GRID[i];
      sendData(data);
      delay(1);
      data &= ~((long long)1 << GRID[i]);
    }
    sendData(data);
  }
}

//Functions
//set charactor pattern
void setString( char* str , int length )
{
  bool firstDigitFlag = true;
  
  //zero clear
  for ( int i = 0 ; i < GRID_NUM ; i++ )
    IV27DispData[i] = 0;

  int digits = GRID_NUM - 1;
  for ( int j = 0 ; j < length ; j++ )
  {
    int id = 0;
    switch ( str[j] ) {
      case '0':  id = 0; break;
      case '1':  id = 1; break;
      case '2':  id = 2; break;
      case '3':  id = 3; break;
      case '4':  id = 4; break;
      case '5':  id = 5; break;
      case '6':  id = 6; break;
      case '7':  id = 7; break;
      case '8':  id = 8; break;
      case '9':  id = 9; break;
      case 'A':  id = 10; break;
      case 'B':  id = 11; break;
      case 'C':  id = 12; break;
      case 'D':  id = 13; break;
      case 'E':  id = 14; break;
      case 'F':  id = 15; break;
      case ' ':  id = 16; break;
      case '-':  id = 17; break;
      case '.':  id = 18; break;
      default:   id = 16; break;
    }

    Serial.print(str[j]);

    if ( digits == GRID_NUM - 1 )
    {
      if ( id == 17 ) //'-'
        IV27DispData[digits] |= (long long)1 << SEG[6];
      if ( id == 18 ) //'.'
        IV27DispData[digits] |= (long long)1 << SEG[0];
      if( id != 17 && id != 18 )
      {
        firstDigitFlag = false;
      }
      digits--;
    }
    else
    {

      if ( id == 18 ) //'.'
      {
        //'.'
        if ( digits < GRID_NUM - 1 )
        {
          if ( digits == GRID_NUM - 2 && firstDigitFlag == true)
            IV27DispData[digits + 1] |= (long long)1 << SEG[0];
          else
            IV27DispData[digits + 1] |= (long long)1 << SEG[7];
        }
      }
      else
      {
        //number
        if ( digits < 0 )
        {
          Serial.println("");
          break;
        }

        if ( id == 17 && digits == GRID_NUM - 2 && firstDigitFlag == true)  //'-'
        {
            IV27DispData[digits + 1] |= (long long)1 << SEG[6];
        }
        else
        {

          for ( int i = 0 ; i < 7 ; i++ )
          {
            if ( CHAR[id][i] == 1 )
            {
              IV27DispData[digits] |= (long long)1 << SEG[i];
            }
            else
            {
              IV27DispData[digits] &= ~((long long)1 << SEG[i]);
            }
          }
          firstDigitFlag = false;
          digits--;
        }
      }
    }
  }
}
//init HV5812
bool initHV5812()
{ 
  SPI.begin();
  SPI.setFrequency(SPI_FREQ);
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  pinMode( STROBE_PIN, OUTPUT );
  digitalWrite( STROBE_PIN, LOW );
  long long data = 0;
  sendData( data );
}
//send data to HV5812
bool sendData( long long data ) 
{
  uint8_t transfarData[5];
  transfarData[0] = ( data & 0x000000FF00000000 ) >> 32;
  transfarData[1] = ( data & 0x00000000FF000000 ) >> 24;
  transfarData[2] = ( data & 0x0000000000FF0000 ) >> 16;
  transfarData[3] = ( data & 0x000000000000FF00 ) >> 8;
  transfarData[4] = ( data & 0x00000000000000FF );
  //  Serial.printf("data:%x %x %x %x %x\n", transfarData[0], transfarData[1], transfarData[2], transfarData[3], transfarData[4]);

  SPI.writeBytes(transfarData, sizeof(transfarData));
  digitalWrite( STROBE_PIN, HIGH );
  delayMicroseconds(1);
  digitalWrite( STROBE_PIN, LOW );
}

The display data can now be specified as a char array. Added support for dots (.) in character strings.

The dynamic lighting process uses a task to automatically turn on the dynamic lights using core 0. Therefore, even if core 1 is processing something, the display will continue.

Lighting!

All the digits are now displayed.

All the digits are now displayed, but it is a little dark because of the dynamic lighting.

Now you can freely display numbers on the IV-27M.

Next time, I'd like to program the IV-27M to be a clock with a calendar, and I'd like to use a real-time clock IC instead of NTP.

Copied title and URL