#include <Servo.h> // Incluye la biblioteca Servo
// Define los pines del botón, del servo, del sensor de proximidad y del buzzer
const int buttonPin = 2;
const int servoPin = 9;
const int trigPin = 10;
const int echoPin = 11;
const int buzzerPin = 12;
Servo myServo; // Crea un objeto Servo
// Variables para el estado del botón y del servo
bool buttonState = LOW;
bool lastButtonState = LOW;
bool servoMoved = false;
bool longPressActive = false;
bool buttonReleased = false; // Nuevo indicador para saber si el botón se ha soltado
unsigned long startTime;
unsigned long lastButtonPressTime = 0;
unsigned long noObjectStartTime = 0; // Nuevo temporizador para contar el tiempo sin objeto cercano
const unsigned long doublePressThresholdMax = 500; // Tiempo máximo entre pulsaciones para considerar una doble pulsación (en ms)
const unsigned long doublePressThresholdMin = 150; // Tiempo mínimo entre pulsaciones para considerar una doble pulsación (en ms)
const unsigned long longPressThreshold = 2000; // Tiempo mínimo para considerar una pulsación larga (en ms)
// Frecuencias de las notas en Hz
const int Sol = 392;
const int Re = 587;
const int Do = 523;
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Configura el pin del botón como entrada con resistencia pull-up interna
pinMode(trigPin, OUTPUT); // Configura el pin trig del sensor de proximidad como salida
pinMode(echoPin, INPUT); // Configura el pin echo del sensor de proximidad como entrada
pinMode(buzzerPin, OUTPUT); // Configura el pin del buzzer como salida
myServo.attach(servoPin); // Adjunta el objeto Servo al pin del servo
myServo.write(0); // Posición inicial del servo
Serial.begin(9600); // Inicializa la comunicación serial para depuración
}
void loop() {
buttonState = digitalRead(buttonPin); // Lee el estado del botón
// Detecta cambio de estado del botón
if (buttonState != lastButtonState) {
if (buttonState == LOW) { // Si el botón está presionado (LOW por INPUT_PULLUP)
unsigned long currentTime = millis(); // Obtiene el tiempo actual
if (currentTime - lastButtonPressTime < doublePressThresholdMax &&
currentTime - lastButtonPressTime > doublePressThresholdMin &&
servoMoved) {
// Doble pulsación detectada y el servo está en 180º
playDoublePressMelody(); // Reproduce "Do Sol"
myServo.write(0); // Mueve el servo a la posición inicial
servoMoved = false; // Permite que el botón lo mueva de nuevo al máximo
longPressActive = false; // Desactiva la pulsación larga
} else if (!servoMoved) {
// Primera pulsación
playMelody(); // Reproduce la melodía
myServo.write(180); // Mueve el servo al máximo
servoMoved = true; // Indica que el servo ya se ha movido
startTime = millis(); // Registra el tiempo en el que el servo se mueve al máximo
noObjectStartTime = 0; // Reinicia el temporizador de objeto cercano
buttonReleased = false; // Resetea el indicador de que el botón se ha soltado
}
lastButtonPressTime = currentTime; // Actualiza el tiempo de la última pulsación
} else if (buttonState == HIGH) {
buttonReleased = true; // Indica que el botón se ha soltado
}
delay(50); // Desactivación del rebote del botón
}
// Detecta pulsación larga
if (servoMoved && buttonReleased && buttonState == LOW && millis() - lastButtonPressTime >= longPressThreshold) {
longPressActive = true; // Activa la pulsación larga
playLongPressMelody(); // Reproduce "Re Re"
}
lastButtonState = buttonState; // Actualiza el último estado del botón
// Control del servo según la proximidad y el tiempo sin objeto cercano
if (servoMoved && !longPressActive) {
if (isObjectDetected()) {
noObjectStartTime = 0; // Reinicia el temporizador si hay un objeto cercano
} else {
if (noObjectStartTime == 0) {
noObjectStartTime = millis(); // Inicia el temporizador si no hay objeto cercano
} else if (millis() - noObjectStartTime >= 5000) { // Comprueba si han pasado 5 segundos sin objeto cercano
giveWarning(); // Da un aviso antes de mover el servo a la posición inicial
myServo.write(0); // Mueve el servo a la posición inicial
servoMoved = false; // Permite que el botón lo mueva de nuevo al máximo
}
}
}
}
// Función para dar un aviso antes de mover el servo a la posición inicial
void giveWarning() {
myServo.write(150); // Mueve el servo a 150º
delay(250); // Espera 0.25 segundos
myServo.write(180); // Mueve el servo de vuelta a 180º
delay(1300); // Espera 1.3 segundos antes de moverse a 0º
}
// Función para comprobar si hay un objeto cercano usando el HC-SR04
bool isObjectDetected() {
long duration;
int distance;
digitalWrite(trigPin, LOW);
delayMicroseconds(2); // Breve retardo
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // Envío del pulso de 10 microsegundos
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH); // Lee la duración del pulso de retorno
distance = duration / 58.2; // Calcula la distancia en cm
Serial.print("Distance: ");
Serial.println(distance); // Imprime la distancia por el puerto serial
// Ajusta este valor según la distancia que consideres "cercana"
if (distance < 100) { // Por ejemplo, 100 cm
return true;
} else {
return false;
}
}
// Función para reproducir la melodía
void playMelody() {
tone(buzzerPin, Sol, 50); // Toca la nota Sol por 50 ms
delay(100); // Espera 100 ms
tone(buzzerPin, Sol, 50); // Repite la nota Sol
delay(100);
tone(buzzerPin, Sol, 50); // Repite la nota Sol
delay(200);
tone(buzzerPin, Sol, 100); // Toca la nota Sol por 100 ms
delay(200);
tone(buzzerPin, Re, 50); // Toca la nota Re por 50 ms
delay(200);
tone(buzzerPin, Do, 100); // Toca la nota Do por 100 ms
delay(200);
noTone(buzzerPin); // Apaga el buzzer
}
// Función para reproducir "Do Sol" en doble pulsación
void playDoublePressMelody() {
tone(buzzerPin, Do, 50); // Toca la nota Do por 50 ms
delay(100);
tone(buzzerPin, Sol, 50); // Toca la nota Sol por 50 ms
delay(100);
noTone(buzzerPin); // Apaga el buzzer
}
// Función para reproducir "Re Re" en pulsación larga
void playLongPressMelody() {
tone(buzzerPin, Re, 50); // Toca la nota Re por 50 ms
delay(200);
tone(buzzerPin, Re, 50); // Repite la nota Re por 50 ms
delay(200);
tone(buzzerPin, Re, 50); // Repite la nota Re por 50 ms
delay(1000);
noTone(buzzerPin); // Apaga el buzzer
}