ARD11 – Sonido

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

Nuestra plaquita Arduino también puede generar frecuencias audibles, que podemos reproducir mediante un transductor, que recibe una señal de cierta frecuencia y la convierte en sonido. Lo ideal es usar un altavoz de mediana calidad pero, para experimentar, de momento emplearemos un simple zumbador. Se venden en cualquier tienda de electrónica y son muy baratos. No nos proporcionará una reproducción musical de alta calidad, pero nos permitirá aprender a generar sonidos. Ya lo sustituiríamos, si fuera necesario, por un altavoz mejor. En la figura 11.1 vemos un zumbador como el que usaremos en este montaje.

Figura 11.1. Un zumbador simple (de los baratitos).

Figura 11.1. Un zumbador simple (de los baratitos).

La mayoría de estos dispositivos carecen de polaridad. Es lógico, puesto que están concebidos para funcionar tanto con señales pulsantes como alternas. Sin embargo, en el mercado se encuentran algunos zumbadores especiales, concebidos para fines muy concretos, que SÍ tienen polaridad (debido a que incorporan un amplificador propio). Si los conectaras al revés, directamente no funcionarían e, incluso, podrían dañarse, o dañar el circuito. No obstante, como decimos, la norma general es que no tengan polaridad y este será el que usemos nosotros.

EL CIRCUITO

El circuito que vamos a montar constará de siete pulsadores, cada uno de los cuales hará que el zumbador reproduzca una nota musical, del DO al SI. Para ello vamos a necesitar conocer las frecuencias en herzios de las siete notas musicales. Evidentemente, estas frecuencias varían de una escala a otra. Un piano, o un teclado electrónico profesional, por ejemplo, tienen varias escalas, de modo que el DO de una escala suena más grave que el DO de la siguiente. En instrumentos musicales profesionales se emplean hasta ocho escalas. Nosotros vamos a usar las frecuencias de las notas de una escala media, que son las siguientes:

  • DO: 261,626 Hz
  • RE: 293,665 Hz
  • MI: 329,628 Hz
  • FA: 349,228 Hz
  • SOL: 391,995 Hz
  • LA: 440 Hz
  • SI: 493,883 Hz

El esquema electrónico del circuito, junto al montaje físico, aparecen en las figuras 11.2 y 11.3.

Figura 11.2. El esquema teórico de este montaje.

Figura 11.2. El esquema teórico de este montaje.

Figura 11.3. El montaje cableado que corresponde a este artículo.

Figura 11.3. El montaje cableado que corresponde a este artículo.

Como ves, el circuito es muy sencillo. Cada pulsador manda señal a un pin de la placa Arduino, y será el sketch el que deba discernir que pulsador está activado y enviar la nota adecuada al zumbador.

EL SKECTH

En este sketch vamos a introducir dos conceptos nuevos: el uso de matrices en el lenguaje Arduino y la generación de tonos de una determinada frecuencia. Como siempre, veamos primero el listado completo, para tener una idea general:

Empezamos definiendo una matriz con las frecuencias de las notas que vamos a usar. Una matriz es un conjunto de valores agrupados bajo un mismo nombre. El acceso a cada uno de los valores se hará a través de un índice numérico, que empieza a contar desde 0, no desde 1. Si estás familiarizado con las matrices en otros lenguajes, como JavaScript, verás que la mecánica es muy similar.

Para declarar una matriz debemos empezar, como en el caso de las variables normales, indicando el tipo de datos que va a tener. En este caso son datos de tipo integer. Aunque las notas musicales tienen frecuencias con decimales (lo que serían datos de tipo float), Arduino solo puede reproducir frecuencias expresadas como números enteros, por lo que cada nota la representaremos como el valor entero más aproximado al real. Para definir una matriz, indicamos su tipo, un nombre seguido de unos corchetes sin nada en medio (lo que le indica a Arduino que lo que declaramos es una matriz, no una variable) y, después del operador de asignación, la colección de elementos que va a contener la matriz, separados por comas, y encerrada entre llaves. Eso es, exactamente, lo que hacemos aquí:

Así, para acceder, por ejemplo, a la frecuencia de la nota DO, que es la primera de la matriz notas, lo haríamos así:

Recuerda que, en Arduino (cómo en todos los lenguajes de programación modernos), los índices de la matriz se empiezan a contar desde 0. Así, en una matriz como la que declaramos en la primera línea, que tiene siete elementos, estos irán indexados de 0 a 6.

En la declaración de una matriz también se puede incluir el número total de elementos que va a tener, como vemos a continuación:

Las matrices pueden declararse para todo tipo de datos, con la limitación de que todos los valores de la matriz deberán ser del mismo tipo. Así si declaramos una matriz de tipo int, no podremos asignarle un valor de tipo float, o string. Date cuenta que en la declaración cuando expresamos int, se refiere al tipo de la matriz, lo que, implícitamente, indica que todos los valores que contenga serán de ese tipo.

Después de declarar una variable para referirnos al pin donde conectaremos el zumbador, y otra para usarla como índice de las matrices, pasamos a la sección setup del sketch. Lo primero que encontramos es el inicio de la comunicación serie con la consola de Arduino, a 9600 baudios, como ya es habitual, y el establecimiento del pin del zumbador como de salida de señal. Después vemos un bucle que usamos para definir como de entrada los pines que están conectados a los pulsadores, así:

Aquí vemos como podemos referirnos a un elemento de una matriz, tal como mencionábamos antes, especificando el nombre de la matriz y, entre corchetes, el índice del elemento al que queremos referirnos. El bucle hace que la variable de control (llamada indice) itere desde el valor inicial de 0 hasta el límite de menor que 7 (es decir, el límite será 6). Así pues, en la primera iteración la única instrucción que forma el cuerpo del bucle equivale a lo siguiente:

O lo que es lo mismo:

En la siguiente iteración, la instrucción equivale a:

o lo que es lo mismo:

Y así sucesivamente, de modo que, al final, los pines del 2 al 8 quedan definidos como de entrada.

Dentro de la sección loop, encontramos otro bucle, basado en la variable de control índice, que va a recorrer las matrices en la siguiente forma:

Cuando la variable de control asume un valor (inicialmente, 0), se comprueba si ese pin tiene, en ese momento, un valor HIGH, mediante la función digitalRead, que ya conocemos, lo que indicaría que el pulsador correspondiente está pulsado. Si es así, se ejecuta la función tone(). Esta recibe dos parámetros: el primero indica el pin por el que tienen que mandar un tono, y el segundo indica la frecuencia de dicho tono. Como ves, el pin está representado por la variable zumbador, que vale 11, que es el pin al que tenemos conectado el sumbador, y la frecuencia es la especificada en el elemento 0 de la matriz notas. Si la variable de control fuera 1, y se detectara esta tecla como pulsada, la frecuencia sería la del elemento 1 de la matriz notas, y así, sucesivamente.

Cuando se encuentra un pulsador activado, se envía la frecuencia correspondiente, mediante la función tone() al zumbador, y se interrumpe el bucle for, es decir, ya no se siguen comprobando el resto de los pulsadores. Acto seguido, la sección loop, que ya no tiene más código, se reinicia, con lo que el bucle for vuelve a empezar a comprobar, desde 0.

Si no se ha encontrado ninguno de los pulsadores con el valor HIGH (es decir, no hay ninguno pulsado) se ejecuta la alternativa del condicional, que llama a la función noTone(). Esta recibe un único argumento, que es el pin afectado, y lo que hace es detener cualquier tono que se esté enviando en ese momento a dicho pin.

La función tone() envia, al pin especificado como primer argumento, la frecuencia especificada como segundo argumento. Una vez que se ejecuta, dicha frecuencia ya se está enviando permanentemente al pin de salida, hasta que ejecutemos la función noTone(), para que deje de enviarse.

Como alternativa, la función tone() admite un tercer argumento opcional que es el tiempo en milisegundos que tiene que durar la nota. En ese caso, la nota se detendrá una vez transcurrido el tiempo establecido, sin necesidad de usar la función noTone().

     

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *