#include <Servo.h>
int servoPin = 4;
int trigPin = 11;
int echoPin = 12;
long duration, cm;
int LED = 8;
int LEDR = 9;
int LEDG = 5;
int LEDB = 6;
int redVal = 255;
int greenVal = 0;
int blueVal = 0;
Servo Servo1;
int Buzzer = 7;
#ifndef MUSIC_H
#define MUSIC_H
// Define the pitches
#define G4 392
#define F4 349
#define E4 330
#define D4 294
#define C4 262
#define A4 440
#define C5 523
// Define the tempo values
#define T4 1.0
#define T8 0.5
#define T2 2.0
#define T4d 1.5 // dotted quarter note
// Define the songs using pitch and tempo constants
const int song1_pitch[] = {
G4, E4, E4, 0, F4, D4, D4, 0, C4, D4, E4, F4, G4, G4, G4, 0
};
const float song1_tempo[] = {
T4, T4, T4, T4, T4, T4, T4, T4, T4, T4, T4, T4, T4, T4, T4, T4
};
const int song2_pitch[] = {
C4, C4, D4, E4, E4, D4, C4, D4, E4, C4, 0, E4, E4, F4, G4, G4, F4, E4, F4, G4, E4, 0
};
const float song2_tempo[] = {
T4, T8, T8, T4, T4, T8, T8, T8, T8, T4, T4, T4, T8, T8, T4, T4, T8, T8, T8, T8, T4, T4
};
const int song3_pitch[] = {
C4, C4, D4, F4, G4, F4, G4, A4, 0, C5, A4, A4, G4, F4, G4, 0, 0
};
const float song3_tempo[] = {
T4d, T8, T4, T4, T4, T8, T8, T4, T4, T4d, T8, T8, T8, T4, T2, T4, T4
};
#endif
#define ButtonPin 10 //按鈕開關的接腳
#define SegmentPinStart 2 //七段顯示器開始的接腳
// 七段顯示器的位模式,每個元素表示一個數字的位狀態(abcdefg, dp)
const byte seg7_digit[6][8] = {
{0, 0, 0, 0, 0, 0, 1, 1}, // 0.
{1, 0, 0, 1, 1, 1, 1, 1}, // 1.
{0, 0, 1, 0, 0, 1, 0, 1}, // 2.
{0, 0, 0, 0, 1, 1, 0, 1}, // 3.
{1, 0, 0, 1, 1, 0, 0, 1}, // 4.
{0, 1, 0, 0, 1, 0, 0, 1} // 5.
};
void setup() {
Servo1.attach(servoPin);
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
pinMode(LED, OUTPUT);
pinMode(Buzzer, OUTPUT);
pinMode(ButtonPin, INPUT_PULLUP); //設置按鈕接腳為輸入,啟用內部上拉電阻
for (int i = SegmentPinStart; i < SegmentPinStart + 8; i++) {
pinMode(i, OUTPUT); //設置七段顯示器的接腳為輸出
}
}
void loop() {
measureDistance();
handleDistanceLogic();
}
void measureDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
cm = (duration / 2) / 29.1;
Serial.print(cm);
Serial.println(" cm");
}
void handleDistanceLogic() {
static int cycleCount = 0; // To track the number of cycles
static int num = 0; // To store the displayed number
if (cm >= 5 && cm <= 30) {
if (cycleCount < 5) { // Limit to 5 cycles
digitalWrite(LED, HIGH);
Servo1.write(90);
delay(3000);
handleLEDEffects();
handleBuzzer();
showDigit(0); // Display "0." on the 7-segment display
waitForButtonPress(num); // Wait for button press to increment number
showDigit(num); // Display number on the 7-segment display
delay(130);
cycleCount++; // Increment the cycle count
} else {
digitalWrite(LED, LOW);
Servo1.write(0);
delay(1500);
}
} else if (cm > 30) {
digitalWrite(LED, LOW);
Servo1.write(0);
delay(1500);
}
}
void handleLEDEffects() {
if (cm > 30) return; // 如果距離大於30cm,不會呼叫handleLEDEffects
int delayTime = getLEDDuration();
for (byte i = 0; i < 255; i++) {
redVal--;
greenVal++;
analogWrite(LEDR, redVal);
analogWrite(LEDG, greenVal);
delay(delayTime);
}
for (byte i = 0; i < 255; i++) {
greenVal--;
blueVal++;
analogWrite(LEDG, greenVal);
analogWrite(LEDB, blueVal);
delay(delayTime);
}
for (byte i = 0; i < 255; i++) {
blueVal--;
redVal++;
analogWrite(LEDB, blueVal);
analogWrite(LEDR, redVal);
delay(delayTime);
}
}
int getLEDDuration() {
if (cm >= 5 && cm <= 10) return 1;
else if (cm > 10 && cm <= 20) return 3;
else if (cm > 20 && cm <= 30) return 5;
return 5; // Default
}
void handleBuzzer() {
showDigit(0); // Display "0." on the 7-segment display
if (cm >= 5 && cm <= 10) playSong(0);
else if (cm > 10 && cm <= 20) playSong(1);
else if (cm > 20 && cm <= 30) playSong(2);
}
void playSong(int songIndex) {
const int* pitch_ptr[] = {song1_pitch, song2_pitch, song3_pitch};
const float* tempo_ptr[] = {song1_tempo, song2_tempo, song3_tempo};
int speed[3] = {140, 80, 60};
int T1time = 4 * 60000 / speed[songIndex];
for (int i = 0; pitch_ptr[songIndex][i] != 0; i++) {
int pitch = pitch_ptr[songIndex][i];
float duration = T1time * tempo_ptr[songIndex][i];
tone(Buzzer, pitch, duration / 2);
delay(duration / 2);
}
}
void waitForButtonPress(int &num) {
while (digitalRead(ButtonPin) == HIGH); // Wait for button press
delay(50); // Debounce delay
if (digitalRead(ButtonPin) == LOW) { // Confirm button press
num = (num + 1) % 6; // Increment number within 0 to 5
delay(200); // Avoid multiple counts for one press
}
}
void showDigit(int digit) {
for (int i = 0; i < 8; i++) {
digitalWrite(SegmentPinStart + i, seg7_digit[digit][i]); //根據位模式設置七段顯示器的接腳
}
}