PR 記事には広告が含まれています
スポンサーリンク
Translate

透明で美しいVFD表示管IV-27Mにカレンダーと時計を表示してみました

スポンサーリンク

IV-27Mに表示する仕組みとリアルタイムクロックを合体させて、カレンダー付き時計を表示させてみたいと思います。

これまで作ってきた、IV-27Mを表示されるプログラムや回路に関して詳しくはこちらです。

リアルタイムクロックPCF2129に関しての記事はこちらです。

スポンサーリンク

回路図

これまでの回路に、リアルタイムクロックの回路を追加しました。

どんどんブレッドボードが拡張されていきます。

スポンサーリンク

プログラム

//HV5812
#include 
#define SPI_FREQ 3300000
#define STROBE_PIN 5

//PCF2719
#include 
#include "PCF2129AT.h"
PCF2129AT rtc;
const int Clock1HzPin = 17;

//for IV-27M
const int GRID_NUM = 14;
long long IV27DispData[GRID_NUM];
char dispData[32] = "";

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 { getTimeTask , dispVFDTask };

void setup()
{
  Serial.begin(115200);
  Wire.begin();
  rtc.init();
  Serial.println("start");

  //Time Setting
  struct tm dt;
  dt.tm_year = 2021 - 1900; // year(from 1900years)
  dt.tm_mon = 5 - 1;      // month(0-11)
  dt.tm_mday = 17;        // day(1-)
  dt.tm_hour = 12;        // hours
  dt.tm_min = 22;         // minits
  dt.tm_sec = 0;          // seconds
  rtc.setDate(&dt);       // Set time to PCF2129

  rtc.setClockOut( ClkoutFreq_1Hz );  //CLKOUT 1Hz

  //Get Time task start
  pinMode( Clock1HzPin , INPUT_PULLUP );
  xTaskCreatePinnedToCore(getTime, "getTime", 4096, NULL, 1, &taskHandle[getTimeTask], 1 );

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

}

void loop ()
{
}

//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);
  }
}

void getTime(void* arg)
{

  int oldPinStatus = digitalRead(Clock1HzPin);
  int newPinStatus;
  struct tm dt;
  while (1)
  {
    newPinStatus = digitalRead(Clock1HzPin);
    if ( oldPinStatus == 0 && newPinStatus == 1 ) //rising edge
    {
      sprintf( dispData ," %02d-%02d %02d.%02d%02d",1 + dt.tm_mon,dt.tm_mday,dt.tm_hour,dt.tm_min,dt.tm_sec);
      setString( dispData, sizeof(dispData) );
      oldPinStatus = newPinStatus;
    }
    if ( oldPinStatus == 1 && newPinStatus == 0)  //folling edge
    {
      rtc.getDate(&dt);          // get date from PCF2129
      Serial.printf("%04d/%02d/%02d %02d:%02d:%02d\n",1900 + dt.tm_year,1 + dt.tm_mon,dt.tm_mday,dt.tm_hour,dt.tm_min,dt.tm_sec);

      sprintf( dispData ," %02d-%02d %02d.%02d.%02d",1 + dt.tm_mon,dt.tm_mday,dt.tm_hour,dt.tm_min,dt.tm_sec);
      setString( dispData, sizeof(dispData) );
      //Serial.printf("%s\n",dispData );

      //clear alarm flag at 10 sec
      if ( dt.tm_sec == 10 )
      {
        rtc.clearAF();
      }
      oldPinStatus = newPinStatus;
    }
    delay(10);
  }
}

//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 );
}

プログラムも、以前のIV-27Mの表示プログラムと、PCF2129のプログラムを合体させました。

PCF2129のCLKOUTの1Hz信号の立ち上がりエッジと、立ち下がりエッジを86行目からのgetTime()タスクの中で検出しています。

立ち下がりエッジ時にリアルタイムクロックから現在時刻を取得して、IV-27Mの表示内容を更新しています。立ち上がりエッジ時には、分と秒の間のドットを消灯するように、表示内容を変更し、1秒に1回ドットが点滅するようになっています。

スポンサーリンク

結果

こちらが動作している様子です。

カメラのシャッター速度の影響で表示がチラついて見えますが、目で見るとチラつきはわかりません。

1秒に1回分と秒の間のドットが点滅し、秒がカウントアップされている様子がわかります。

透明なVFD表示管に、数字の光が浮かんでいて、とっても素敵です。

カレンダーと時計が表示できるようになりましたが、時間の設定がまだできないので、次回は時間の設定をスイッチでできるようにしたいと思います。

つづきはこちら