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行目からの
立ち下がりエッジ時にリアルタイムクロックから現在時刻を取得して、IV-27Mの表示内容を更新しています。立ち上がりエッジ時には、分と秒の間のドットを消灯するように、表示内容を変更し、1秒に1回ドットが点滅するようになっています。
結果
こちらが動作している様子です。
カメラのシャッター速度の影響で表示がチラついて見えますが、目で見るとチラつきはわかりません。
1秒に1回分と秒の間のドットが点滅し、秒がカウントアップされている様子がわかります。
透明なVFD表示管に、数字の光が浮かんでいて、とっても素敵です。
カレンダーと時計が表示できるようになりましたが、時間の設定がまだできないので、次回は時間の設定をスイッチでできるようにしたいと思います。
つづきはこちら
コメント