Ejercicio 17: Música automática
Secuencias de notas y silencios en orden y duración aleatoria.
| Novedades hardware | Novedades software |
| | Generación de series de números pseudoaleatorios. |
| | Reinicio de variables para efectuar un reset por software. |
Requisitos:
- 4 LEDs, 4 resistencias de 220 ohmios
- 4 pulsadores, 4 resistencias de 1Kohmio.
- Un zumbador piezoeléctrico
Planteamiento: ¿Las máquinas pueden “componer” por nosotros?. Ësta nos ofrece una nueva melodía cada vez con sólo pulsar un botón
Presentación: Reinicio de variables para efectuar un reset por software.
Este ejercicio parece complicado, pero en realidad no lo es tanto.
Introducimos 2 procedimientos nuevos:
- void silencio( ) que es muy simple y sirve para parar y tener silencios entre notas.
- void resetea( ) que devuelve a las variables que se habían ido actualizando durante la ejecución del programa a sus valores iniciales.
De forma similar a como en el ejercicio anterior, ruleta musical aleatoria?, usábmos los números pseudoaleatorios para producir 4 posiciones al azar en la lista de LEDs, en este lo hacemos para producir, guardándolos en la variable tiempo, números al azar entre 0 y 9.
Los valores de tiempo los multiplicamos por 20 para tener 10 duraciones razonables posibles para las notas y el silencio.
La mayor novedad reside en que introducimos un reset por software.
Veamos cómo lo hacemos.
Nada más empezar el programa hay un if que se ejecuta sólo la primera vez, porque antes de que termine el primer ciclo completo de void loop( ), c habrá aumentado y no será 0.
Dentro del if está el mismo bucle while del ejercicio anterior.
¿Por qué no poner el while en el setup( ) y que se ejecute sólo una vez al comienzo?.
Porque entonces para volver a empezar tendríamos que resetear la placa y queremos resetear
por software, presionando un pulsador que no sea el de la placa.
Sólo queda especificar el botón de reset, que hemos colocado en el PIN 2 y dar un margen para levantar el dedo. Cuando se pulse vuelve a cumplirse la condición para que el if del comienzo nos de otra semilla, ini, y tengamos nuevos números y nueva melodía.
Variantes:
- Cambia las constantes en la función randomize y deja que tu oído te diga cuánto de aleatorios son tus nuevos números. Las series pseudoaleatorias tienen un ciclo a partir del cual se repiten. Si tu ciclo es corto, notarás que la melodía se repite.
VIDEO DEL EJERCICIO 17
VIDEO DEL EJERCICIO 17 (versión para el montaje del SIMON)
CODIGO FUENTE
Copyright (C) 2006 Juan Carlos Alonso de Mena
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation;
See the GNU General Public License for more details?
int zumb=10;
int cadenaLeds[]={6,7,8,9};
int cadenaPuls[]={2,3,4,5};
int notas[]={1915, 1700, 1519, 1432, 1275, 1136, 1014};
int tiempo=0;
int n=0;
int m=0;
int c=0; //variable que indicará si es el primer ciclo del void loop()
int ini=0; //variable para guardar la semilla del nº pseudoaleatorio
int psrnum=0; //nº pseudoaleatorio
int duracion=200; //duración de la nota
void setup (){
for(n=0;n<4;n++){
pinMode(cadenaLeds[n],OUTPUT);
pinMode(cadenaPuls,INPUT);
}
pinMode(zumb,OUTPUT);
}
void flash(){
for(n=0;n<4;n++){
digitalWrite(cadenaLeds[n],HIGH);
}
delay(200);
for(n=0;n<4;n++){
digitalWrite(cadenaLeds[n],LOW);
}
delay(200);
}
void nota(){
for(m=0;m<=duracion;m++){
digitalWrite(zumb,HIGH);
delayMicroseconds(notas[n]);
digitalWrite(zumb,LOW);
delayMicroseconds(notas[n]);
}
}
void silencio(){ //procedimiento para definir un silencio entre notas
delay(duracion);
}
randomize(int data){ //Función del generador de números pseudoaleatorios
return ((1664525*data)%1021); //al introducir un nº devuelve el resto de dividir
} //ese nº multiplicado por 1664525 entre 1021
void resetea() { //procedimiento que reinicia las variables:
c=0; //hace que se ejecute el primer if para producir la semilla del nº pseudoaleatorio
ini=0;
}
void loop(){
if (c==0){ //si es el primer ciclo
while(digitalRead(2)==LOW&&digitalRead(3)==LOW&&digitalRead(4)==LOW&&digitalRead(5)==LOW){ //mientras no se pulse nada:
flash(); //parpadean los LEDs
ini=ini+1; //y la variable ini aumenta
} //si se pulsa algún pulsador
flash();
psrnum= randomize(ini); // Obtenemos el primer nº pseudoaleatorio usando el valor de ini como argumento
} // de la función que lo produce
psrnum= randomize(psrnum); // Obtenemos sucesivos números psudoaleatorios a partir de los anteriores
tiempo=abs(psrnum)%10; //Obtenemos una duración de la nota ente 0 y 380
duracion=tiempo*20;
n=abs(psrnum)%8; //obtenemos la posición en la cadena de una nota (del 0 al 6)
if(n==7){ //o de un silencio, si sale el 7
silencio();
}
nota(); //suena la nota
c=c+1; //contamos que empieza otro ciclo
if(digitalRead(2)==HIGH){ //si pulsamos el pulsador conectado al PIN 2
delay(2000); //hacemos tiempo para levantar el dedo y que no lo lea en el while del comuienzo
resetea(); //volvemos a empezar
} //seguimos con la música porque c es distinto de 0 y en el siguiente
} // ciclo se salta el if del comienzo
Volver?
Copyright (c) 2006 Juan Carlos Alonso de Mena
Permission is granted to copy, distribute and/or modify this document under the terms of
the GNU Free Documentation License, Version 1.2 or any later version published by the
Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no
Back-Cover Texts. A copy of the license is included in the section entitled
GNU Free Documentation License?.