小組組員:411214209 吳宇瀚 411214217 歐邑衡
自製以七段顯示器為主的時鐘,並加上許多小功能,可以得知當下的溫度與體感溫度,蜂鳴器在整點的時候會發出多段的聲響來告知時間...
因為每次切換模式都要按按鈕,實在是太麻煩了。所以我們選擇用超音波感測器,這樣不需要觸碰也可以切換模式。
又加入LED燈在不同模式下,亮不同的顏色,可以在某些情況下更輕鬆地辨別當前的模式。
程式碼
#include <SimpleDHT.h>
#include <TM1637Display.h>
#include <DS1302.h>
// ------- 腳位定義 -------
#define DHT11_PIN 2
#define TM1_CLK 3
#define TM1_DIO 4
#define TM2_CLK 5
#define TM2_DIO 6
#define BUZZER_PIN 8
#define TRIG_PIN 12
#define ECHO_PIN 13
#define LED_TIME_PIN A0
#define LED_TEMP_PIN A1
// ------- RTC DS1302 腳位定義 -------
DS1302 rtc(11, 10, 9); // CE, IO, SCLK
// ------- 物件初始化 -------
SimpleDHT11 dht11(DHT11_PIN);
TM1637Display displayDate(TM1_CLK, TM1_DIO);
TM1637Display displayTime(TM2_CLK, TM2_DIO);
// ------- 切換狀態 -------
bool showTemperature = false;
unsigned long lastSwitchTime = 0;
const unsigned long displayTempDuration = 5000;
void setup() {
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_TIME_PIN, OUTPUT);
pinMode(LED_TEMP_PIN, OUTPUT);
displayDate.setBrightness(5);
displayTime.setBrightness(5);
rtc.halt(false);
rtc.writeProtect(false);
Serial.println("系統啟動完成");
Serial.println("若需設定時間,請輸入格式:T:HH,MM,SS,WEEKDAY,DAY,MONTH,YEAR");
}
void loop() {
// ------- 讀取超音波距離 -------
long duration, distance;
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH, 30000);
distance = (duration / 2) / 29.1; // 換算成公分
if (!showTemperature && distance >= 10 && distance <= 20) {
showTemperature = true;
lastSwitchTime = millis();
beep(1); // 提示音
Serial.print("手勢偵測!距離:"); Serial.print(distance); Serial.println("cm");
}
// ------- 顯示模式切換與顯示內容 -------
if (showTemperature) {
showTempAndFeelsLike();
updateLEDs(false); // 顯示溫度模式燈號
// 檢查是否超時
if (millis() - lastSwitchTime >= displayTempDuration) {
showTemperature = false;
}
} else {
showDateTime();
updateLEDs(true); // 顯示時間模式燈號
}
// 讀取 Serial 設定時間
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input.startsWith("T:")) {
setTimeFromSerial(input);
}
}
delay(200);
}
// ------- LED 狀態控制 -------
void updateLEDs(bool isTimeMode) {
if (isTimeMode) {
digitalWrite(LED_TIME_PIN, HIGH);
digitalWrite(LED_TEMP_PIN, LOW);
} else {
digitalWrite(LED_TIME_PIN, LOW);
digitalWrite(LED_TEMP_PIN, HIGH);
}
}
// ------- 顯示日期與時間 -------
void showDateTime() {
Time t = rtc.time();
int dateVal = t.mon * 100 + t.date;
int timeVal = t.hr * 100 + t.min;
displayDate.showNumberDecEx(dateVal, 0x40, true); // MM.DD
displayTime.showNumberDecEx(timeVal, 0x40, true); // HH:MM
}
// ------- 顯示溫度與體感溫度 -------
void showTempAndFeelsLike() {
byte temperature = 0;
byte humidity = 0;
if (dht11.read(&temperature, &humidity, NULL) != SimpleDHTErrSuccess) {
return;
}
int feelsLike = temperature - ((100 - humidity) / 5);
displayDate.showNumberDec(temperature, true);
displayTime.showNumberDec(feelsLike, true);
}
// ------- 蜂鳴器提示音 -------
void beep(int times) {
for (int i = 0; i < times; i++) {
tone(BUZZER_PIN, 1000);
delay(100);
noTone(BUZZER_PIN);
delay(100);
}
}
// ------- 解析序列字串並設定時間 -------
void setTimeFromSerial(String input) {
input.remove(0, 2); // 移除 "T:"
int hh, mm, ss, wd, dd, mo, yy;
int parsed = sscanf(input.c_str(), "%d,%d,%d,%d,%d,%d,%d", &hh, &mm, &ss, &wd, &dd, &mo, &yy);
if (parsed == 7) {
Time newTime(ss, mm, hh, wd, dd, mo, yy);
rtc.time(newTime);
Serial.println("時間已更新");
beep(2);
} else {
Serial.println("格式錯誤!請使用:T:HH,MM,SS,WEEKDAY,DAY,MONTH,YEAR");
beep(3);
}
}
所需材料:
Arduino Uno 1個 主控制器
DS3231 RTC模組 1個 日期時間來源
DHT11 感測器 1個 溫濕度量測
超聲波感測器 1個 測量距離用
七段顯示器 2個 顯示時間/溫度
LED燈 2個 顯示當前模式
蜂鳴器 1個 音效提示
電線、電阻、面包板等 若干 連接用
手靠近就可以切換成溫度和體感溫度,側面有透光可以看到當前的模式。(距離在10-20cm才會切換模式)
白光模式:左到右依序是溫度與體感溫度
橘光模式:左到右依序是日期與時間
心得:
吳宇瀚:可以自己做一些方便自己的懶人設備很快樂,可以提升自己又能交作業。
歐邑衡:這次將原本的自製時鐘進行升級,加入超音波感測與 LED,讓時鐘不只是顯示時間,還能與使用者互動。在實作過程中不斷調整距離判斷條件與程式流程,雖然過程繁瑣,但讓我更熟悉感測器與各元件之間的整合方式,也加深了對 Arduino 系統運作的理解。