#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
// 핀 설정
const int ledPin = 2;
const int buzzerPin = 3;
const int servoPin = 7;
const int micPin = A0;
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myServo;
// 부저 멜로디 설정
const int melody[] = { 440, 349, 523, 440, 523, 659, 698, 523, 440 };
const int durations[] = { 300, 200, 150, 300, 300, 300, 200, 150, 350 };
const int melodyLen = sizeof(melody) / sizeof(int);
int noteIndex = 0;
bool notePlaying = false;
unsigned long noteStartMs = 0;
int noteDurationMs = 0;
const int noteGapMs = 40;
int melodyRepeatCount = 0;
const int maxRepeat = 2;
bool currentState = false;
bool printed = false;
// 🎤 MAX4466 마이크 관련
const int threshold = 580;
int loudCount = 0;
unsigned long lastLoudTime = 0;
const unsigned long loudTimeout = 1000; // 1초 내 연속 감지 허용
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
myServo.attach(servoPin);
myServo.write(90); // 초기 위치
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("System Ready");
Serial.begin(115200);
}
void loop() {
readSerialCommand(); // 라즈베리 명령 처리
// 상태 제어
if (currentState) { // 불안 모드
digitalWrite(ledPin, HIGH);
showAlertLCD();
if (melodyRepeatCount < maxRepeat) {
updateMelody();
} else {
stopBuzzer();
}
} else { // 평상시
digitalWrite(ledPin, LOW);
showIdleLCD();
stopBuzzer();
}
// 🎤 마이크 입력 감지
int micValue = analogRead(micPin);
Serial.println(micValue);
unsigned long now = millis();
if (micValue > threshold) {
if (now - lastLoudTime <= loudTimeout) {
loudCount++;
} else {
loudCount = 1;
}
lastLoudTime = now;
}
// 3회 이상 감지 시 라즈베리로 "1" 전송
if (loudCount >= 3) {
Serial.println("1");
loudCount = 0;
}
delay(20);
}
// 🧠 시리얼 명령 처리 함수
void readSerialCommand() {
while (Serial.available()) {
char ch = Serial.read();
if (ch == '1') {
// 불안 상태 시작
currentState = true;
melodyRepeatCount = 0;
noteIndex = 0;
} else if (ch == '0') {
// 평상시 상태 복귀
currentState = false;
} else if (ch == '2') {
// 라즈베리에서 '2' 명령 받았을 때
// ① 서보 작동
rotateServo();
// ② 불안 상태 해제 및 평상시로 복귀
currentState = false;
stopBuzzer();
digitalWrite(ledPin, LOW);
showIdleLCD();
}
}
}
// LCD 출력 함수
void showAlertLCD() {
if (!printed) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Dog is anxious");
printed = true;
}
}
void showIdleLCD() {
if (printed) {
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("* ^ ^ *");
printed = false;
}
}
// 부저 멜로디 재생
void updateMelody() {
unsigned long now = millis();
if (!notePlaying) {
tone(buzzerPin, melody[noteIndex]);
noteDurationMs = durations[noteIndex];
noteStartMs = now;
notePlaying = true;
} else if (now - noteStartMs >= noteDurationMs) {
noTone(buzzerPin);
notePlaying = false;
noteIndex++;
if (noteIndex >= melodyLen) {
noteIndex = 0;
melodyRepeatCount++;
}
delay(noteGapMs);
}
}
void stopBuzzer() {
noTone(buzzerPin);
notePlaying = false;
noteIndex = 0;
}
// 서보 동작
void rotateServo() {
myServo.write(0);
delay(500);
myServo.write(90);
}