Proyecto Arduino. Guardar la señal de entrada recibida

Hola, estoy intentando hacer una especie de Simón Dice en Arduino pero me ha surgido un problema; cuando empieza la secuencia se me enciende el correspondiente led del valor aleatorio que toca, pero a la hora de que el usuario encienda ese mismo led suceden 2 cosas:

  1. O el led se enciende pero lo detecta como error y comienza la secuencia error.
  2. El led directamente no se enciende.

He comprobado las conexiones mirando si cada pulsador enciende al led correspondiente y eso funciona perfecto así que el error debe ser de código, pero después de más de una semana intentandolo no encuentro el fallo; alguien podría aportarme alguna idea. Adjunto el mapa del cableado y todo el código que tengo hasta el momento.

/* implementar un juego “Simón” con cuatro LEDS y cuatro pulsadores; 
el programa iluminará los LED en una secuencia aleatoria, y el
jugador deberá reproducirla; el juego acaba con los cuatro LED destelleando
durante 5 segundos (a intervalo de un segundo), cuando el jugador se
equivoca. Presentaremos el nº de aciertos que ha tenido*/

const int redS = 13;
const int redE = 2;
const int blueS = 12;
const int blueE = 3;
const int yellowS = 11;
const int yellowE = 4;
const int greenS = 10;
const int greenE = 5;


int arrayE[300];
int arrayS[300];
int secuencia=1;

void generaAleatorios(){//generamos al principio toda la secuencia que puede llegar a realizar
  for (int i = 0; i< 300; i++){
    int n = random(4);
    arrayS[i]=n;
  }
}

void simonDice() {//muestra la secuencia nivel a nivel
  for (int i = 0; i<secuencia; i++){
    //le asignamos a cada color un número de los aleatorios que contiene el array de salida
    if (arrayS[i] == 1) {
      digitalWrite (redS, HIGH);
      delay(1000);
      digitalWrite (redS, LOW);
      delay(1000);
    }
    
     if (arrayS[i] == 2) {
      digitalWrite (blueS, HIGH);
      delay(1000);
      digitalWrite (blueS, LOW);
      delay(1000);
    }
    
     if (arrayS[i] == 3) {
      digitalWrite (yellowS, HIGH);
      delay(1000);
      digitalWrite (yellowS, LOW);
      delay(1000);
    }
    
     if (arrayS[i] == 4) {
      digitalWrite (greenS, HIGH);
      delay(1000);
      digitalWrite (greenS, LOW);
      delay(1000);
    }
  }
}

void playerDice(){
  int flag = 0;//condicionante que nos permite estar dentro del while
  int estadoR = digitalRead(redE);
  int estadoB = digitalRead(blueE);
  int estadoY = digitalRead(yellowE);
  int estadoG = digitalRead(greenE);
  for(int i = 0; i < 300; i++){
    flag = 0;//siempre que salimos se vuelve a poner a cero
    while(flag == 0){//mientras el condicionante valga 0 estaremos dentro del while
      if(estadoR == HIGH){
        digitalWrite(redS, HIGH);
        arrayE[i] = 1;
        flag = 1;
        delay(1000);
        if(arrayE[i] != arrayS[i]){// si no se cumple la igual entra en la función error
          error();
        }
      }
      else{
        digitalWrite(redS, LOW);
      }
      if(estadoB == HIGH){
        digitalWrite(blueS, HIGH);
        arrayE[i] = 2;
        flag = 1;
        delay(1000);
        if(arrayE[i] != arrayS[i]){
          error();
        }
      }
      else{
        digitalWrite(blueS, LOW);
      }
      if(estadoY == HIGH){
        digitalWrite(yellowS, HIGH);
        arrayE[i] = 3;
        flag = 1;
        delay(1000);
        if(arrayE[i] != arrayS[i]){
          error();
        }
      }
      else{
        digitalWrite(yellowS, LOW);
      }
      if(estadoG == HIGH){
        digitalWrite(greenS, HIGH);
        arrayE[i] = 4;
        flag = 1;
        delay(1000);
        if(arrayE[i] != arrayS[i]){
          error();
        }
      }
      else{
        digitalWrite(greenS, LOW);
      }
    }
  }
  correcto();//cuando se cumplen todos los ciclos 
}
    
void correcto(){//función para aumentar un ciclo
  if (secuencia < 300){
    secuencia++;
  }
  delay(500);
}

void error(){
  //secuencia de salida
  for (int j = 0; j < 5; j++){
    digitalWrite(redS, HIGH);
    digitalWrite(blueS, HIGH);
    digitalWrite(yellowS, HIGH);
    digitalWrite(greenS, HIGH);
    delay(500);
    
    digitalWrite(redS, LOW);
    digitalWrite(blueS, LOW);
    digitalWrite(yellowS, LOW);
    digitalWrite(greenS, LOW);
    delay(500);
  }
  secuencia = secuencia - 1;
  Serial.print("Has llegado al nivel: ");
  Serial.println(secuencia);
  exit(0);
}

void setup() {
  
  Serial.begin(9600);
  //definimos las entradas y salidas
  pinMode(redS, OUTPUT);
  pinMode(redE, INPUT);
  pinMode(blueS, OUTPUT);
  pinMode(blueE, INPUT);
  pinMode(yellowS, OUTPUT);
  pinMode(yellowE, INPUT);
  pinMode(greenS, OUTPUT);
  pinMode(greenE, INPUT);
}

void loop(){
  if (secuencia == 1){// solo la primera vez
    generaAleatorios();
    simonDice();
    delay(200);
    playerDice();
  }
  if (secuencia !=1){// el resto de ciclos
    simonDice();
    delay(200);
    playerDice();
  }
}

Hola, nada mas enpezar veo que en la funcion simon dice() haces comparaciones con valores del 1 al 4, pero en el if que llena el array estas generando numeros del 0 al 3.
debes cambiar a " int n = random (1, 5); . A ver si solo es de eso, miratelo.
Lo siento es tarde y no tengo ganas de leer mas codigo, me voy a la cama,.
Buenas noches.

Lo he cambiado pero nada, sigue sin funcionar

Hola, Si estoy entendiendo bien el código , ¿no crees que en la función playerDice el for deberia ser el mismo que el de la funciön simonDice?. es decir con i<secuencia.
No entiendo lo que quieres hacer en la funcion error con exit(0); explicamelo ampliamente.
Saludos.

Si, tienes razón acabo de corregir lo de la función playerDice() corrigiendo lo de i<secuencia y he de decir que he visto un progreso. Se me ha encendido la luz verde, he conseguido encenderla activando y pulsador y se me ha encendido la azul; a partir de aí ya nada. Eso sí, la verde tendría que haberse vuelto a encender antes que el azul… sigo sin saber qué es lo que tengo mal respecto a eso.

En la función error solo entrariamos cuando el usuario falla, se encienden todas las luces parpadeando para indicarle al usuario el fin de la partida y con la función exit(0) le digo al programa que finalice.

¿Que finalice?, ¿un reset y reinicio al principio?, porque ahy lo que hace es retornar a la funcion que lo llamo.

vale, lo he solucionado, pero me sigue ocurriendo lo mismo que he descrito antes

Hola.
El problema que tienes es que lees los puertos fuera del for y del wile. Cambia tus if del dentro del wile a: " if(digitalRead(colorE) == HIGH){ " y elimina las variables correspondientes.
Saludos.

1 Like

Hola, le he hecho varias modificaciones y sigo con problemas. Gracias al aporte de gonpezzi ahora las luces se encienden perfectamente. Uno de los problemas ahora es que nada más pulso la luz a la que le corresponde encenderse la función simón dice no muestra la secuencia desde el principio, si no desde donde lo habíamos dejado; por ejemplo si estamos en la secuencia 2, solo enciende la luz correspondiente a la posición 2.

const int redS = 13;
const int redE = 2;
const int blueS = 12;
const int blueE = 3;
const int yellowS = 11;
const int yellowE = 4;
const int greenS = 10;
const int greenE = 5;


int arrayE[300];
int arrayS[300];
int secuencia=1;

void generaAleatorios(){//generamos al principio toda la secuencia que puede llegar a realizar
  for (int i = 0; i< 300; i++){
    int n = random(4);
    arrayS[i]=n;  
  }
}

void simonDice() {//muestra la secuencia nivel a nivel
  for (int i = 0; i<secuencia; i++){
    //le asignamos a cada color un número de los aleatorios que contiene el array de salida
    if (arrayS[i] == 0) {
      digitalWrite (redS, HIGH);
      delay(500);
      digitalWrite (redS, LOW);
      delay(500);
    }
    
     if (arrayS[i] == 1) {
      digitalWrite (blueS, HIGH);
      delay(500);
      digitalWrite (blueS, LOW);
      delay(500);
    }
    
     if (arrayS[i] == 2) {
      digitalWrite (yellowS, HIGH);
      delay(500);
      digitalWrite (yellowS, LOW);
      delay(500);
    }
    
     if (arrayS[i] == 3) {
      digitalWrite (greenS, HIGH);
      delay(500);
      digitalWrite (greenS, LOW);
      delay(500);
    }
  }
}

void playerDice(){
  int flag = 0;
  for(int i = 0; i < secuencia; i++){
    flag = 0;//siempre que salimos se vuelve a poner a cero
    while(flag == 0){//mientras el condicionante valga 0 estaremos dentro del while
      if(digitalRead(redE) == HIGH){
        digitalWrite(redS, HIGH);
        arrayE[i] = 0;
        //delay(500);
        flag = 1; 
      }
      else{
        digitalWrite(redS, LOW);
      }
      if(digitalRead(blueE) == HIGH){
        digitalWrite(blueS, HIGH);
        arrayE[i] = 1;
        //delay(500);
        flag = 1;   
      }
      else{
        digitalWrite(blueS, LOW);
      }
      if(digitalRead(yellowE) == HIGH){
        digitalWrite(yellowS, HIGH);
        arrayE[i] = 2;
        //delay(500);
        flag = 1;
        
      }
      else{
        digitalWrite(yellowS, LOW);
      }
      if(digitalRead(greenE) == HIGH){
        digitalWrite(greenS, HIGH);
        arrayE[i] = 3;
        //delay(500);
        flag = 1;
        
      }
      else{
        digitalWrite(greenS, LOW);
      }
    }
  } 
}

void comparaArrays(){
  Serial.println("Estoy comparando...");
  for (int i = 0; i < secuencia; i++){
    if(arrayE[i] != arrayS[i]){
      error();
    }
  }
  correcto();
}
    
void correcto(){//función para aumentar un ciclo
  Serial.println("secuencia correcta. Continua.");
  if (secuencia < 300){
    secuencia++;
  }
  delay(500);
}

void error(){
  //secuencia de salida
  for (int j = 0; j < 5; j++){
    digitalWrite(redS, HIGH);
    digitalWrite(blueS, HIGH);
    digitalWrite(yellowS, HIGH);
    digitalWrite(greenS, HIGH);
    delay(500);
    
    digitalWrite(redS, LOW);
    digitalWrite(blueS, LOW);
    digitalWrite(yellowS, LOW);
    digitalWrite(greenS, LOW);
    delay(500);
  }
  secuencia = secuencia - 1;
  Serial.print("Has llegado al nivel: ");
  Serial.println(secuencia);
  exit(0);
}

void setup() {
  
  Serial.begin(9600);
  //definimos las entradas y salidas
  pinMode(redS, OUTPUT);
  pinMode(redE, INPUT);
  pinMode(blueS, OUTPUT);
  pinMode(blueE, INPUT);
  pinMode(yellowS, OUTPUT);
  pinMode(yellowE, INPUT);
  pinMode(greenS, OUTPUT);
  pinMode(greenE, INPUT);
}

void loop(){
  if (secuencia == 1){// solo la primera vez
    generaAleatorios();
    simonDice();
    delay(200);
    playerDice();
  }
  if (secuencia !=1){// el resto de ciclos
    simonDice();
    delay(200);
    playerDice();
    delay(500);
  }
}

Antes independientemente de lo que pasase siempre entraba en la función error() así que he probado a comprobar si los arrays son iguales en otra función, pero el programa nunca entra en ella y por consiguiente tampoco en correcto() ni en error().

vale, me he dado cuenta de que nunca le he dicho a Arduino que entre en la funcion comparaArrays(). Ahora si entra en todas las funciones correspondientes, pero sigue mostrandome sólo la última luz de la secuencia.

Hola.
Me gustaba mas la lógica del primer código y en esa me he basado, en el segundo lo lias ,(a mi parecer), un poco mas. Asi que me baso en el primero.
Sigo sin entender que quieres hacer con exit(0) , eso no existe en el c de arduino por mas librerias que incluyas, asi que lo cambio por un reset.
Si no me he equivocado al reestablecer el código, ya que para las pruebas no he usado led, solo dos botones, serialprint, etc esto te deberia funcionar:

#define RESET asm("jmp (0x0000)")

const int redS = 13;
const int redE = 2;
const int blueS = 12;
const int blueE = 3;
const int yellowS = 11;
const int yellowE = 4;
const int greenS = 10;
const int greenE = 5;


int arrayE[300];
int arrayS[300];
int secuencia;
int flag;

void generaAleatorios() { //generamos al principio toda la secuencia que puede llegar a realizar
  for (int i = 0; i < 300; i++) {
    int n = random(4);
    arrayS[i] = n;
  }
}

void simonDice() {//muestra la secuencia nivel a nivel
  for (int i = 0; i <= secuencia; i++) {
    //le asignamos a cada color un número de los aleatorios que contiene el array de salida 
    if (arrayS[i] == 0) {
      digitalWrite (redS, HIGH);
      delay(500);
      digitalWrite (redS, LOW);
      delay(500);
    }

    if (arrayS[i] == 1) {
      digitalWrite (blueS, HIGH);
      delay(500);
      digitalWrite (blueS, LOW);
      delay(500);
    }

    if (arrayS[i] == 2) {
      digitalWrite (yellowS, HIGH);
      delay(500);
      digitalWrite (yellowS, LOW);
      delay(500);
    }

    if (arrayS[i] == 3) {
      digitalWrite (greenS, HIGH);
      delay(500);
      digitalWrite (greenS, LOW);
      delay(500);
    }
  }
}

void playerDice() {
  for (int i = 0; i <= secuencia; i++) {
    flag = 0;//siempre que salimos se vuelve a poner a cero
    while (flag == 0) { //mientras el condicionante valga 0 estaremos dentro del while
      if (digitalRead(redE) == HIGH) {
        digitalWrite(redS, HIGH);
        arrayE[i] = 0;
        if (arrayE[i] != arrayS[i]) { // si no se cumple la igual entra en la función error
          error();
        }
        delay(500);
        flag = 1;
      }
      else {
        digitalWrite(redS, LOW);
      }
      if (digitalRead(blueE) == HIGH) {
        digitalWrite(blueS, HIGH);
        arrayE[i] = 1;
        if (arrayE[i] != arrayS[i]) { // si no se cumple la igual entra en la función error
          error();
        }
        delay(500);
        flag = 1;
      }
      else {
        digitalWrite(blueS, LOW);
      }
      if (digitalRead(yellowE) == HIGH) {
        digitalWrite(yellowS, HIGH);
        arrayE[i] = 2;
        if (arrayE[i] != arrayS[i]) { // si no se cumple la igual entra en la función error
          error();
        }
        delay(500);
        flag = 1;
      }
      else {
        digitalWrite(yellowS, HIGH);
      }
      if (digitalRead(greenE) == HIGH) {
        digitalWrite(greenS, HIGH);
        arrayE[i] = 3;
        if (arrayE[i] != arrayS[i]) { // si no se cumple la igual entra en la función error
          error();
        }
        delay(500);
        flag = 1;
      }
      else {
        digitalWrite(greenS, LOW);
      }
    }
  }
  correcto();
}



void correcto() { //función para aumentar un ciclo
  Serial.println("secuencia correcta. Continua.");
  if (secuencia < 300) {
    secuencia++;
  }
  delay(500);
}

void error() {
  //secuencia de salida
  for (int j = 0; j < 5; j++) {
    digitalWrite(redS, HIGH);
    digitalWrite(blueS, HIGH);
    digitalWrite(yellowS, HIGH);
    digitalWrite(greenS, HIGH);
    delay(500);

    digitalWrite(redS, LOW);
    digitalWrite(blueS, LOW);
    digitalWrite(yellowS, LOW);
    digitalWrite(greenS, LOW);
    delay(500);
  }
  Serial.print("Has llegado al nivel: ");
  Serial.println(secuencia);
  delay (1000);
  RESET;
}

void setup() {

  Serial.begin(9600);
  //definimos las entradas y salidas
  pinMode(redS, OUTPUT);
  pinMode(redE, INPUT);
  pinMode(blueS, OUTPUT);
  pinMode(blueE, INPUT);
  pinMode(yellowS, OUTPUT);
  pinMode(yellowE, INPUT);
  pinMode(greenS, OUTPUT);
  pinMode(greenE, INPUT);
  generaAleatorios();
}

void loop() {
  simonDice();
  delay(200);
  playerDice();
  delay(500);
}

Si no funciona y no puedes arreglarlo te coloco mi código de prueba. Funciona a traves del monitor serial, solo uso dos botones conectados directamente a GND. Comprueba su funcionamiento y logica con el tuyo.



#define RESET asm("jmp (0x0000)")
const int redS = 13;
const int redE = 8;
const int blueS = 12;
const int blueE = 9;



int arrayE[5];
int arrayS[5];
int secuencia;
int flag;

void generaAleatorios(){//generamos al principio toda la secuencia que puede llegar a realizar
  for (int i = 0; i < 5; i++){
    int n = random(1,3);
    arrayS[i]=n;  
  }
}

void simonDice() {//muestra la secuencia nivel a nivel
  Serial.println("");  
  for (int i = 0; i<secuencia; i++){
    //le asignamos a cada color un número de los aleatorios que contiene el array de salida
    if (arrayS[i] == 1) {
      //digitalWrite (redS, HIGH);
      Serial.print("Rojo,");
      delay(1000);
      digitalWrite (redS, LOW);
      delay(1000);
    }
    
     if (arrayS[i] == 2) {
      //digitalWrite (blueS, HIGH);
      Serial.print("Azul,");
      delay(1000);
      digitalWrite (blueS, LOW);
      //delay(1000);
    }  
  }
if (secuencia != 0){Serial.println("¿ Que he dicho ??????");}  
}

void playerDice(){

  for(int i = 0; i < secuencia; i++){
    flag = 0;//siempre que salimos se vuelve a poner a cero
    while(flag == 0){//mientras el condicionante valga 0 estaremos dentro del while
      if(digitalRead(redE) == LOW){
        Serial.print ("Rojo,");
        arrayE[i] = 1;
        flag = 1;
        delay(1000);
        if(arrayE[i] != arrayS[i]){// si no se cumple la igual entra en la función error
          error();
        }
      }
      else{
        digitalWrite(redS, LOW);
      }
      if(digitalRead(blueE) == LOW){
        //digitalWrite(blueS, HIGH);
        Serial.print ("Azul,");
        arrayE[i] = 2;
        flag = 1;
        delay(1000);
        if(arrayE[i] != arrayS[i]){
          error();
        }
      }
      else{
        digitalWrite(blueS, LOW);
      }
 
    }
  }
  correcto();//cuando se cumplen todos los ciclos 
}
    
void correcto(){//función para aumentar un ciclo
  if (secuencia < 5){
    secuencia++;
  }
  else {
  Serial.println("");
  Serial.println("");
  Serial.println("CAMPEON!!!!!");
  delay (800);
  RESET;
  }
  delay(500);
}

void error(){
  //secuencia de salida
  Serial.print("Has llegado al nivel: ");
  Serial.println(secuencia-1);
  delay(1000);
  RESET;
}

void setup() {
  
  Serial.begin(9600);
  //definimos las entradas y salidas
  pinMode(redS, OUTPUT);
  pinMode(redE, INPUT_PULLUP);
  pinMode(blueS, OUTPUT);
  pinMode(blueE, INPUT_PULLUP);
  Serial.println("");
  Serial.println("¿ Una nueva partidita ? Pulsa un boton o apagame");
  while ((digitalRead(redE) == HIGH)&&(digitalRead(blueE) == HIGH)){}
  generaAleatorios();
}

void loop(){

    simonDice();
    delay(200);
    playerDice();
    delay(200);
}

Saludos.