///////////////////////////////
// Definición de constantes //
/////////////////////////////
const uint8_t pinPiezo = 11; // Pin al que se conecta el piezoelectrico.
const uint8_t pinLed = 13; // Pin al que se conecta el led.
const uint8_t valorLedEncendido = HIGH; // Valor de la salida para encender el led.
const uint8_t valorTeclaPulsada = LOW; // Valor de lectura cuando se pulsa la tecla asociada a la nota.
const unsigned long tiempoAntiRebote = 25UL; // Tiempo en milisegundos para suprimir los rebotes. Siendo este el tiempo mínimo que sonará la nota y que durará el silencio. El UL es para indicar que se un entero largo sin signo.
// Estructura para asignar cada pin y la frecuencia de su nota.
struct PinNota {
uint8_t pin; // Pin al que está conectada la tecla (pulsador).
uint16_t frecuencia; // Frecuencia de la nota que ha de sonar.
};
// Pines asignados a las teclas y frecuencias de las notas.
const PinNota Teclas[] = {
{10, 262}, // Pin y frecuencia de la nota C.
{ 9, 294}, // Pin y frecuencia de la nota D.
{ 8, 330}, // Pin y frecuencia de la nota E.
{ 7, 349}, // Pin y frecuencia de la nota F.
{ 6, 392}, // Pin y frecuencia de la nota G.
{ 5, 440}, // Pin y frecuencia de la nota A.
{ 4, 493} // Pin y frecuencia de la nota B.
};
//////////////////////////////////////////////////////////////////
// Constantes calculadas a partir de las constantes anteriores //
////////////////////////////////////////////////////////////////
#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) // Macro para calcular el número total de elementos de un array.
const size_t cantidadTeclas = SIZEOF(Teclas); // Cantidad total de notas/teclas de las que se dispone.
const size_t noHayTeclaPulsada = cantidadTeclas; // Cuando no hay tecla pulsada el valor es el mismo que el número total de teclas.
const uint8_t valorLedApagado = !valorLedEncendido; // Valor de la salida para apagar el led (el contrario de valorLedEncendido).
/////////////////////////
// Variables globales //
///////////////////////
size_t teclaValida = noHayTeclaPulsada; // Para saber cual es la tecla que ha de sonar.
unsigned long instanteDetectadoNuevaTecla = 0UL; // Guarda en que momento se detectó la nueva tecla pulsada.
void setup()
{
// Bucle para inicializar como entrada y con resistencia PULL UP todos los pines de las teclas.
for (size_t i = 0; i < cantidadTeclas; i++) {
pinMode(Teclas[i].pin, INPUT_PULLUP);
}
pinMode(pinLed, OUTPUT); // Configuramos como salida el pin del led.
digitalWrite(pinLed, valorLedApagado); // Nos aseguramos de que el led esté apagado.
noTone(pinPiezo); // Nos aseguramos que no se está emitiendo ningún sonido.
}
void loop()
{
unsigned long instanteActual = millis(); // Obtenemos el instante actual.
if ((instanteActual - instanteDetectadoNuevaTecla) >= tiempoAntiRebote) { // Vemos si ha pasado tiempo suficiente desde que se detectó una tecla pulsada. No se hará nada mientras no haya pasado ese tiempo.
size_t teclaDetectada = 0; // Para averiguar qué tecla está pulsada en este momento. Es importante no declarar esta variable dento del siguiente for para que su valor sea accesible después del for.
for ( ; teclaDetectada < cantidadTeclas; teclaDetectada++) { // Téngase en cuenta que no se define el primer componente del for porque se ha definido justo en la línea anterior. Este bulcle verifica una por una las teclas buscando la primera que se encuentre pulsada.
if (digitalRead(Teclas[teclaDetectada].pin) == valorTeclaPulsada) { // Si se detecta una tecla pulsada...
break; // Salimos del bucle sin haber llegado al final.
}
}
if (teclaValida != teclaDetectada) { // Si la tecla detectada es distinta a la tecla validada por última vez...
teclaValida = teclaDetectada; // La tecla válida pasa a ser la tecla detectada.
instanteDetectadoNuevaTecla = instanteActual; // Guardamos este tiempo para esperar y evitar los rebotes.
if (teclaValida == noHayTeclaPulsada) { // Si no hay tecla válida pulsada.
noTone(pinPiezo); // Apagamos el sonido.
digitalWrite(pinLed, valorLedApagado); // Apagamos el led.
}
else { // Hay una nueva tecla válida pulsada.
tone(pinPiezo, Teclas[teclaValida].frecuencia); // Hacemos sonar el tono asignado a la tecla pulsada.
digitalWrite(pinLed, valorLedEncendido); // Encendemos el led.
}
}
}
}