Mi programa no suma como espero

Hola ^^, es mi primera vez usando el foro, asi que pido perdón de antemano si cometo algunos errores.

En un proyecto que comencé hace poco me di cuenta de que mi programa de arduino no estaba sumando valores como debiese, y he revisado varias veces el código y no he sido capaz de percatar el error, motivo del que hago este post por si alguien sabe que está fallando.

Explico en que consiste el proyectito: Son 4 botones que vienen a simular una contraseña numérica, 3 para introducir los números y otro botón para reiniciar la contraseña y cambiarla. Los botones se identifican como "1", "2" y "3", y dependiendo del orden que se opriman, se obtiene una contraseña u otra, como puede ser 123 o 321, la cual es guardada en una variable "contra" (*Las contraseñas siempre son de 3 dígitos). Para lograr esto, utilicé una variable "intentos" (que comienza en 0), que va guardando cuantas veces se a oprimido un botón, y la función exponencial en base 10 y de exponente la variable intento, multiplicando esta última por el valor del botón (1,2 o 3), logrando así que si se oprime 1 2 y 3 en ese orden, debiese resultar que suma será igual a:

suma=110^0+210^1+3*10^3=321
Donde el primer numero introducido es el de más a la derecha y el último el de la izquierda

Y es aquí donde nace el problema, ya que para este caso se espera que el valor final de "suma" sea 321, pero al imprimir en el monitor en seria su valor, sale que es de 320. Este error también sucede para el caso de de que la contraseña introducía sea 123, ya que en el monitor en serie sale 122, o 323 imprime 322.

Adjunto el código (*que fue recortado e incluye otras cosas como feedback mediante leds al usuario)

// CONSTANTES Y VARIABLES UTILES
const int boton1_pin=10; const int boton2_pin=9; const int boton3_pin=8;const int boton_r_pin=6;const int rojo_pin=5;const int verde_pin=4;

int b1;int b2;int b3;int br;
int estado=0;int suma=0;int intentos=0;int cambiar=0;int contra=0; static long t=0; 

int hola=10;

//-------------------------
void setup(){
  Serial.begin(9600);

  pinMode(boton1_pin,INPUT);pinMode(boton2_pin,INPUT);pinMode(boton3_pin,INPUT);pinMode(boton_r_pin,INPUT);pinMode(verde_pin,OUTPUT);pinMode(rojo_pin,OUTPUT);pinMode(4,OUTPUT);pinMode(2,OUTPUT);
  }
  
void loop(){
  
  b1=digitalRead(boton1_pin);b2=digitalRead(boton2_pin);b3=digitalRead(boton3_pin);br=digitalRead(boton_r_pin);

  

//BOTÓN DE CAMBIO DE CONTRASEÑA

if (br==1 &&cambiar==0){
  cambiar=1;
  contra=0;
  intentos=0;
  suma=0;
  digitalWrite(rojo_pin,HIGH);
  digitalWrite(verde_pin,HIGH);
  delay(400);
  digitalWrite(rojo_pin,LOW);
  digitalWrite(verde_pin,LOW);
  }

if (cambiar==1 && intentos==3){
  cambiar=0;
  intentos=0;

  }
//-------------------------

//CAMBIO DE CONTRASEÑA

if(cambiar==1 && b1==1){
  contra+=1*pow(10,intentos);
  delay(10);
  intentos++;
  digitalWrite(verde_pin,HIGH);
  delay(580);
  digitalWrite(verde_pin,LOW);

  }

else if(cambiar==1 && b2==1){
  contra+=2*pow(10,intentos);
  delay(10);
  intentos++;
  digitalWrite(verde_pin,HIGH);
  delay(580);
  digitalWrite(verde_pin,LOW);

  }
  
else if(cambiar==1 && b3==1){
  contra+=3*pow(10,intentos);
  delay(10);
  intentos++;
  digitalWrite(verde_pin,HIGH);
  delay(580);
  digitalWrite(verde_pin,LOW);

  }

//-------------------------
  
delay(120);

//ACERTAR CONTRASEÑA

  if (contra==suma && intentos==3){
    
  if(t==0){
    t=millis();
    } 
  if (millis()-t>3300){
    suma=0; t=0;}
  

  }
//--------------CREAND0 EL INTENTO----------------

if (cambiar==0){

  if(b1==1){
    suma=suma+1*pow(10,intentos);
    delay(10);
    intentos++;
    digitalWrite(rojo_pin,HIGH);
    delay(580);
    digitalWrite(rojo_pin,LOW);
    Serial.println("---------------");
    Serial.println(1*pow(10,intentos-1));
    Serial.println("---------------");
    }

  else if(b2==1){
    suma+=2*pow(10,intentos);
    delay(10);
    intentos++;
    digitalWrite(rojo_pin,HIGH);
    delay(580);
    digitalWrite(rojo_pin,LOW);
    Serial.println("---------------");
    Serial.println(2*pow(10,intentos-1));
    Serial.println("---------------");
    }

  else if(b3==1){
    suma+=3*pow(10,intentos);
    delay(10);
    intentos++;
    digitalWrite(rojo_pin,HIGH);
    delay(580);
    digitalWrite(rojo_pin,LOW);
    Serial.println("---------------");
    Serial.println(3*pow(10,intentos-1));
    Serial.println("---------------");
    }
}

Serial.print("intentos ");
Serial.println(intentos);
Serial.print("contra: ");
Serial.println(contra);
Serial.print("suma: ");
Serial.println(suma);



// MOSTRAR AL USUARIO QUE SE EQUIVOCÓ

if(intentos>3){
  intentos=0;
  suma=0;
  digitalWrite(rojo_pin,HIGH);
  delay(100);
  digitalWrite(rojo_pin,LOW);
  delay(100);
  digitalWrite(rojo_pin,HIGH);
  delay(100);
  digitalWrite(rojo_pin,LOW);
  delay(100);
  digitalWrite(rojo_pin,HIGH);
  delay(100);
  digitalWrite(rojo_pin,LOW);
  delay(100);
  }
  Serial.println(" ");
  }

Además de algunos casos del monitor en serie:

Contraseña "123"

intentos 0
contra: 0
suma: 0
 
intentos 0
contra: 0
suma: 0
 
intentos 1
contra: 3
suma: 0
 
intentos 1
contra: 3
suma: 0
 
intentos 1
contra: 3
suma: 0
 
intentos 1
contra: 3
suma: 0
 
intentos 1
contra: 3
suma: 0
 
intentos 1
contra: 3
suma: 0
 
intentos 2
contra: 23
suma: 0
 
intentos 2
contra: 23
suma: 0
 
intentos 2
contra: 23
suma: 0
 
intentos 2
contra: 23
suma: 0
 
intentos 2
contra: 23
suma: 0
 
intentos 2
contra: 23
suma: 0
 
intentos 3
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
intentos 0
contra: 122
suma: 0
 
---------------
3.00
---------------
intentos 1
contra: 122
suma: 3
 
intentos 1
contra: 122
suma: 3
 
intentos 1
contra: 122
suma: 3
 
intentos 1
contra: 122
suma: 3
 
intentos 1
contra: 122
suma: 3
 
intentos 1
contra: 122
suma: 3
 
intentos 1
contra: 122
suma: 3
 
---------------
20.00
---------------
intentos 2
contra: 122
suma: 23
 
intentos 2
contra: 122
suma: 23
 
intentos 2
contra: 122
suma: 23
 
intentos 2
contra: 122
suma: 23
 
intentos 2
contra: 122
suma: 23
 
intentos 2
contra: 122
suma: 23
 
intentos 2
contra: 122
suma: 23
 
---------------
100.00
---------------
intentos 3
contra: 122
suma: 122
 
intentos 3
contra: 122
suma: 122
 
intentos 3
contra: 122
suma: 122
 
intentos 3
contra: 122
suma: 122

Contraseña "321"

intentos 0
contra: 0
suma: 0
 
intentos 0
contra: 0
suma: 0
 
intentos 0
contra: 0
suma: 0
 
intentos 1
contra: 1
suma: 0
 
intentos 1
contra: 1
suma: 0
 
intentos 1
contra: 1
suma: 0
 
intentos 1
contra: 1
suma: 0
 
intentos 2
contra: 21
suma: 0
 
intentos 2
contra: 21
suma: 0
 
intentos 2
contra: 21
suma: 0
 
intentos 2
contra: 21
suma: 0
 
intentos 2
contra: 21
suma: 0
 
intentos 3
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
intentos 0
contra: 320
suma: 0
 
---------------
1.00
---------------
intentos 1
contra: 320
suma: 1
 
intentos 1
contra: 320
suma: 1
 
intentos 1
contra: 320
suma: 1
 
intentos 1
contra: 320
suma: 1
 
intentos 1
contra: 320
suma: 1
 
---------------
20.00
---------------
intentos 2
contra: 320
suma: 21
 
intentos 2
contra: 320
suma: 21
 
intentos 2
contra: 320
suma: 21
 
intentos 2
contra: 320
suma: 21
 
---------------
300.00
---------------
intentos 3
contra: 320
suma: 320
 
intentos 3
contra: 320
suma: 320

Muchas gracias por su atención ^^

Moderador:
No uses mayúsculas en los titulos de los temas que propongas.
Y tampoco uses la palabra AYUDA porque eso es lo que vienes a pedir, asi que no hay porque pedir lo que se te va a brindar.

El problema es el error de redondeo del formato double al pasar a entero, y pow() devuelve un double.

Me estaba volviendo loco porque podía reproducir el error pero no encontraba donde estaba. :angry:

Se me ocurrió hacer lo siguiente

//--------------CREAND0 EL INTENTO----------------

if (cambiar == 0){
  switch(intentos){
    case 0: br = 1;
      break;
    case 1: br = 10;
      break;
    case 2: br = 100;
      break;
  }
  if(b1 == 1){
     suma += 1 * br; // *** cambiar fórmula

// resto del código...

Y dió lo que debía, ahí me di cuenta que el error lo estaba provocando pow().
Resultó que para la entrada "321" el valor double de suma era 320.9.... Al redondear a entero quedaba 320.

Creo que te conviene usar el switch/case como hice yo, solo que cambia la variable donde asigna la potencia de 10 porque yo usé br en las pruebas ya que no la usaba

Además, con el cambio, el compilado resulta ser 2kB más pequeño. :wink:

Saludos

PD:
Si quieres ver el error, define suma como double y luego, para ver los decimales, donde imprimes el resultado cambia por

Serial.println(suma,6);

O no usar pow porque hay un modo mas simple de hacerlo

En la situación que sea

 if (intento != 0)
    suma *=10;
  suma +=numeroASumar;

Entonces mira que simple es.
intonto se incrementa como ya lo haces...0.1.2.3

Pero suma se multiplica x 10 en el intento = 1 o sea el 2.
suma = 0;

y se le suma el valor, ejemplo
intento = 0
Si primero digitas 1 => suma = 1;
como intento = 0 no multiplico x 10
suma luego se incrementa a 1.
Presiono 2
ahora como intento = 1
suma *= 10 => suma = 10 porque contenia 1 * 10 = 10 si hubiera contenido otro digito sería lo mismo
nos falta la suma => 12

al 3er caso... digamos 4
intento = 2
suma = 10 >= 1210 = 120
y el digito 4
suma += numero => 124

Como ves muy fácil y sin redondeos y cosas raras.
suma *=10 =>

El tema es que ingresa los dígitos en orden inverso, empieza por las unidades y termina con las centenas.

Yo me ajuste a su código porque imagino que si lo hace así tendrá sus motivos.

Pero si cambia de idea, y hace el ingreso en el orden habitual, claramente no hay mejor solución.

Yo escribo de izquierda a derecha, no de derecha a izquierda como en este caso, ni observé tu comentario porque me parece siempre que lo lógico es ingresar las cosas como las escribimos.

Si alguien lo quiere hacer al revés y vale la pena, okay.

Ok.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.