//******************************************************
// FILE WIFI時計 MAX7219-DOT-LED
// DATE :Tue, Jan 10, 2025
// DESCRIPTION : タイマー割り込みにて 制御。
// CPU TYPE : ESP32
// by Chiyabo
// This file is generated by Renesas Project Generator.
//******************************************************
//
#include < WiFi.h > //For WiFi Network Connection
#include < time.h > //For Time Based Application
#include < MD_Parola.h > //For MAX7219 Matrix LED
#include < MD_MAX72xx.h > //For MAX7219 SPI LED Driver
#include < SPI.h > //For SPI Communication
#include < WiFiUdp.h > //For WiFi UDP
#include " F3x8p.h" // 3x8 font
#include "GF4x8p.h" // 4x8 font
//MAX7219
#define MAX_DEVICES 4 // four modules
#define CLK_PIN 18
#define data_PIN 23
#define CS_PIN 5
//このライブラリは複数の種類のMAX7219製品に対応しています。
//そのため使う製品によってハードウェアの構成を変える必要があります。
//下記の4つの設定のうち、自分のモジュールで正常に表示される設定一つだけを有効にする。
//#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW
//#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define SPEED_TIME 25 //Small numbers are faster. Zero is the fastest.
// ハードウェア SPI 接続を持つ MD_Parola クラスの新しいインスタンスを作成します。
MD_Parola Display = MD_Parola( HARDWARE_TYPE, CS_PIN, MAX_DEVICES ) ;
// ソフトウェア SPI のセットアップ:
//MD_Parola myDisplay = MD_Parola( HARDWARE_TYPE、data1_PIN、CLK_PIN、CS_PIN、MAX_DEVICES ) ;
// 家のwifiのssidとパスワードを入力
const char* ssid = "YOUR_SSID" ;
const char* password = "YOUR_PASSWORD" ;
// NTPサーバー設定
const char* ntpServer = "ntp.nict.jp" ; // 日本標準時(JST)
const long gmtOffset_sec = 9 * 3600 ; // GMT+9(日本時間)
const int daylightOffset_sec = 0 ; // サマータイム(日本は使用しない)
//timer 初期化
hw_timer_t * timer = NULL ;
char TimeInEnCnt = 0 ; //WiFi_Time Read時間 時間*TimeInEnCnt = 時間間隔
char TimeInEn = true ;
char Int_Cnt = 2 ;
char Int_1Sec = false ;
char ErrFlg = false ;
char Sec ; // 秒
char Min ; // 分
char Hor ; // 時
//char Week ; // 曜日
char DisplayTime = true ;
int Sec_Change ;
int Min_Change ;
int Hor_Change ;
// アナログ入力関連
int analogPin = 33 ; // potentiometer wiper (middle terminal)
// connected to analog pin 33
// outside leads to ground and +3.3V
int val = 0 ; // variable to store the value read
char SetBrightNoOld ;
char bufS[ 3 ], bufT[ 6 ] ; // bufS = Sec, 'ss' + 1 = 3, bufT = HourMinute, 'hh:mm" + 1 = 6
char WeekText[ ][ 5 ] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" } ;
//char WeekText[ ][ 8 ] = { "Sunday", "Monday", "Tuesday", "Wednes", "Thurs", "Friday", "Satur" } ;
static char DspBuf1[ 8 ] ;
static char DspBuf2[ 8 ] ;
unsigned char SelMessage = 0 ;
unsigned char DotMessage = false ;
unsigned char MsgNo = 0 ;
// 割込みサービスルーチン 0.5秒
void IRAM_ATTR LED_Blink( ){
if( --Int_Cnt == 0 ){
Int_Cnt = 2 ;
Int_1Sec = true ;
}
}
void setup( ){
//Serial.begin( 115200 ) ;
Display.begin( 2 ) ; // オブジェクトを初期化します: 2 zones
Display.setZone( 0, 1, 3 ) ; //00011111 <- Zone 0 for HM Display1
Display.setZone( 1, 0, 0 ) ; //11100000 <- Zone 1 for Sec Display1
Display.setFont( 0,GF4x8p ) ;
Display.setFont( 1, GF3x8p ) ;
Display.setIntensity( 0 ) ; // ディスプレイの明るさを設定(0〜15)。明るさMax:15
// 周波数を直接指定(ここでは1MHz = 1µsごとにカウントアップ)
timer = timerBegin( 1000000 ) ;
// 割り込み関数を登録
timerAttachInterrupt( timer, &LED_Blink ) ;
// アラーム設定: 500000カウントごと(=0.5Sec)、繰り返し
timerAlarm( timer, 500000, true, 0 ) ; // 第3引数をtrue指定で、繰り返し。その際は第4引数は無
}
void loop( ){
char SetBrightNoNew ;
if( ErrFlg == true ){
WiFiTime( ) ;
}
// 現在時刻を表示
if( Int_1Sec == true ){
Int_1Sec = false ;
//if( Display.displayAnimate( ) ){// 何故か2秒間隔で表示?
Display.displayAnimate( ) ;
DotLed( ) ;
//}
}
// 現在時刻を取得
if( TimeInEn == true ){
TimeInEn = false ;
WiFiTime( ) ;
}
// DisPlay Bright Adjust
if( DisplayTime == true ){
val = analogRead( analogPin ) ; // read the input pin
if( val <= 1490 ){
SetBrightNoNew = 3 ;
}
else if( val <= 2980 ){
SetBrightNoNew = 2 ;
}
else{
SetBrightNoNew = 1 ;
}
if( SetBrightNoOld != SetBrightNoNew ){
SetBrightNoOld = SetBrightNoNew ;
if( SetBrightNoNew >= 3 ){
Display.setIntensity( 1 ) ; // ディスプレイの明るさを設定(0〜15)。明るさMax:15
}
else{
Display.setIntensity( 0 ) ; // ディスプレイの明るさを設定(0〜15)。明るさMax:15
}
}
DisplayTime = false ;
}
}
void connectToWiFi( ){
char RtyErr = 0 ;
// WiFiに接続
WiFi.begin( ssid, password ) ;
// WiFi接続出来るまで繰り返す
while( WiFi.status( ) != WL_CONNECTED ){
delay( 1000 ) ;
if( RtyErr >= 3 ){
ErrFlg = true ;
WiFi.disconnect( true ) ;
return;
}
}
// WiFi接続成功!
}
bool getLocalTime( ){
struct tm timeinfo ;
return getLocalTime( &timeinfo ) ;
}
void printLocalTime( ){
struct tm timeinfo ;
if ( !getLocalTime( &timeinfo ) ){
// 時刻取得エラー
ErrFlg = true ;
WiFi.disconnect( true ) ;
return ;
}
ErrFlg = false ;
// 時刻を整形して表示
//Serial.printf( "現在時刻: %04d/%02d/%02d/%d %02d:%02d:%02d\n ",
// timeinfo.tm_year + 1900,
// timeinfo.tm_mon + 1,
// timeinfo.tm_mday,
// timeinfo.tm_wday, // 曜日
// timeinfo.tm_hour,
// timeinfo.tm_min,
// timeinfo.tm_sec ) ;
sprintf( DspBuf1, "%04d", timeinfo.tm_year + 1900 ) ;
sprintf( DspBuf2, "%02d/%02d %d", timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_wday) ;
SelMessage = ( DspBuf2[ 6 ] -( 16 * 3 ) ) ;
DspBuf2[ 6 ] = NULL ;
DotMessage = true ;
//Serial.println( DspBuf1 ) ;
//Serial.println( DspBuf2 ) ;
//Serial.println( SelMessage, DEC ) ;
Sec = ( char )timeinfo.tm_sec ; // 秒
Min = ( char )timeinfo.tm_min ; // 分
Hor = ( char )timeinfo.tm_hour ; // 時
//Week = ( char )timeinfo.tm_wday ; // 曜日
//Serial.println( Sec, DEC ) ;
//Serial.println( Min, DEC ) ;
//Serial.println( Week, DEC ) ;
//Serial.println( WeekText[ Week ] ) ;
//ESP32のWi-Fi切断
WiFi.disconnect( true ) ;
}
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// FunctionName : WiFi時刻取得
// Prototype: void WiFiTime( void )
// Function : WiFi時刻設定
// Input : NONE
// Output : NONE
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void WiFiTime( void ){
connectToWiFi( ) ;
// NTP時刻設定
configTime( gmtOffset_sec, daylightOffset_sec, ntpServer ) ;
// 時刻同期を待つ
printLocalTime( ) ;
}
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// FunctionName : Led Write Task
// Prototype: void LED( void )
// Function : LED data1 SET & WRITE
// Input : NONE
// Output : NONE
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void DotLed( void ){
char Test ;
if( ++Sec >= 60 ){
Sec = 0 ;
DisplayTime = true ;
if( ++Min >= 60 ){ // 分
Min = 0 ;
if( ++Hor >= 24 ){
Hor = 0 ;
TimeInEnCnt = 0 ;
TimeInEn = true ;
}
if( ++TimeInEnCnt >= 6 ){ // 6時間経過 WiFiTime( )
TimeInEnCnt = 0 ;
TimeInEn = true ;
}
}
}
else if( Sec == 1 ){
DotMessage = true ;
MsgNo = 0 ;
}
//Serial.println( Sec,DEC ) ;
//時計表示切替
Test = HexChgDec( Hor ) ;
bufT[ 0 ] = ( ( Test >> 4 ) + 0x30 ) ;
bufT[ 1 ] = ( ( Test & 0x0f ) + 0x30 ) ;
bufT[ 2 ] = ':' ;
Test = HexChgDec( Min ) ;
bufT[ 3 ] = ( ( Test >> 4 ) + 0x30 ) ;
bufT[ 4 ] = ( ( Test & 0x0f ) + 0x30 ) ;
Test = HexChgDec( Sec ) ;
bufS[ 0 ] = ( ( Test >> 4 ) + 0x30 ) ;
bufS[ 1 ] = ( ( Test & 0x0f ) + 0x30 ) ;
//時計表示切替
//Zone 0 Time
if( DotMessage == true ){
if( Display.displayAnimate( ) ){
DotLed1( MsgNo ) ;
if( ++MsgNo == 4 ){ ;
DotMessage = false ;
}
}
}
else{
//if( Display.getZoneStatus( 0 ) ){ //何故か1秒遅れて変化?
Display.displayZoneText( 0, bufT, PA_CENTER, SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT ) ;
Display.displayReset( 0 ) ;
//}
}
//Zone 1 Time
//if( Display.getZoneStatus( 1 ) ){ //何故か2秒単位で変化?
Display.displayZoneText( 1, bufS, PA_RIGHT, SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT ) ;
Display.displayReset( 1 ) ;
//}
}
void DotLed1( unsigned char MsgNo ){
if( MsgNo == 0 ){
Display.displayZoneText( 0, DspBuf1, PA_CENTER , SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT ) ;
Display.displayReset( ) ;
}
else if( MsgNo == 1 ){
Display.displayZoneText( 0, DspBuf2, PA_CENTER , SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT ) ;
Display.displayReset( ) ;
}
else{ // 2 3
Display.displayZoneText( 0, WeekText[ SelMessage ], PA_CENTER , SPEED_TIME, 0, PA_PRINT, PA_NO_EFFECT ) ;
Display.displayReset( ) ;
}
}
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// FunctionName : HexChgDec
// Prototype: int HexChgDec(unsigned char HexByte)
// Function : HEXをDEC値に変換する
// Input : 00h-->ffh
// Output : 変換結果
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int HexChgDec( unsigned char HexByte ){
unsigned char i ;
int Value , Work ;
i = 0 ;
Value = Work = 0 ;
for( Work = 0 ; HexByte >= 0x0a ; Work++ ){
HexByte = ( HexByte - 0x0a ) ;
}
if( Work >= 0x0a ){
for( i = 0 ; Work >= 0x0a ; i++ ){
Work = ( Work - 0x0a ) ;
}
}
Value = ( ( i * 0x100 ) + ( Work * 0x10 ) + ( int )HexByte ) ;
return Value;
}