Ejercicio 17: Música automática

Secuencias de notas y silencios en orden y duración aleatoria.

Novedades hardwareNovedades 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?.