Proyecto Simón: DISEÑO SISTEMAS MÓVILES Y EMPOTRADOS DSEM Ángel Castillo Sergi Martínez Héctor Ortiz Toni Torronteras 1 ÍNDICE 1. 2. INTRODUCCIÓN ......................................................................................................... 3 DISEÑO ANALÓGICO.................................................................................................. 4 2.1. Pulsadores .......................................................................................................... 5 2.2. Caja..................................................................................................................... 7 3. Placa Wiring............................................................................................................... 8 4. Código...................................................................................................................... 10 4.1. Funcionamiento del programa ........................................................................ 11 4.2. Modo 1 player .................................................................................................. 11 4.3. Modo 2 player .................................................................................................. 12 5. Presupuesto............................................................................................................. 15 6. Conclusiones............................................................................................................ 15 7. Anexo código placa esclavo..................................................................................... 16 8. Anexo código placa maestro ................................................................................... 22 2 1. INTRODUCCIÓN DSEM (Diseño de Sistemas Móviles y Empotrados) es una de las optativas de la ingeniería técnica de telecomunicaciones, en la cual hemos aprendido a desarrollar aplicaciones para PDA’s, teléfonos móviles y además a programar en un nuevo lenguaje para nosotros, Processing. Es un lenguaje basado en Java, pero de mucho mas alto nivel, es decir, mucho mas entendible para el usuario, ya que no utiliza un código demasiado complejo. Este lenguaje nació precisamente para que gente poco habituada a la programación pudiera realizar proyectos de un cierto grado de complejidad. A partir de haber descubierto esta nuevo tipo de lenguaje y su facilidad para la programación, habiendo realizado una serie de pruebas, estudio de librerías y diferentes tipos de programas realizados por variedad de programadores, conocimos la programación Wiring, muy similar a Processing, pero con un dispositivo hardware por en medio. Este dispositivo hardware consta principalmente de una placa donde tenemos una BIOS donde cargamos el código del programa, puertos de entrada/salida, entrada USB, para conectar con el ordenador y una entrada para la alimentación después de aprender el funcionamiento de Wiring se decidió realizar un proyecto final de asignatura basado en este lenguaje. Para ello y tras una selección de diferentes propuestas de proyectos, decidimos elaborar el proyecto sobre un juego tradicional, “Simón Dice”. Este juego trata de seguir la secuencia de colores, pulsando el botón adecuado a cada color, en el que además incluye la opción de dos jugadores. A priori, parece que no tiene gran complejidad, pero como veremos mas adelante, tiene mas de la que parece. Para hacer este proyecto mas atractivo, y como el mismo nombre de la asignatura indica, decidimos realizar todo el montaje del proyecto, es decir, tanto la parte de programación como mecánica, la construcción física del aparato a partir de la placa Wiring. 3 2. DISEÑO ANALÓGICO Antes de empezar a elaborar todo el proyecto, empezamos a tomar ideas para realizar el diseño del aparato en cuestión que el usuario debería tener para poder jugar. El diseño en estaría basado en una caja de metraquilato donde colocaríamos la placa Wiring y toda la electrónica que necesitáramos. Esta caja debe tener unas dimensiones adecuadas para que dentro de ella cupiera la placa, circuitería interna, una pequeña fuente de alimentación en forma de pila. En un principio la caja no debía ser cerrada, ya que los pulsadores deberían estar por fuera y necesitábamos tener la cara de arriba libre, pero tras la adquisición de la caja cerrada, con la posibilidad de abrirla por la parte superior, decidimos que sería una mejor opción hacer los agujeros en la tapa para la colocación de los pulsadores. La caja en cuestión tiene las siguientes medidas 160mm de largo, 100mm de ancho y 50mm de alto. Para el montaje de los pulsadores desde el principio teníamos en mente soldar cuatro botones en las esquinas de una placa de baquelita de unos 35cmx35cm, con suficiente espacio para poder pegarla en la parte superior de la caja de metraquilato de exactamente 35cm. y colocar 4 led’s en el centro de la placa como muestra la figura 1, haciendo así que la cabeza del led saliera dos milímetros por encima de la placa de baquelita, y las dos patas por cada led por debajo, que quedarían dentro de la caja de metraquilto. Una vez hecho esto, pensamos en una primera instancia sacar dos cables por cada botón, pero al final fue una idea descartada, ya que era inviable la idea de sacar 8 cables de los 4 botones mas las 8 patas de los led’s, por cada pulsador por falta de espacio dentro de la caja, por lo tanto, decidimos unir las pistas de la placa de metraquilato, uniendo así los cuatro botones en paralelo y sacar únicamente 3 cables por cada pulsador mas las dos patas de cada led. FIG. 1 Esquema pulsador Una vez definido el esquema de este pulsador, decidimos colocar encima de los cuatro botones, una placa de metraquilato de cada color y la uniríamos con pegamento. Con lo que quedaría un prototipo como el de ver Fig. 2. 4 FIG. 2 Vista aérea del prototipo Una vez realizado esto, teníamos que decidir como colocar de manera visible el nivel de la partida elegida y el jugador activo en ese momento, para ello colocamos en nuestro diseño, tres led`s indicando la dificultad. Un led encendido significa nivel fácil, dos led’s encendidos, nivel medio, tres led`s encendidos significa nivel difícil. El jugador que esta activo lo mostraría mediante un siete segmentos. Fig. 3 Vista aérea del prototipo versión 2. 2.1. Pulsadores Empezamos cortando la placa de baquelita para realizar los pulsadores. Aquí tuvimos el primer problema, ya que si cortábamos mal, la placa se rompería fácilmente, por lo tanto no era posible cortar esta placa con tijeras, ni con cutex, así que al final optamos por utilizar una Dremel, herramienta óptima para cortar, perforar este tipo de material, de una manera limpia y segura. Empezamos serrando cuadrados de baquelita de 30x 30, un total de 8. Una vez cortados, tuvimos que realizar cuatro perforaciones por cada cuadrado de baquelita, para introducir los led’s. Continuamos soldando los botones en las esquinas como mostraba la Fig. 1, acto seguido, usando estaño creamos las pistas necesarias para poder colocar los botones en paralelo y finalmente enganchamos los leds. En resumen, de cada placa de baquelita nos salen 2 cables por led, un cable común para todos los pulsadores y 2 cables que se unirán para el otro polo de los pulsadores. 5 Fig. 4 Esquema electrónico pulsador. En la FIG. 4, se muestran en rojo las conexiones a los cables de salida. Estas 4 placas de baquelita van pegadas con loctite a la caja del juego. En la siguiente FIG. 5, se muestra el modo en el que van conectados los pulsadores en la placa. De este modo conseguimos un ‘0’ o un ‘1’ lógico evitando el estado de alta impedancia. Fig. 5 Esquema electrónico pulsador individual. Los 4 leds deben estar conectados en paralelo con una resistencia de valor resistivo bajo y en serie. Fig. 6 Esquema electrónico leds boton. El resultado final se puede observar en la siguiente imagen (ver FIG. 7) : 6 Fig. 7 Fotografía pulsador final. 2.2. Caja El montaje de la caja tiene menor complejidad que los pulsadores, ya que la caja de metraquilatro ya estaba fabricada a medida, como hemos dicho anteriormente, aprovechábamos la tapa de la caja para insertar los pulsadores, para ello perforamos la caja con una Dremel en las cuatro posiciones indicadas en la Fig. 2 para marcarlas y posteriormente hacer un agujero mucho mayor con una corona, con unas dimensiones adecuadas inferior a los 30x30, para que la placa de baquelita no caiga dentro de la perforación. Una vez perforamos realizado este paso, queda enganchar los pulsadores y el resultado es el siguiente (ver FIG. 8) : Fig. 8 Fotografía montage botones. 7 Una vez realizados estos pasos, hicimos tres perforaciones para indicar el grado de dificultad de la partida; Dos más para indicar cuál de los dos jugadores tiene el turno y además un 7 segmentos para indicar las vidas restantes. En la misma caja, incluimos un botón especial para seleccionar estos parámetros del juego. 3. Placa Wiring El corazón de la placa lo integra un microcontrolador modelo ATMEGA128 del fabricante ATMEL. Hemos extraido las características del datasheet que proporciona este fabricante y son las siguientes: Fig. 9 caracteristicas atmel128, 8-Bit microcontroller with 128KBytes In-System Programmable Flash. 8 La placa Wiring esta adaptada a este microcontrolador mediante un esquema electrónico con las conexiones I/O realizadas mediante agrupaciones de pines, es decir, PUERTOS. Tambien incluye una conexión USB para facilitar la conexión al PC y con ello su programación, un led de power, un botón de reset, etc. Fig. 10 Placa Wiring. 43 Pines digitales I/O. 5 Puertos digitales (8 bits por puerto). 8 Entradas analógicas (10 bits de resolución). 6 Salidas analógicas de Pulse Width Modulation PWM. 2 Puertos series. 2 Pines Two Wire Interface, más conocido como i2c. 8 Interrupciones externas. Conector para alimentación, fuente 7-13 V a 800mA. El entorno de programación consiste en un software de libre descarga y diseñado para la programación de la placa Wiring. El lenguaje de programación utilizado es C pero con unas series de librerías (ya integradas en el software) que facilitan la tarea. No olvidemos que esta iniciativa esta enfocada a un publico no familiarizado con la electrónica ni con programación. 9 Fig. 11 Entorno de programación wiring. Tal como vemos en la FIG. 11 se trata de un software bastante sencillo comparado con otros entornos de programación (Microsoft Visual Studio, MPLAB, …). Unicamente disponemos de 7 botones: play (compila), stop, new, save, load, upload to I/O board (grabar en placa wiring) y serial monitor (herramienta más próxima a un debuger). 4. Código Nuestro programa se puede dividir en cuatro partes: 1. Variables globales: aquí se declaran aquellas variables que podemos utilizar en cualquier momento del programa. También declaramos nombres a los pines a utilizar. 2. Funciones: en esta parte del programa, definiremos todas aquellas funciones que necesitaremos a lo largo del programa. Estas funciones puden ser llamadas en la parte Loop y dentro de otras funciones. 3. Setup: esta parte consiste en la configuración de la placa, es decir, estableceremos que pines serán de salida o de entrada y activaremos la interfaz para los pines de comunicación. 4. Loop: es el equivalente al main() de cualquier lenguaje de programación, con la diferencia que se ejectua en modo bucle infinito. 10 4.1. Funcionamiento del programa Nuestro proyecto consiste en emular el juego conocido por todos como SIMON tanto para 1 jugador como para 2 jugadores. Cuando encendemos (conectamos alimentación) la placa wiring espera 10 segundos para introducirle el número de jugadores, esto será indicado mediante ledPlayer1 en pin 20 y ledPlayer2 en pin 21 usando el pulsador central conectado al pin 19. Si queremos jugar en modo multijador debemos establecer player 2 en las dos placas. Sino cada placa funcionaran de manera independiente. El siguiente paso consiste en elegir el modo de dificultad deseada. Hemos programa tres niveles de dificultad para un máximo de 10 turnos. Disponemos de otros 10 segundos para elegir modo mediante el mismo pulsador central (pin19) y se visualiza mediante tres leds conectados a los pines 16, 17, 18. A continuación describimos las cabeceras de las funciones: int seleccionaplayer(); int seleccionadificultad(); int hazturno(int turnos, int aleatorio[],int error); void apagarLEDS(); void leeentrada(int vectoruser[],int turnos); void muestravector(int vector[],int turnos); int comparavector(int vector_random[], int vector_user[], int turnos); void segmentos_off(); void segmentos_on(int number); void receiveEvent(int howMany); void requestEvent(); 4.2. Modo 1 player . . . if(prueva==0) { player=seleccionaplayer(); } if (player==1) { for(i=0;i<30;i++) { aleatorio[i]=random(8,12); } dificultad=seleccionadificultad(); for(turnos=1;turnos<10*dificultad;turnos++) { aux=hazturno(turnos*dificultad,aleatorio,aux); if (aux==1) turnos=0; } } . . . Fig. 12 Extracto de código modo 1player. Este extracto de código es para el modo 1 jugador y pertenece a la parte “void loop()”. Primero llamamos a la función “int seleccionplayer()” que nos devuelve el resultado de 11 elegir player 1. Segundo generamos el vector “int aleatorio*30+” y mediante la función “random(8,12)”. Recordemos que el ledAzul corresponde al pin 8, el ledVerde al pin 9, el ledRojo al pin 10 y el ledAmarillo al pin11. El tercer paso consiste en llamar a la función “int seleccionadificultad()” que nos devuelve el nivel de dificultad elegido. Una vez elegido el player 1 y el nivel de dificultad comienza el juego. El turno lo controlamos mediante un bucle “for(turnos=1;turnos<10*dificultad;turnos++)”, la función “int hazturno(int turnos, int aleatorio*+,int aux)” es la que se encarga de realizar el juego: muestra el vector aleatorio, recoge el botón pulsado, muestra la secuencia pulsada por el player y comprueba si es correcto sino lo es devuelve un auxiliar y parpadean los 4 leds tres veces consecutivas. Por supuesto el juego se reinicia. A continuación mostramos el código de la función “hazturno(,,,)” ya que es la principal: int hazturno(int turnos, int aleatorio[],int error) { int n; int vectoruser[30]; muestravector(aleatorio,turnos); leeentrada(vectoruser,turnos); muestravector(vectoruser,turnos); error=comparavector(aleatorio,vectoruser,turnos); if(error==1) { for(n=0;n<3;n++) { digitalWrite(ledAZUL,HIGH); digitalWrite(ledVERDE,HIGH); digitalWrite(ledROJO,HIGH); digitalWrite(ledAMARILLO,HIGH); delay(200); digitalWrite(ledAZUL,LOW); digitalWrite(ledVERDE,LOW); digitalWrite(ledROJO,LOW); digitalWrite(ledAMARILLO,LOW); delay(200); } } return(error); } Fig. 13 Extracto del código de la función “int hazturno(int turnos, in t aleatorio[],int error) 4.3. Modo 2 player Esta ha sido la parte mas conflictiva del proyecto. Las placas wiring disponen de 2 puertos tipo serie para comunicarse con hardware externo (PC junto a processing), estos puertos se configuran en la parte “vodi setup()” del siguiente modo (ver FIG. 14): 12 Void setup() { Serial.begin(9600); //puerto serie USB o pines 37 y 36 Serial1.begin(9600);// puerto serie pins 3 (Rx) y 4 (Tx) . . . } Void loop() { . . . Int val = Serial1.read();//para Rx Serial1.print(val);//para Tx . . . } Fig. 14 Código puerto serie. En un primera versión se intento el puerto serie descrito en la FIG. 14 pero no fue posible enviar y recibir debido a una falta de sincronismo entre las dos placas. Este módo está más indicado para enviar info al PC y mediante software Procesing capturar estos datos para un procesado en PC. Una vez descartada esta posibilidad, la otra librería que nos proporciona el entorno Wiring para comunicación entre placas es el interfaz llamado TWI (Two Wire Interface) que usa el nombre Wire y los pines 0 (SCL) y 1 (SDA). Este interfaz es conocido por los electrónicos como i2c. Se establece un dispositivo como master y los demás dispositivos (pueden ser varios) como esclavos. Como contrapartida, hay que aclarar que los códigos de cada placa son diferentes (una para la placa maestra ver Fig. 16 y otra esclava ver FIG. 15). Void setup() { Wire.begin(2); //dispositivo esclavo con identificador 2 Wire.onRequest(requestEvent); // evento petición tx esclavomaster Wire.onReceive(receiveEvent); // evento comunicación masteresclavo . . . } Void loop() { . . . if(player==2) { if(prueva==0) { dificultad=seleccionadificultad(); prueva=1; } if(aviso==1) { int turnosaux=0; turnos++; turnosaux=turnos*dificultad; error=hazturno(turnosaux,aleatorio,error); delay(500); turnos++; aviso=0; digitalWrite(pinslave,HIGH);//pin para indicar a master que has terminado turno, y le toca a el. } } } void receiveEvent(int howMany) { int i=0; int error=0; if(primero==0) { 13 while(1<Wire.available()) { aleatorio[i] = Wire.receive();// recibe vector aleatorio de master. i++; } } } void requestEvent() { aviso=1; digitalWrite(pinslave,LOW); //pin para indicar a master que estas haciendo el turno (esclavo). Wire.send(error); // responde al master con el envio variable error. } Fig. 15 Exctracto código TWI dispositivo esclavo. Void setup() { Wire.begin();//dispositivo como maestro. . . . } Void loop() { . . . if(player==2) { int error=0; dificultad=seleccionadificultad(); Wire.beginTransmission(2);//comenzamos transmisión al dispositivo 2. for(i=0;i<30;i++) { Wire.send(aleatorio[i]);//enviamos aleatorio al esclavo } Wire.endTransmission();//cerramos la conexión while(turnos<10) { if(aviso==0) { error=hazturno(turnos*dificultad,aleatorio,error); Wire.requestFrom(2,2);//solicitamos envio del esclavo. error=Wire.receive(); aviso=1; turnos=turnos+2; } else { if(digitalRead(pinslave)==HIGH)//si es cierto le toca turno a master aviso=0; } } } } FIG. 16 Extracto código TWI dispositivo maestro. Hemos tenido que utilizar la ayuda de un pin auxiliar llamado pinslave y conectado al pin 7. En modo INPUT en código maestro y OUTPUT en en código esclavo. Con este pin hemos establecido un sistema de turnos mediante la variable “int aviso”. Cuando queremos enviar info desde el master al esclavo utilizamos la función “Wire.send(aleatorio*i+)”, se genera un evento en la placa esclavo con nombre “void receiveEvent(int howMany)” que se encarga de rellenar el vector aleatorio generado en placa master. Para solictar info desde el esclavo al master utilizamos la función “Wire.requestFrom(2,2)” donde el primer 2 indica el dispositivo al que pedimos la info 14 y el segundo 2 indica el tamaño en bytes que esperamos recibir. En el código esclavo se atiende al evento con “void requestEvent()” activamos pinslave a valor HIGH cuando finaliza el turno en esclavo. Para dicha comunicación vamos a utilizar tres pines, el pin 0, el pin 1 y el pin 7. Los códigos completos se pueden consultar en el anexo, al final de este documento. 5. Presupuesto Componentes 2 Bolsas 36 Pins conexion Pila Alcalina 9v Clip portapilas 9v Pulsador grande start Resistencias, Leds, Condensadores, Pulsadores,… Caja metraquilato con tapa 160x1 Placas metraquilato redondas o cuadradas (4 unidades de 4) Conectores alimentación 1 Placa de baquelita 1 metro cable rectil TOTAL: Precio un simon 2.28€ 4.59€ 0.16€ 0.68€ GRATIS Precio dos simon 4.56€ 9.18€ 0.32€ 1.36€ GRATIS 16€ 3.7€ 32€ 7.40€ 0.14€ 4.75€ 1.30€ 0.28€ 9.5€ 2.60€ 23.28€ 47.7€ Tabla 1 Presupuesto proyecto. El coste total para realizar un simon es de 23.28€ y el doble 47.7€ en el caso de implementar los dos simon. Lo más caro del presupuesto es la caja de metraquilato donde vamos a alojar las placas Wiring con un precio de 16€ la unidad. Existen toda una serie de componentes que no son necesarios comprar, ya que como estudiantes de Ing. Telecos disponemos de resistencias, leds, condensadores, cables, pulsadores,… de asignaturas anteriores. Tienda consultada: Diotronic. La caja de metraquilato es de color transparente y dispone de una tapa en la parte superior facilitando la manipulación del contenido. Tienda consultada: Servei Estació. 6. Conclusiones Es la primera vez que nos enfrentamos a un proyecto que incluya software y hardware. El entorno Wiring nos ha proporcionado el conocimiento de un nuevo lenguaje bastante intuitivo (poco complejo) y de muy alto nivel, ya que se basa en el uso de librerías proporcionadas por Wiring. El diseño analógico no ha sido nada trivial, ya que hemos tenido que realizar diversas pruebas desde cero (variación del esquema electrónico inicial). Realizar el hardware en cajas de metraquilato con la ayuda de una dremel ha sido un proceso muy laborioso y costos en términos de horas. 15 Como conclusión destacar que es un proyecto para realizar en grupo de cuatro personas, como mínimo. Y es necesario una cordinación entre miembros P2P. Eso sí, nos hemos divertido, hemos disfrutado y hemos alcanzado la mitad de objetivos propuestos: una caja de metraquilato y placa protoboard, modo un jugador y modo dos jugadores. Nos ha faltado tiempo para añadirle el BCD 7 segmentos para indicar turnos y sonido a cada botón. 7. Anexo código placa esclavo int prueva=0; int aviso=0; int error=0; int player = 1; int dificultad=1; int turnos=1;//variable global para el numero de turnos (maximos 10 turnos) int ledAZUL=8;//8 int ledVERDE=9;//9 int ledROJO=10;//10 int ledAMARILLO=11;//11 int botonAZUL=12;//12 int botonVERDE=13;//13 int botonROJO=14;//14 int botonAMARILLO=15;//15 int ledSTART=23; int ledplayer1=20; int ledplayer2=21; //int vectoruser[30]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int aleatorio[30]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int ledDificultad1=16; int ledDificultad2=17; int ledDificultad3=18; int botonDificultad=19; int pinslave=7; int primero=0; //int ruido=0; void receiveEvent(int howMany) { int i=0; int error=0; if(primero==0) { while(1<Wire.available()) { aleatorio[i] = Wire.receive(); // receive byte as an integer //Serial.print(aleatorio[i]); i++; } } } void requestEvent() { aviso=1; digitalWrite(pinslave,LOW); Wire.send(error); // respond with message of 6 bytes } int seleccionaplayer() { int dif=0;//variable para leds dificultad int aux=1;//variable para nivel dificultad. int time1=(int)(millis());//variable milisegundos tiempo de la aplicación ejecutada int time=time1; digitalWrite(ledplayer1,HIGH); 16 while(time<time1+10000)//10 segundos para elegir modo de dificultad. { if(digitalRead(botonDificultad)==HIGH) { delay(500); if(digitalRead(botonDificultad)==LOW) { dif++; if(dif==1)//dificultad facil, se avanza de uno en uno. { digitalWrite(ledplayer1,HIGH); digitalWrite(ledplayer2,LOW); aux=1; } if(dif==2)//difultad dificil, se avanza de tres en tres. { digitalWrite(ledplayer2,HIGH); dif=0; aux=2; } } } time=(int)millis(); } return(aux); } int seleccionadificultad() { int dif=0;//variable para leds dificultad int aux=1;//variable para nivel dificultad. int time1=(int)(millis());//variable milisegundos tiempo de la aplicación ejecutada int time=time1; digitalWrite(ledDificultad1,HIGH); while(time<time1+10000)//10 segundos para elegir modo de dificultad. { if(digitalRead(botonDificultad)==HIGH) { delay(500); if(digitalRead(botonDificultad)==LOW) { dif++; if(dif==1)//dificultad facil, se avanza de uno en uno. { digitalWrite(ledDificultad1,HIGH); digitalWrite(ledDificultad2,LOW); digitalWrite(ledDificultad3,LOW); aux=1; } if(dif==2)//difucltad media, se avanza de dos en dos. { digitalWrite(ledDificultad2,HIGH); digitalWrite(ledDificultad3,LOW); aux=2; } if(dif==3)//difultad dificil, se avanza de tres en tres. { digitalWrite(ledDificultad3,HIGH); dif=0; aux=3; } } } time=(int)millis(); } 17 return(aux); } int hazturno(int turnos, int aleatorio[],int error) { int n; int vectoruser[30]; Serial.println("ANTES"); muestravector(aleatorio,turnos); Serial.println(aleatorio[0]); leeentrada(vectoruser,turnos); muestravector(vectoruser,turnos); error=comparavector(aleatorio,vectoruser,turnos); if(error==1) { for(n=0;n<3;n++) { digitalWrite(ledAZUL,HIGH); digitalWrite(ledVERDE,HIGH); digitalWrite(ledROJO,HIGH); digitalWrite(ledAMARILLO,HIGH); delay(200); digitalWrite(ledAZUL,LOW); digitalWrite(ledVERDE,LOW); digitalWrite(ledROJO,LOW); digitalWrite(ledAMARILLO,LOW); delay(200); } } return(error); } void apagarLEDS() { digitalWrite(ledAZUL,LOW); digitalWrite(ledVERDE,LOW); digitalWrite(ledROJO,LOW), digitalWrite(ledAMARILLO,LOW); } void leeentrada(int vectoruser[],int turnos) { int i; for ( i=0;i<turnos;i++) { if( digitalRead(botonAZUL)==HIGH ) { delay(50); if(digitalRead(botonAZUL)==LOW) { vectoruser[i]=8; continue; } } if( digitalRead(botonVERDE)==HIGH ) { delay(50); if(digitalRead(botonVERDE)==LOW) { vectoruser[i]=9; continue; } } if( digitalRead(botonROJO)==HIGH ) { delay(50); if(digitalRead(botonROJO)==LOW) 18 { vectoruser[i]=10; continue; } } if( digitalRead(botonAMARILLO)==HIGH ) { delay(50); if(digitalRead(botonAMARILLO)==LOW) { vectoruser[i]=11; continue; } } i--; } } void muestravector(int vector[],int turnos) { int i; int t=(int)millis(); for(i=0;i<turnos;i++) { digitalWrite(vector[i],HIGH); delay(500); digitalWrite(vector[i],LOW); delay(500); } } int comparavector(int vector_random[], int vector_user[], int turnos) { int n; int a=0; for(n=0;n<turnos;n++) { if(vector_random[n]!=vector_user[n]) a=1; } return a; } void segmentos_off()//funcion q apaga el 7segmentos { for(int i=0; i<8; i++) { digitalWrite(i, HIGH); } } void segmentos_on(int number)//funcion para el 7segmentos { if(number==0) { digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==1) { digitalWrite(5, LOW); digitalWrite(3, LOW); } if(number==2) 19 { digitalWrite(7, digitalWrite(4, digitalWrite(6, digitalWrite(0, digitalWrite(1, HIGH); HIGH); HIGH); HIGH); HIGH); } if(number==3) { digitalWrite(4, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==4) { digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(7, HIGH); digitalWrite(2, HIGH); } if(number==5) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(7, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==6) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==7) { digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(2, HIGH); } if(number==8) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==9) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } delay(1000); // waits for 1000 milli seconds //number = number + 1; // increments the variable to show if(number > 9) { // check for the range, if greater then 9 goes back to 0s number = 0; 20 } } void setup() { Serial.begin(9600); //Serial1.begin(9600); Wire.begin(2); Wire.onRequest(requestEvent); Wire.onReceive(receiveEvent); pinMode(ledAZUL,OUTPUT); pinMode(ledVERDE,OUTPUT); pinMode(ledROJO,OUTPUT); pinMode(ledAMARILLO,OUTPUT); pinMode(botonAZUL,INPUT); pinMode(botonVERDE,INPUT); pinMode(botonROJO,INPUT); pinMode(botonAMARILLO,INPUT); pinMode(ledDificultad1,OUTPUT); pinMode(ledDificultad2,OUTPUT); pinMode(ledDificultad3,OUTPUT); pinMode(botonDificultad,INPUT); pinMode(ledSTART,OUTPUT); pinMode(ledplayer1,OUTPUT); pinMode(ledplayer2,OUTPUT); pinMode(pinslave,OUTPUT); //pinMode(ruido,OUTPUT); } void loop() { int i=0; int n=0; int aux=0; int a; int sound; digitalWrite(ledSTART,HIGH); //int prueva[10]={8,9,10,11,8,9,10,11,8,8}; if(prueva==0) {player=seleccionaplayer(); Serial.println(player); } if (player==1) { for(i=0;i<30;i++) { aleatorio[i]=random(8,12); } dificultad=seleccionadificultad(); for(turnos=1;turnos<10*dificultad;turnos++) { aux=hazturno(turnos*dificultad,aleatorio,aux); if (aux==1) turnos=0; } } if(player==2) { if(prueva==0) { dificultad=seleccionadificultad(); prueva=1; 21 } if(aviso==1) { int turnosaux=0; turnos++; turnosaux=turnos*dificultad; Serial.println(turnosaux); error=hazturno(turnosaux,aleatorio,error); delay(500); turnos++; aviso=0; digitalWrite(pinslave,HIGH); } } } Fig. 17 Código completo placa wiring esclavo. 8. Anexo código placa maestro int player = 1; int aviso=0; int dificultad=1; int turnos=1;//variable global para el numero de turnos (maximos 10 turnos) int ledAZUL=8;//8 int ledVERDE=9;//9 int ledROJO=10;//10 int ledAMARILLO=11;//11 int botonAZUL=12;//12 int botonVERDE=13;//13 int botonROJO=14;//14 int botonAMARILLO=15;//15 int ledSTART=23; int ledplayer1=20; int ledplayer2=21; //int vectoruser[30]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int aleatorio[30]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int ledDificultad1=16; int ledDificultad2=17; int ledDificultad3=18; int botonDificultad=19; int pinslave=7; //int ruido=0; int seleccionaplayer() { int dif=0;//variable para leds dificultad int aux=1;//variable para nivel dificultad. int time1=(int)(millis());//variable milisegundos tiempo de la aplicación ejecutada int time=time1; digitalWrite(ledplayer1,HIGH); while(time<time1+10000)//10 segundos para elegir modo de dificultad. { if(digitalRead(botonDificultad)==HIGH) { delay(500); if(digitalRead(botonDificultad)==LOW) { dif++; if(dif==1)//dificultad facil, se avanza de uno en uno. { digitalWrite(ledplayer1,HIGH); digitalWrite(ledplayer2,LOW); aux=1; } if(dif==2)//difultad dificil, se avanza de tres en tres. { 22 digitalWrite(ledplayer2,HIGH); dif=0; aux=2; } } } time=(int)millis(); } return(aux); } int seleccionadificultad() { int dif=0;//variable para leds dificultad int aux=1;//variable para nivel dificultad. int time1=(int)(millis());//variable milisegundos tiempo de la aplicación ejecutada int time=time1; digitalWrite(ledDificultad1,HIGH); while(time<time1+10000)//10 segundos para elegir modo de dificultad. { if(digitalRead(botonDificultad)==HIGH) { delay(500); if(digitalRead(botonDificultad)==LOW) { dif++; if(dif==1)//dificultad facil, se avanza de uno en uno. { digitalWrite(ledDificultad1,HIGH); digitalWrite(ledDificultad2,LOW); digitalWrite(ledDificultad3,LOW); aux=1; } if(dif==2)//difucltad media, se avanza de dos en dos. { digitalWrite(ledDificultad2,HIGH); digitalWrite(ledDificultad3,LOW); aux=2; } if(dif==3)//difultad dificil, se avanza de tres en tres. { digitalWrite(ledDificultad3,HIGH); dif=0; aux=3; } } } time=(int)millis(); } return(aux); } int hazturno(int turnos, int aleatorio[],int error) { int n; int vectoruser[30]; muestravector(aleatorio,turnos); leeentrada(vectoruser,turnos); muestravector(vectoruser,turnos); error=comparavector(aleatorio,vectoruser,turnos); if(error==1) { for(n=0;n<3;n++) { digitalWrite(ledAZUL,HIGH); digitalWrite(ledVERDE,HIGH); 23 digitalWrite(ledROJO,HIGH); digitalWrite(ledAMARILLO,HIGH); delay(200); digitalWrite(ledAZUL,LOW); digitalWrite(ledVERDE,LOW); digitalWrite(ledROJO,LOW); digitalWrite(ledAMARILLO,LOW); delay(200); } } return(error); } void apagarLEDS() { digitalWrite(ledAZUL,LOW); digitalWrite(ledVERDE,LOW); digitalWrite(ledROJO,LOW), digitalWrite(ledAMARILLO,LOW); } void leeentrada(int vectoruser[],int turnos) { int i; for ( i=0;i<turnos;i++) { if( digitalRead(botonAZUL)==HIGH ) { delay(50); if(digitalRead(botonAZUL)==LOW) { vectoruser[i]=8; continue; } } if( digitalRead(botonVERDE)==HIGH ) { delay(50); if(digitalRead(botonVERDE)==LOW) { vectoruser[i]=9; continue; } } if( digitalRead(botonROJO)==HIGH ) { delay(50); if(digitalRead(botonROJO)==LOW) { vectoruser[i]=10; continue; } } if( digitalRead(botonAMARILLO)==HIGH ) { delay(50); if(digitalRead(botonAMARILLO)==LOW) { vectoruser[i]=11; continue; } } i--; } } void muestravector(int vector[],int turnos) { 24 int i; for(i=0;i<turnos;i++) { digitalWrite(vector[i],HIGH); delay(500); digitalWrite(vector[i],LOW); delay(500); } } int comparavector(int vector_random[], int vector_user[], int turnos) { int n; int a=0; for(n=0;n<turnos;n++) { if(vector_random[n]!=vector_user[n]) a=1; } return a; } void segmentos_off()//funcion q apaga el 7segmentos { for(int i=0; i<8; i++) { digitalWrite(i, HIGH); } } void segmentos_on(int number)//funcion para el 7segmentos { if(number==0) { digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==1) { digitalWrite(5, LOW); digitalWrite(3, LOW); } if(number==2) { digitalWrite(7, HIGH); digitalWrite(4, HIGH); digitalWrite(6, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); } if(number==3) { digitalWrite(4, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==4) { digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(7, HIGH); digitalWrite(2, HIGH); 25 } if(number==5) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(7, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==6) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==7) { digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(2, HIGH); } if(number==8) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(0, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } if(number==9) { digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(1, HIGH); digitalWrite(2, HIGH); } delay(1000); // waits for 1000 milli seconds //number = number + 1; // increments the variable to show if(number > 9) { // check for the range, if greater then 9 goes back to 0s number = 0; } } void setup() { Serial.begin(9600); Serial1.begin(9600); pinMode(ledAZUL,OUTPUT); pinMode(ledVERDE,OUTPUT); pinMode(ledROJO,OUTPUT); pinMode(ledAMARILLO,OUTPUT); pinMode(botonAZUL,INPUT); pinMode(botonVERDE,INPUT); pinMode(botonROJO,INPUT); pinMode(botonAMARILLO,INPUT); pinMode(ledDificultad1,OUTPUT); pinMode(ledDificultad2,OUTPUT); pinMode(ledDificultad3,OUTPUT); pinMode(botonDificultad,INPUT); pinMode(ledSTART,OUTPUT); pinMode(ledplayer1,OUTPUT); 26 pinMode(ledplayer2,OUTPUT); //pinMode(ruido,OUTPUT); pinMode(pinslave,INPUT); Wire.begin(); } void loop() { int i=0; int n=0; int aux=0; int a; int sound; digitalWrite(ledSTART,HIGH); //int prueva[10]={8,9,10,11,8,9,10,11,8,8}; player=seleccionaplayer(); Serial.println(player); for(i=0;i<30;i++) { aleatorio[i]=random(8,12); } if (player==1) { for(i=0;i<30;i++) { aleatorio[i]=random(8,12); } dificultad=seleccionadificultad(); for(turnos=1;turnos<10;turnos++) { aux=hazturno(turnos*dificultad,aleatorio,aux); if (aux==1) turnos=1; } } if(player==2) { int error=0; dificultad=seleccionadificultad(); Wire.beginTransmission(2); for(i=0;i<30;i++) { Wire.send(aleatorio[i]); } Wire.endTransmission(); while(turnos<10) { if(aviso==0) { error=hazturno(turnos*dificultad,aleatorio,error); Wire.requestFrom(2,2); error=Wire.receive(); aviso=1; turnos=turnos+2; } else { if(digitalRead(pinslave)==HIGH) aviso=0; } //delay(3000*turnos*dificultad); } } } Fig. 18 Codigo completo placa wiring maestro. 27