/*
增加整點報時 (每分鐘一次)
增加伺服馬達當作秒針
因為伺服馬達只有 180 度
所以用了兩個,一個負責 180
為了美觀也隱藏了他們的電線
*/
#include <WiFi.h>
// 網路設定
const char* ssid = "Nokia 5.4"; // Nokia 5.4
const char* password = "12345678"; // 12345678
// 取得網路時間相關參數設定
const char* ntpServer = "time.google.com"; // Google - NTP Server
const long gmtOffset_sec = 28800; //台灣時區+8hr,28800=8*60*60
const int daylightOffset_sec = 0; //台灣無日光節約時間
// 七段顯示器腳位設定
#define pin_DIG1 14
#define pin_DIG2 23
#define pin_DIG3 22
#define pin_DIG4 19
#define pin_A 12
#define pin_B 21
#define pin_C 5
#define pin_D 2
#define pin_E 15
#define pin_F 13
#define pin_G 18
#define pin_DP 4
// 共陰極、共陽極設定
#define hardwareConfig 0 //COMMON_ANODE=1 COMMON_CATHODE=0
// 條件編譯
#if hardwareConfig==0
// 共陰極
#define digitOn 0
#define digitOff 1
#define light 1
#define dark 0
#else
// 共陽極
#define digitOn 1
#define digitOff 0
#define light 0
#define dark 1
#endif
int digitPins[4] = {pin_DIG1, pin_DIG2, pin_DIG3, pin_DIG4};
int segmentPins[8] = {pin_A, pin_B, pin_C, pin_D, pin_E, pin_F, pin_G, pin_DP};
bool num[10][8] {
{light,light,light,light,light,light,dark,dark},
{dark,light,light,dark,dark,dark,dark,dark},
{light,light,dark,light,light,dark,light,dark},
{light,light,light,light,dark,dark,light,dark},
{dark,light,light,dark,dark,light,light,dark},
{light,dark,light,light,dark,light,light,dark},
{light,dark,light,light,light,light,light,dark},
{light,light,light,dark,dark,dark,dark,dark},
{light,light,light,light,light,light,light,dark},
{light,light,light,light,dark,light,light,dark}
};
void displayNum(int pos,int number) {
for(int i=0; i<4; i++){
digitalWrite(digitPins[i], digitOff);
}
for(int i=0; i<8; i++){
digitalWrite(segmentPins[i], num[number][i]);
}
for (int i=0;i<4;i++) {
if (pos==i) digitalWrite(digitPins[i], digitOn);
else digitalWrite(digitPins[i], digitOff);
}
}
// Pulse Cycle 20ms,使用50Hz(每秒重複50次),週期為20ms的PWM訊號來控制馬達
// pulse width 0.5ms~2.4ms => 0 ~ 180
int pulseWidth_min = 500; // 0.5毫秒 = 500微秒
int pulseWidth_max = 2400;
double anglePulse = (pulseWidth_max-pulseWidth_min)/180; // 計算1度的脈寬值
void servoPulse(int ServoPin, double angle){
double pulseWidth = (angle*anglePulse) + pulseWidth_min; // 將角度轉為脈寬值
for(int i=0; i<1; i++){ // 50Hz(給伺服馬達足夠時間轉至指定角度即可)
digitalWrite(ServoPin, HIGH); // 將servoPin拉至高電位持續pulseWidth微秒
delayMicroseconds(pulseWidth);
digitalWrite(ServoPin, LOW); // 將servoPin拉至高電位持續pulseWidth微秒
delayMicroseconds(20000- pulseWidth);
}
}
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
//WiFi.begin(ssid, password); // 以STA(網路終端)模式連接到WiFi基地台
WiFi.begin("Wokwi-GUEST", "", 6); //wokwi提供的虛擬 WiFi 接入點
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.print("IP位址: ");
Serial.println(WiFi.localIP()); // 回傳分配到的IP位址
Serial.print("WiFi RSSI: ");
Serial.println(WiFi.RSSI()); // 回傳接收訊號強度(以 dBm 為單位)
// Init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
// 四位數七段顯示器初始化
for(int i=0; i<4; i++){
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], digitOff);
}
for(int i=0; i<8; i++){
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], dark);
}
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
pinMode(27, OUTPUT);
}
void loop() {
showTime();
}
float scantime=1.0/(16*4)*1000;
void showTime() {
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.print("Hour: "); //顯示英文 時 24小時制
Serial.println(timeinfo.tm_hour);
Serial.print("Minute: "); //顯示英文 分
Serial.println(timeinfo.tm_min);
Serial.print("Second: "); //顯示英文 秒
Serial.println(timeinfo.tm_sec);
displayNum(0,timeinfo.tm_min/10); delay(scantime);
displayNum(1,timeinfo.tm_min%10); delay(scantime);
displayNum(2,timeinfo.tm_sec/10); delay(scantime);
displayNum(3,timeinfo.tm_sec%10); delay(scantime);
if (timeinfo.tm_sec==0) tone(27, 262, 50);
servoPulse(26,timeinfo.tm_sec*6);
servoPulse(25,((timeinfo.tm_sec+30)%60)*6);
}
void printLocalTime(){
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.print("Hour: "); //顯示英文 時 24小時制
Serial.println(timeinfo.tm_hour);
Serial.print("Minute: "); //顯示英文 分
Serial.println(timeinfo.tm_min);
Serial.print("Second: "); //顯示英文 秒
Serial.println(timeinfo.tm_sec);
}