(EN) LedTree. LED CHRISTMAS TREE. Study about sound and leds multiplexing with Arduino.
(FR) ArbreLed. ARBRE DE NOËL AVEC LEDS. Étude de multiplexage de leds et son avec Arduino.
(PT) ÁrvoreLed. ÁRVORE DE NATAL COM LEDS. Estudo de multiplexagem de led e som com Arduino.
------------------------------------------------------------------------------------------------------------------------------------ PARA REPASAR E INFORMARSE: Para este montaje usaré un Arduino Uno. Hay un montón de información en la web. Aquí un enlace a su página oficial.
Básicamente se trata de manejar leds, así que es interesante tener claro como se polariza un led. En este blog ya se ha tratado el tema.
Mi idea ha sido con transistores como conmutadores. Así que es interesante tener una idea simple de como funcionan en corte y en saturación. Hay mucha información en la web. Aquí hay un ejemplo que me ha gustado. Más concretamente uso un array de transistores, el integrado ULN2003.
PLANTEAMIENTO INICIAL Y MOTIVACIÓN DEL PROYECTO.
Con la proximidad de la navidad, allá por noviembre del 2014, comentamos entre amiguetes makers, el montar un árbol de navidad con arduino. En principio, la idea de montar unos leds sobre una plaquita pcb en forma de pino, y encender y apagar, me pareció algo demasiado sencillo. Pero al poco tiempo caí en la idea de algo interesante:
Arduino tiene un número relativamente limitado de entradas y salidas (yo tengo un Arduino Uno; 14 digitales y 6 analógicas). Estas no pueden soportar más de 40mA cada una, y mejor no pasar de 20mA. Y en total no más de 300mA, todas juntas. Pensemos, intentando no pasar de 150 o 200mA, por si acaso.
Así que, imposible usar directamente más de 20 leds, y esta cantidad, con mucho cuidado.
¿Cómo hacer, entonces, para manejar más? Pues montarlos en una matriz, y no encenderlos todos al mismo tiempo. Una matriz que habrá que controlar continuamente filas y columnas y que si además sincronizamos con una musiquilla se convierte (para mi nivel al menos) en un ejercicio interesante de sincronismo y programación.
Además el propósito va a ser diseñar y montar yo el circuito. Activar filas y columnas parece una cosa factible con transistores...
MATRIZ. FILAS Y COLUMNAS.Así que, imposible usar directamente más de 20 leds, y esta cantidad, con mucho cuidado.
¿Cómo hacer, entonces, para manejar más? Pues montarlos en una matriz, y no encenderlos todos al mismo tiempo. Una matriz que habrá que controlar continuamente filas y columnas y que si además sincronizamos con una musiquilla se convierte (para mi nivel al menos) en un ejercicio interesante de sincronismo y programación.
Además el propósito va a ser diseñar y montar yo el circuito. Activar filas y columnas parece una cosa factible con transistores...
En una red o matriz de leds podemos conectar una serie de filas a unas salidas del arduino, y una serie de columnas a otras. Si ponemos a nivel alto determinada salida alimentaremos positivamente toda una linea de leds (en nuestro dibujito las filas). De esos leds se encederán los que tengan su cátodo también a negativo o nivel bajo (en nuestro caso, la columna apropiada). Solo debemos cuidarnos de no activar más de una linea de leds al mismo tiempo para que no interfieran unas lineas con otras.
Graficamente se entiende mejor la activación o no de los leds en una matriz |
En nuestro ejemplo (con lógica positiva), si activáramos a nivel alto dos filas, el activar una columna a nivel bajo encendería los dos leds de las diferentes filas. El truco es activar solo una fila, y las columnas apropiadas un instante y luego hacer lo mismo con otra fila. Todo lo suficientemente rápido como para que nuestro ojo no se de cuenta.
LIMITACIÓN DE LA CORRIENTE. Y USO DE TRANSISTORES.
Cada led debería tener una resistencia que limitase su corriente para que no se queme.
Y para no consumir demasiada corriente de las salidas de nuestro arduino, la primera idea es usar transistores que aislen las salidas del arduino respecto de la intensidad que consuman nuestros leds.
Así mi primera idea ha sido polarizar un par de transistores, que según estén sus bases, a nivel alto conducirán, o a nivel bajo estarán en corte.
El transistor en corte nos aisla de masa y conecta con tensión a través de la resistencia. En saturacíón conduce y nos conecta directamene a masa. |
Una vez, así presentado el esquema, es fácil caer en la cuenta de que podemos sacar la resistencia inferior y dejar el transistor conectado a colector abierto. Sólo nos interesa que el cátodo del diodo se conecte a masa o no.
Y de esta forma, la única resistencia que queda será la que nos limita la corriente por el diodo, de forma elemental.
Cuando el led conduce e ilumina, el transistor superior "aisla" la masa, y el inferior la "une" por lo que el cirucuito se convierte en un sencillo "resistencia en serie con led". |
EL INTEGRADO ULN2003A PARA NUESTRO MONTAJE.
El integrado ULN2003A es un conjunto de resistencias, transistores y diodos. Se compone de siete circuitos iguales que en las hojas de características suelen venir representados como una puerta lógica NOT. Es básicamente un adaptador de potencia. Por la entrada nosotros introducimos una señal lógica TTL. Unas resistencias polarizan y atacan la base de un transistor tipo darlington (dos conectados para aumentar potencia) y esto nos da una salida negada (a masa si la entrada está a nivel alto, a colector de los transistores si la entrada es a nivel bajo)por la que puede pasar mucha más intensidad que por nuestros pines del arduino. Para simplificar y pensar electrónicamente tenemos nuestro transistor básico (pudiéndonos despreocupar de las adaptaciones de la señal ttl de nuestro arduino): un 0 o nivel bajo de nuestro arduino, nos pone a "nuestro" transistor en corte (o abierto colector-emisor) y por tanto aislado de masa; un 1 o nivel alto provocará a "nuestro" transistor a saturación (o cerrado colector-emisor) y por tanto conectado a masa.
También existen unos diodos, con un contacto en común, que no usaremos aquí, pensados para poner con selenoides, para cortocircuitar los transitorios de desconexión de las bobinas, generalmente de relés. Aquí no hay de eso, así que no los usamos.
PRUEBAS Y DISEÑO.
Pues con estas ideas hacemos unas pruebas, para ver que nuestras ideas eléctricas funcionan. Y corregir errores y decisiones iniciales como la patilla común de los leds RGB, valores de las resistencias, etc.
LLevando a la práctica la teoría de nuestro PinoLed. |
Y todas las conclusiones se han conviertido en el siguiente esquema definitivo
Aquí está como ha quedado el esquema definitivo de mi PinoLed. |
VALOR DE LAS RESISTENCIAS.
La corriente que circulará por la carga más importante (leds) la "recojo" por Vin y no por 5V por dos razones: para liberar de trabajo al regulador de tensión; y pensando en poder conectar con baterías diferentes y hacer que los leds alumbren más o menos.
Pensando, además, que hay leds de diferentes colores y tipos (finalmente he optado también por jugar con un par de leds RGB), y que éstos tienen diferentes umbrales de tensión a partir de los cuales conducen, la elección del valor de la resistencia limitadora de corriente ha sido un poco a prueba y error.
Originalmente, en el prototipo sobre protoboard he empezado con resistencias de 1K. Pensaba en una de las opciones menos favorables: 20v de entrada (Vin) y led rojo (tensión umbral aproximada 1,8v según pruebas propias) y curándome un poco en salud con la corriente (I diodo máx.<20ma aria-haspopup="true" class="goog-spellcheck-word" data-blogger-="" id=":1b.167" role="menuitem" span="" style="background: yellow;" tabindex="-1">escaped20ma>
R=(Vin-Vd)/Idmax=(20-1,8)/0,020=910 ohmios.
Una vez, en fase de programación del Arduino, al multiplexar, el brillo de los leds baja notablemente porque la tensión sólo se aplica a cada linea 1/6 parte del tiempo. Por lógica he bajado el valor de las resistencias 1/6 parte (1000/6=166,66). Por seguridad mejor 180 que 150 ohmios.DETALLES Y RESULTADOS DE LA CONSTRUCCIÓN.
Con la construcción no quería gastar demasiado dinero. Se trataba de un ejercicio. Así que he optado por cartulina y leds pequeños de 3mm. La circuitería está montada sobre un escudo casero del que ya he hablado en otra entrada. Hubiera sido más vistoso y luminoso usar leds grandes. Seguro que hay ideas mucho más trabajadas, pero esta es la mía...
En mi montaje, en el lugar del potenciometro para el volumen he puesto un puente, optando así por la potencia máxima, pero esto puede ser molesto para algunas personas así que indico la posibilidad de regular el volumen. Como altavoz uso un buzzer pasivo.
En la foto se puede ver, todavía sin acabar, mi idea original, con una pila de 9v. Pero, aunque válida, no ha resultado ser una opción demasiado buena. Esto requiere una interesante explicación que comentaré en los siguientes párrafos. De momento unas fotos para hacerse una idea:
En mi montaje, en el lugar del potenciometro para el volumen he puesto un puente, optando así por la potencia máxima, pero esto puede ser molesto para algunas personas así que indico la posibilidad de regular el volumen. Como altavoz uso un buzzer pasivo.
En la foto se puede ver, todavía sin acabar, mi idea original, con una pila de 9v. Pero, aunque válida, no ha resultado ser una opción demasiado buena. Esto requiere una interesante explicación que comentaré en los siguientes párrafos. De momento unas fotos para hacerse una idea:
Idea del proceso de montaje y detalles del PinoLed |
Una foto del PinoLed durante las pruebas |
Y el video, un poco cutre (también en YouTube), da una pequeña muestra del resultado final de mi ejercicio, bautizado como PinoLed.
APUNTES SOBRE LA PROGRAMACIÓN.
También dejo por aquí a la vista mi programa del arduino. Probablemente muy simple y poco elegante para los muy iniciados. Pero espero que útil para aprender a los que, como yo, no lo son tanto. Fue desarrollado y probado con un Arduino Uno R3 y con el IDE de programación 1.6.1.
Básicamente se trata de la función "Visualizar()" que está constantemente mostrando el brillo de cada led que la matriz "diodoFilCol[7][7]" guarda en sus índices (0 apagado, 255 brillo máximo).
Estos valores del brillo de cada led se van modificando según una "secuencia()" temporal para que coincida con la música también definida en esta función.
Para que no sea demasiado repetitivo, de forma medio chapucera (en honor al nombre del blog), he creado un par de posibles estados en donde, sin música, las luces hacen un par de efectos aleatorios: uno jugando con encender y apagar leds al azar; otro jugando con subir y bajar el brillo de diferentes colores. De manera más o menos accidental puede volverse al estado inicial de secuencia leds-música, y si no, al cabo de un tiempo mínimo, de manera forzada (establecido ahora para las pruebas en 60 segundos) .
Otras funciones organizan de forma predefinida efectos simples de luces para simplificar la repetición en la programación.
Por si alguien se anima a probar, dejo aquí una copia del archivo .ino definitivo comprimido en zip.
Y para quien solo quiera curiosear y echar un vistazo rápido, aquí está el código.
//////////////////////////////////////////////// // Para hacer funcionar PinoLed // // Matriz de 36 leds y un buzzer // // http//:electronicaychapuzas.blogspot.com.es// // by Sancos v1.1 // //////////////////////////////////////////////// byte diodoFilCol[7][7]; //definira estado diodos:0 apagado 255 encendido // fila y columna define que pines uso.No usamos fila0 ni columna0 byte fila[7]={255,15,14,2,4,7,8}; //No usare fila0. 14=A0, 15=A1 byte columna[7]={255,3,5,6,9,10,11}; //No usare columna0 //Podría usar pwm por comodidad. Por eso utilizo estas salidas. //Pero para poder usar Tone() sin problemas no usaré PWM //Ademas, después de montado el circuito, he caido en que hubiera //sido mas interesante el PWM en las filas. int v=2; //Velocidad tempo int i,c,n,f,luz; //Contadores uso general int estado; //Que estamos haciendo? 0-inicio; 1-secuencia; unsigned long tiempo0,tiempo; //Contadores tiempo short Do2,Si2,Do3,Re3,Mi3,Fa3,Sol3,La3,Si3,Do4; //Notas que vamos a usar void setup() { // Filas. Activas a nivel bajo. Reposo a nivel alto. for (f=1; f<7; f=f+1) { pinMode(fila[f],OUTPUT); digitalWrite(fila[f],HIGH); } // Audio implementado por pin 12. //señal de audio. Reposo a nivel bajo pinMode(12,OUTPUT); digitalWrite(12,LOW); // Notas Do2=130.813; Si2=246.942; Do3=261.626; Re3=293.665; Mi3=329.628; Fa3=349.228; Sol3=391.995; La3=440; Si3=493.883; Do4=523.251; //Columnas. Activas a nivel alto. Reposo a nivel bajo. for (c=1; c<7; c=c+1) { pinMode(columna[c],OUTPUT); digitalWrite(columna[c],LOW); } //Inicializamos el estado de cada led a apagado. //La matriz diodoFilCol define cada diodo // desde 0 (apagado) a 255 (brillo maximo) for (f=1; f<7; f=f+1) { for (c=0; c<7; c=c+1) { diodoFilCol[f][c]=0; } } tone(12,440,1000); //Test al inicio delay(5000); //Esperamos unos segundos antes de arrancar tiempo0=millis(); //Tomamos tiempo inicial para temporizaciones estado=1; } void loop() { if (estado==0) Test(); //Test al inicio if (estado==1) Secuencia(); //Secuencia programada con musica if (estado==2) Luces(); //Luces al azar y silencio if (estado==3) Rgb(); Visualizar(); } // Visualizar la matriz diodoFilCol. void Visualizar() { for (c=1; c<7; c=c+1) //Repetir con las seis columnas { digitalWrite(columna[c],HIGH); //Activar columna for (n=1; n<255; n=n+4) //Pasos lo mas cortos posible sin que parpadeen los leds { for (f=1; f<7; f=f+1) //Activar las filas según brillo en matriz { //Activamos o no más veces según numero en matriz mas alto if ((255-n)<(diodoFilCol[f][c])) digitalWrite(fila[f],LOW); else digitalWrite(fila[f],HIGH); } } digitalWrite(columna[c],LOW); //Desactivar columna for (f=1; f<7; f=f+1) //Desactivar filas { digitalWrite(fila[f],HIGH); } } } /********************/ /* Efectos de luces */ /********************/ // Apagar todos los leds (0), o encender(255) void Todos(int brillo) { for (f=0; f<7; f=f+1) { for (c=0; c<7; c=c+1) { diodoFilCol[f][c]=brillo; } } } // Iluminar un led en concreto. void Led(int fil,int col,int brillo) { diodoFilCol[fil][col]=brillo; } // Iluminar una columna en concreto. void Columna(int col, int brillo) { for (c=0;c<7;c=c+1) { diodoFilCol[c][col]=brillo; } } //Iluminar una fila en concreto. void Fila(int fil, int brillo) { for (c=0;c<7;c=c+1) { diodoFilCol[fil][c]=brillo; } } //Iluminar todos rojos void Rojos(int brillo) { Led(1,1,brillo); Led(1,4,brillo); Led(2,3,brillo); Led(2,6,brillo); Led(3,2,brillo); Led(3,5,brillo); Led(4,2,brillo); Led(4,5,brillo); Led(5,2,brillo); Led(5,5,brillo); Led(6,2,brillo); Led(6,5,brillo); } //Iluminar todos verdes void Verdes(int brillo) { Led(1,2,brillo); Led(1,5,brillo); Led(2,2,brillo); Led(2,5,brillo); Led(3,3,brillo); Led(3,6,brillo); Led(4,3,brillo); Led(4,6,brillo); Led(5,3,brillo); Led(5,6,brillo); Led(6,3,brillo); Led(6,6,brillo); } //Iluminar todos amarillos void Amarillos(int brillo) { //Para amarillo 180 de rojo y 255 de verde //porque el led rojo alumbra más con menos tension int correccionbrillo; correccionbrillo=((brillo*180)/255); Led(1,1,correccionbrillo); Led(1,2,brillo); Led(1,3,0); Led(1,4,correccionbrillo); Led(1,5,brillo); Led(1,6,0); Led(2,1,brillo); Led(2,4,brillo); Led(3,1,brillo); Led(3,4,brillo); Led(4,1,brillo); Led(4,4,brillo); Led(5,1,brillo); Led(5,4,brillo); Led(6,1,brillo); Led(6,4,brillo); } void AzarLed(int cuantas, int pausa) //Cuantas luces encendemos; cada una pausa ms { // tiempo aprox. funcion = cuantas * pausa long int filaazar, columnaazar; Todos(0); randomSeed(analogRead(3)); //El pin A3 está al aire for (i=0; i<cuantas; i=i+1); { filaazar=random(1,7); columnaazar=random(1,7); Led(filaazar,columnaazar,255); delay(pausa); } } void AzarFila(int cuantas, int pausa) //Cuantas filas encendemos cada pausa ms { //tiempo aprox.funcion=cuantas*pausa long int filaazar; Todos(0); randomSeed(analogRead(3)); //A3 al aire for (i=0; i<cuantas; i=i+1); { filaazar=random(1,7); Fila(filaazar,255); delay(pausa); } } void AzarColumna(int cuantas, int pausa) //Cuantas columnas encendemos cada pausa ms { //tiempo aprox.funcion=cuantas*pausa long int columnaazar; Todos(0); randomSeed(analogRead(3)); //A3 al aire for (i=0; i<cuantas; i=i+1); { columnaazar=random(1,7); Columna(columnaazar,255); delay(pausa); } } /***********************/ /* Secuencias */ /***********************/ void Test() { tiempo=(millis()-tiempo0); if (tiempo<1000) { Todos(255); } if ((tiempo>=1000)&&(tiempo<2000)) { Todos(0); Led(1,1,255); Led(1,4,255); //Rojo } if ((tiempo>=2000)&&(tiempo<3000)) { Todos(0); Led(1,1,0); Led(1,4,0); Led(1,2,255); Led(1,5,255); //Verde } if ((tiempo>=3000)&&(tiempo<4000)) { Todos(0); Led(1,2,0); Led(1,5,0); Led(1,3,255); Led(1,6,255); //Azul } if ((tiempo>=4000)&&(tiempo<4500)) { Todos(0); Led(1,3,200); Led(1,6,200); //Apagando azul Led(1,5,5); //Encendiendo verde } if ((tiempo>=4500)&&(tiempo<5000)) { Todos(0); Led(1,3,100); Led(1,6,100); //Apagando azul Led(1,15,5); //Encendiendo verde } if ((tiempo>=5000)&&(tiempo<5500)) { Todos(0); Led(1,3,50); Led(1,6,50); //Apagando azul Led(1,5,50); //Encendiendo verde } if ((tiempo>=5500)&&(tiempo<6000)) { Todos(0); Led(1,3,25); Led(1,6,25); //Apagando azul Led(1,5,100); //Encendiendo verde } if ((tiempo>=6000)&&(tiempo<6500)) { Todos(0); Led(1,3,15); Led(1,6,15); //Apagando azul Led(1,5,200); //Encendiendo verde } if ((tiempo>=6500)&&(tiempo<7000)) { Todos(0); Led(1,3,0); Led(1,6,0); //Apagando azul Led(1,5,255); //Encendiendo verde } if ((tiempo>=7000)) { estado=1; tiempo0=millis(); } } //Luces al azar para reposo void Luces() { long int quehacer,fil,col; randomSeed(analogRead(3)); //A3 al aire quehacer=random(1,100); fil=random(1,7); col=random(1,7); if (quehacer<3) Todos(0); if ((quehacer>=5)&&(quehacer<45)) Led(fil,col,255); if ((quehacer>=45)&&(quehacer<85)) Led(fil,col,0); if (quehacer==85) estado=3; //ejecuta Rgb() if ((quehacer>85)&&(estado<89)) Fila(fil,255); if ((quehacer>89)&&(estado<94)) Columna(col,255); if ((quehacer>99)) { estado=1; tiempo0=millis(); } if ((millis()-tiempo0)>60000){ estado=1; tiempo0=millis(); } //aqui aseguro musica cada 60 segundos } //Led de colores void Rgb() { long int quehacer; //luz interesa global randomSeed(analogRead(3)); //A3 al aire quehacer=random(1,100); if (quehacer>60) luz=luz+1; if (luz>250) luz=luz-1; if ((luz>200)&&(quehacer>95)) luz=0; if (quehacer>98) {luz=0; estado=2;} //volver a luces() if (quehacer<33) Rojos(luz); if ((quehacer>33)&&(quehacer<66)) Verdes(luz); if ((quehacer>66)&&(quehacer<98)) Amarillos(luz); if ((quehacer>99)&&(luz>200)) { estado=1; tiempo0=millis(); } } //Programar secuencia a repetir void Secuencia() { tiempo=(millis()-tiempo0); /*************** MUSICA ******************/ //Compas1 if (tiempo<(500/v)) { if (tiempo<(400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(500/v))&&(tiempo<(1000/v))) { if (tiempo<(900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(1000/v))&&(tiempo<(2000/v))) { if (tiempo<(1750/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(2000/v))&&(tiempo<(2500/v))) { if (tiempo<(2400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(2500/v))&&(tiempo<(3000/v))) { if (tiempo<(2900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(3000/v))&&(tiempo<(4000/v))) { if (tiempo<(3750/v)) tone(12,Mi3,(100/v)); } //Compas2 if ((tiempo>=(4000/v))&&(tiempo<(4500/v))) { if (tiempo<(4400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(4500/v))&&(tiempo<(5000/v))) { if (tiempo<(4900/v)) tone(12,Sol3,(100/v)); } if ((tiempo>=(5000/v))&&(tiempo<(5750/v))) { if (tiempo<(5600/v)) tone(12,Do3,(100/v)); } if ((tiempo>=(5750/v))&&(tiempo<(6000/v))) { if (tiempo<(5900/v)) tone(12,Re3,(100/v)); } if ((tiempo>=(6000/v))&&(tiempo<(8000/v))) { if (tiempo<(6500/v)) tone(12,Mi3,(100/v)); } //Compas3 if ((tiempo>=(8000/v))&&(tiempo<(8500/v))) { if (tiempo<(8400/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(8500/v))&&(tiempo<(9000/v))) { if (tiempo<(8900/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(9000/v))&&(tiempo<(9750/v))) { if (tiempo<(9700/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(9750/v))&&(tiempo<(10000/v))) { if (tiempo<(9900/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(10000/v))&&(tiempo<(10500/v))) { if (tiempo<(10400/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(10500/v))&&(tiempo<(11000/v))) { if (tiempo<(10900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(11000/v))&&(tiempo<(11500/v))) { if (tiempo<(11400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(11500/v))&&(tiempo<(11750/v))) { if (tiempo<(11700/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(11750/v))&&(tiempo<(12000/v))) { if (tiempo<(11900/v)) tone(12,Mi3,(100/v)); } //Compas4 if ((tiempo>=(12000/v))&&(tiempo<(12500/v))) { if (tiempo<(12400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(12500/v))&&(tiempo<(13000/v))) { if (tiempo<(12900/v)) tone(12,Re3,(100/v)); } if ((tiempo>=(13000/v))&&(tiempo<(13500/v))) { if (tiempo<(13400/v)) tone(12,Re3,(100/v)); } if ((tiempo>=(13500/v))&&(tiempo<(14000/v))) { if (tiempo<(13900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(14000/v))&&(tiempo<(15000/v))) { if (tiempo<(14900/v)) tone(12,Re3,(100/v)); } if ((tiempo>=(15000/v))&&(tiempo<(15750/v))) { if (tiempo<(15700/v)) tone(12,Sol3,(100/v)); } if ((tiempo>=(15750/v))&&(tiempo<(16000/v))) { if (tiempo<(15700/v)) tone(12,Do2,(100/v)); } //Compas5 if ((tiempo>=(16000/v))&&(tiempo<(16500/v))) { if (tiempo<(16400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(16500/v))&&(tiempo<(17000/v))) { if (tiempo<(16900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(17000/v))&&(tiempo<(18000/v))) { if (tiempo<(17750/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(18000/v))&&(tiempo<(18500/v))) { if (tiempo<(18400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(18500/v))&&(tiempo<(19000/v))) { if (tiempo<(18900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(19000/v))&&(tiempo<(20000/v))) { if (tiempo<(19750/v)) tone(12,Mi3,(100/v)); } //Compas6 if ((tiempo>=(20000/v))&&(tiempo<(20500/v))) { if (tiempo<(20400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(20500/v))&&(tiempo<(21000/v))) { if (tiempo<(20900/v)) tone(12,Sol3,(100/v)); } if ((tiempo>=(21000/v))&&(tiempo<(21750/v))) { if (tiempo<(21700/v)) tone(12,Do3,(100/v)); } if ((tiempo>=(21750/v))&&(tiempo<(22000/v))) { if (tiempo<(21900/v)) tone(12,Re3,(100/v)); } if ((tiempo>=(22000/v))&&(tiempo<(24000/v))) { if (tiempo<(22500/v)) tone(12,Mi3,(100/v)); } //Compas7 if ((tiempo>=(24000/v))&&(tiempo<(24500/v))) { if (tiempo<(24400/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(24500/v))&&(tiempo<(25000/v))) { if (tiempo<(24900/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(25000/v))&&(tiempo<(25750/v))) { if (tiempo<(25700/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(25750/v))&&(tiempo<(26000/v))) { if (tiempo<(25900/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(26000/v))&&(tiempo<(26500/v))) { if (tiempo<(26400/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(26500/v))&&(tiempo<(27000/v))) { if (tiempo<(26900/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(27000/v))&&(tiempo<(27500/v))) { if (tiempo<(27400/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(27500/v))&&(tiempo<(27750/v))) { if (tiempo<(27700/v)) tone(12,Mi3,(100/v)); } if ((tiempo>=(27750/v))&&(tiempo<(28000/v))) { if (tiempo<(27900/v)) tone(12,Mi3,(100/v)); } //Compas8 if ((tiempo>=(28000/v))&&(tiempo<(28500/v))) { if (tiempo<(28400/v)) tone(12,La3,(100/v)); } if ((tiempo>=(28500/v))&&(tiempo<(29000/v))) { if (tiempo<(28900/v)) tone(12,Sol3,(100/v)); } if ((tiempo>=(29000/v))&&(tiempo<(29500/v))) { if (tiempo<(29400/v)) tone(12,Fa3,(100/v)); } if ((tiempo>=(29500/v))&&(tiempo<(30000/v))) { if (tiempo<(29900/v)) tone(12,Re3,(100/v)); } if ((tiempo>=(30000/v))&&(tiempo<(30500/v))) { if (tiempo<(30400/v)) tone(12,Do3,(100/v)); } if ((tiempo>=(30500/v))&&(tiempo<(32000/v))) { if (tiempo<(31900/v)) noTone(12); } /***************** LUCES *******************/ //Compas1 if (tiempo<(500/v)) { //Mi3 Todos(0); Rojos(255); } if ((tiempo>=(500/v))&&(tiempo<(1000/v))) { //Mi3 Todos(0); Amarillos(255); } if ((tiempo>=(1000/v))&&(tiempo<(2000/v))) { //Mi3 Todos(0); Verdes(255); } if ((tiempo>=(2000/v))&&(tiempo<(2500/v))) { //Mi3 Todos(0); Rojos(255); } if ((tiempo>=(2500/v))&&(tiempo<(3000/v))) { //Mi3 Amarillos(255); } if ((tiempo>=(3000/v))&&(tiempo<(4000/v))) { //Mi3 Verdes(255); } //Compas2 if ((tiempo>=(4000/v))&&(tiempo<(4500/v))) { //Mi3 Fila(1,0); Fila(2,0); } if ((tiempo>=(4500/v))&&(tiempo<(5000/v))) { //Sol3 Fila(3,0); } if ((tiempo>=(5000/v))&&(tiempo<(5750/v))) { //Do3 Fila(4,0); } if ((tiempo>=(5750/v))&&(tiempo<(6000/v))) { //Re3 Fila(5,0); } if ((tiempo>=(6000/v))&&(tiempo<(6500/v))) { //Mi3 Fila(6,0); } if ((tiempo>=(6500/v))&&(tiempo<(7000/v))) { //Silencio Led(1,6,255); } if ((tiempo>=(7000/v))&&(tiempo<(7500/v))) { //Silencio } if ((tiempo>=(7500/v))&&(tiempo<(8000/v))) { //Silencio Led(1,6,0); Led(1,4,180); Led(1,5,255); } //Compas3 if ((tiempo>=(8000/v))&&(tiempo<(8500/v))) { //Fa3 Todos(0); Columna(1,255); Columna(2,30);Columna(3,0);Columna(4,125);Columna(5,0);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(8500/v))&&(tiempo<(9000/v))) { //Fa3 Columna(1,30); Columna(2,255);Columna(3,30);Columna(4,0);Columna(5,125);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(9000/v))&&(tiempo<(9500/v))) //Varia de nota { //Fa3 Columna(1,0); Columna(2,30);Columna(3,255);Columna(4,30);Columna(5,0);Columna(6,125); Fila(1,0);Fila(2,0); } if ((tiempo>=(9500/v))&&(tiempo<(10000/v))) //Varia de nota { //Fa3 Columna(1,125); Columna(2,0);Columna(3,30);Columna(4,255);Columna(5,30);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(10000/v))&&(tiempo<(10500/v))) { //Fa3 Columna(1,0); Columna(2,125);Columna(3,0);Columna(4,30);Columna(5,255);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(10500/v))&&(tiempo<(11000/v))) { //Mi3 Columna(1,30); Columna(2,0);Columna(3,125);Columna(4,0);Columna(5,30);Columna(6,255); Fila(1,0);Fila(2,0); } if ((tiempo>=(11000/v))&&(tiempo<(11500/v))) { //Mi3 Columna(1,255); Columna(2,30);Columna(3,0);Columna(4,125);Columna(5,0);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(11500/v))&&(tiempo<(11750/v))) { //Mi3 Columna(1,30); Columna(2,255);Columna(3,30);Columna(4,0);Columna(5,125);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(11750/v))&&(tiempo<(12000/v))) { //Mi3 } //Compas4 if ((tiempo>=(12000/v))&&(tiempo<(12500/v))) { //Mi3 Columna(1,0); Columna(2,30);Columna(3,255);Columna(4,30);Columna(5,0);Columna(6,125); Fila(1,0);Fila(2,0); } if ((tiempo>=(12500/v))&&(tiempo<(13000/v))) { //Re3 Columna(1,125); Columna(2,0);Columna(3,30);Columna(4,255);Columna(5,30);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(13000/v))&&(tiempo<(13500/v))) { //Re3 Columna(1,0); Columna(2,125);Columna(3,0);Columna(4,30);Columna(5,255);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(13500/v))&&(tiempo<(14000/v))) { //Mi3 Columna(1,30); Columna(2,0);Columna(3,125);Columna(4,0);Columna(5,30);Columna(6,255); Fila(1,0);Fila(2,0); } if ((tiempo>=(14000/v))&&(tiempo<(15000/v))) { //Re3 Columna(1,255); Columna(2,30);Columna(3,0);Columna(4,125);Columna(5,0);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(15000/v))&&(tiempo<(15750/v))) { //Sol3 Columna(1,30); Columna(2,255);Columna(3,30);Columna(4,0);Columna(5,125);Columna(6,0); Fila(1,0);Fila(2,0); Led(1,1,255); } if ((tiempo>=(15750/v))&&(tiempo<(16000/v))) { //Do2 Todos(0); Led(1,1,255); } //Compas5 if ((tiempo>=(16000/v))&&(tiempo<(16500/v))) { //Mi3 Todos(0); Rojos(255); } if ((tiempo>=(16500/v))&&(tiempo<(17000/v))) { //Mi3 Todos(0); Amarillos(255); } if ((tiempo>=(17000/v))&&(tiempo<(18000/v))) { //Mi3 Todos(0); Verdes(255); } if ((tiempo>=(18000/v))&&(tiempo<(18500/v))) { //Mi3 Todos(0); Rojos(255); } if ((tiempo>=(18500/v))&&(tiempo<(19000/v))) { //Mi3 Amarillos(255); } if ((tiempo>=(19000/v))&&(tiempo<(20000/v))) { //Mi3 Verdes(255); } //Compas6 if ((tiempo>=(20000/v))&&(tiempo<(20500/v))) { //Mi3 Fila(6,0); } if ((tiempo>=(20500/v))&&(tiempo<(21000/v))) { //Sol3 Fila(5,0); } if ((tiempo>=(21000/v))&&(tiempo<(21750/v))) { //Do3 Fila(4,0); } if ((tiempo>=(21750/v))&&(tiempo<(22000/v))) { //Re3 Fila(3,0); } if ((tiempo>=(22000/v))&&(tiempo<(24000/v))) { //Mi3 Fila(2,0); Fila(1,0); } //Compas7 if ((tiempo>=(24000/v))&&(tiempo<(24500/v))) { //Fa3 Todos(0); Columna(1,255); Columna(2,30);Columna(3,0);Columna(4,125);Columna(5,0);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(24500/v))&&(tiempo<(25000/v))) { //Fa3 Columna(1,30); Columna(2,0);Columna(3,125);Columna(4,0);Columna(5,30);Columna(6,255); Fila(1,0);Fila(2,0); } if ((tiempo>=(25000/v))&&(tiempo<(25500/v))) //No coincide con nota { //Fa3 Columna(1,0); Columna(2,125);Columna(3,0);Columna(4,30);Columna(5,255);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(25500/v))&&(tiempo<(26000/v))) //No coincide con nota { //Fa3 Columna(1,125); Columna(2,0);Columna(3,30);Columna(4,255);Columna(5,30);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(26000/v))&&(tiempo<(26500/v))) { //Fa3 Columna(1,0); Columna(2,30);Columna(3,255);Columna(4,30);Columna(5,0);Columna(6,125); Fila(1,0);Fila(2,0); } if ((tiempo>=(26500/v))&&(tiempo<(27000/v))) { //Mi3 Columna(1,30); Columna(2,255);Columna(3,30);Columna(4,0);Columna(5,125);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(27000/v))&&(tiempo<(27500/v))) { //Mi3 Columna(1,255); Columna(2,30);Columna(3,0);Columna(4,125);Columna(5,0);Columna(6,30); Fila(1,0);Fila(2,0); } if ((tiempo>=(27500/v))&&(tiempo<(27750/v))) { //Mi3 Columna(1,30); Columna(2,0);Columna(3,125);Columna(4,0);Columna(5,30);Columna(6,255); Fila(1,0);Fila(2,0); } if ((tiempo>=(27750/v))&&(tiempo<(28000/v))) { //Mi3 Columna(1,0); Columna(2,125);Columna(3,0);Columna(4,30);Columna(5,255);Columna(6,30); Fila(1,0);Fila(2,0); } //Compas8 if ((tiempo>=(28000/v))&&(tiempo<(28500/v))) { //La3 Columna(1,125); Columna(2,0);Columna(3,30);Columna(4,255);Columna(5,30);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(28500/v))&&(tiempo<(29000/v))) { //Sol3 Columna(1,0); Columna(2,30);Columna(3,255);Columna(4,30);Columna(5,0);Columna(6,125); Fila(1,0);Fila(2,0); } if ((tiempo>=(29000/v))&&(tiempo<(29500/v))) { //Fa3 Columna(1,30); Columna(2,255);Columna(3,30);Columna(4,0);Columna(5,125);Columna(6,0); Fila(1,0);Fila(2,0); } if ((tiempo>=(29500/v))&&(tiempo<(30000/v))) { //Re3 Todos(0); } if ((tiempo>=(30000/v))&&(tiempo<(30500/v))) { //Do3 Todos(255); } if ((tiempo>=(30500/v))&&(tiempo<(32000/v))) { //Tres silencios corchea if (tiempo<(31900/v)) noTone(12); } if (tiempo>=(32000/v)) { tiempo0=millis(); estado=2; //ejecuta Luces() } }
INTERESANTE PROBLEMILLA NO PREVISTO CON PILA DE 9V Y EXCESIVO CONSUMO.
Al final, casi siempre hay algo que podría haber estado mejor pensado. Y aquí he caído en la cuenta, cuando ya todo estaba demasiado montado.
Mi idea original era alimentar todo con una pila de 9v oculta debajo del pino de cartulina. Y en principio todo parece bien pensado, pero haciendo pruebas y test durante la programación me he encontrado con dos detalles:
Con la batería todo va bien unos minutos, pero enseguida el arduino se apaga y enciende (el regulador de 5v necesita más de 7 en Vin). Cosa que si alimento con el usb (aunque usamos menos tensión), todo parece ir mejor.
Y originalmente las resistencias eran de menos potencia pero se calentaban mucho más de lo deseable. Tuve que montarlas de más watios. Así que tenía que haber exceso de consumo por algún sitio...
Repensando sobre el esquema del circuito ya montado me he dado cuenta que cuando los leds están apagados porque la fila está desactivada, la resistencia limitadora conduce de Vin a masa. Así que todas las lineas conducen y consumen corriente. Incluso más en reposo.
Esto, aunque no llega a los límites del arduino porque es a través de los transistores, sí que agota la batería demasiado rápido. Las baterías de 9v tampoco son una maravilla en capacidad de carga.
Y si pensamos en una alimentación alta para que los leds alumbren mejor. Más allá de los 15v nos vamos a consumos peligrosos de más de 500mA ((15v/180ohm)*6 resistencias=0,5A).
Así que la idea de alimentarlo con baterías funciona, pero nos saldrá cara. Habrá que fijarse más en esta cuestión para otros proyectos.
Pero en este punto ha quedado éste.