Problema con codigo, varios if dentro de un while (Solucionado)

Hola a todos nuevamente, esta vez tengo un problema de codigo tonto pero que hoy no acabo de encontar.

He probado con dos while encadenados.

Con varios for,.... i finalmente me he decidido a usar un while con algunos if pero nada de nada.

Vamos a ver la idea es la siguiente:

Con un sensor mido la distancia a una pieza.
Si tengo pieza, doy un pulso a un paso a paso y sube, vuelvo a mirar...... asi hasque no no encuentre pieza.

En ese momento otro motor gira la plataforma donde esta la pieza (imaginaros que era un donut)

Si durante una vuelta entera no encuentro pieza pues ya esta he terminado

Pero si encuentro tengo que volver a ir subiendo otra vez...........

os pongo mi ultimo codigo.

subir = 1;
medida = 0;

while (medida == 0){
      
    if ((subir == 1) && (sensor0.readRangeContinuousMillimeters() <= 180)){
       pasoAscenso();
       pasosAscensoAcumulados++;
            Serial.print("pasosAscensoAcumulados");
            Serial.println(pasosAscensoAcumulados);
            delay(500);
    }
    else if ((subir == 1) && (sensor0.readRangeContinuousMillimeters() >= 180)){
    subir=0;
    girar=1;
    }   
       if ((girar == 1)&&(medida == 0)){
            pasoGiro();
            pasosGiroAculados++;
                   Serial.print("pasosGiroAculados");
                   Serial.print( pasosGiroAculados);
                   delay(500);
       }
        
               if (sensor0.readRangeContinuousMillimeters() >= 180){
                subir = 1;
                girar = 0;
                pasosGiroAculados = 0;
               }
               else if (pasosGiroAculados == 200){
               medida = 1;
               } 
              }

Tanto el sensor como los valores de codigos aculumados pueden variar, el sensor que dada uno saque el que quiera.

Tambien tengo dos pequeñas funciones que son girar:

void pasoGiro() {
    digitalWrite(stepPin_M0,HIGH);
    delayMicroseconds(700);
    digitalWrite(stepPin_M0,LOW);
    delayMicroseconds(700);
}

void pasoAscenso() {
    digitalWrite(stepPin_M1,HIGH);
    delayMicroseconds(700);
    digitalWrite(stepPin_M1,LOW);
    delayMicroseconds(700);

Falta la parte de inicializar y todo eso pero vamos que el problemas esta en el modo de anidar nada mas. ¿Alguna idea?

Puedes sacar por el serial la variable pasosGiroAculados a principio del bucle while, fuera de los if, y ver qué valor alcanza. Si llega a 200, el problema podría estar en la reinicialización de esta variable a 0, en el if anterior a la asignación medida=1.

Otra opción, ¿sería posible que pasosGiroAculados superara el valor 200 antes de la comprobación final? Si es así, al tener la condición pasosGiroAculados==200 no entraría en el else if.

Hola, gracias por contestar y os voy contando

Puedes sacar por el serial la variable pasosGiroAculados a principio del bucle while, fuera de los if, y ver qué valor alcanza.

Efectivamente al ponerlo al principio justo debajo del while se queda contanto sin fin, da igual lo que pase, cuenta y cuenta.......

Si llega a 200, el problema podría estar en la reinicialización de esta variable a 0, en el if anterior a la asignación medida=1.
Otra opción, ¿sería posible que pasosGiroAculados superara el valor 200 antes de la comprobación final? Si es así, al tener la condición pasosGiroAculados==200 no entraría en el else if.
Esto ya ni lo he mirado al ver lo anterior. pero no creo que sea el problema ya que este no llega ni a comenzar a contar.

yo te ayudaría siempre y cuanto estés dispuesto a deshacer TODO ese código.

Se cambia todo lo que hace falta sin ningun problema.

edito de entrada podrías:
1. Quitar delays() para poder trabajar con todo a la vez. (Uso de timers).

Los puse para ver en el monitor mejor.

2. No usar bucles que interfieran en las lecturas del sensor ni el resto de líneas.
Desde luego es una buena opcion primero queria hacerlo funcionar y luego optimizarlo.

Lo único que tienes que hacer es leer el sensor cada X tiempo.
Si en el intervalo la distancia es la que buscas
Ejecutar acción
En caso contrario
Ejecutar otra acción

¿Por qué usar bucles si todo está dentro del loop? No tienes un listado de elementos a recorrer (al menos en lo que veo del código, más allá del motor)

Esta es una funcino dentro de un programa principal.

Voy a explicarme. el loop solamente hace tres if.

Si cumplo uno de ellos llamo a esta funcion que asu vez dentro de ella llama a dos funciones mas que son las de mover los motores.

Aparte no encuentro el sentido de la variable "media", pero ante todo si las variables media y pasos sólo tienen valores 0 y 1 (flag/boolean) ¿Por qué son declarados y usados cómo enteros?

La variable media es como decir mientras no estes a uno estas haciendo el while cuando logres hacer las cuentas pues te pones a uno y ya se que has terminado, efectivametne seria mejor un boolean pero las prisas son las prisas y lo puse asi, es una de las cosas a mejorar cuando fucione, o siempre puedo hacerlo bien desde un principio.

  • Ok, pero entonces, ¿Estás haciendo las lecturas del sensor sin pausas? El sensor desde que inicio el sistama lo tengo en modo disparo continuo. Me tengo que pelear luego con el para que realice disparos de distancia cuando yo quiera pero de momento siempre midiendo la distancia y la guarda en sus registros.
    Yo solo accedo a ese dato cuando me hace falta.

  • El setup() es para inicializar en el Arduino lo necesario antes de partir al loop() Si lo que queremos es que una acción sólo se haga una vez tras el loop() se usa un flag y listo.
    Tengo varias acciones que dependen de un valor que llega por puerto serie 1. atendiendo a eso hago una cosa u otra

Vamos por partes para poder ayudarte con el código:
Según entiende tienes un motor.
Este se activa en base a un sensor.
Llegado a un punto este movimiento debe parar y sólo realizar estas acciones hasta el fin del mismo (que básicamente al no usar un flag estás poniendo bucles sin parar en el setup, ¿Verdad?)

Si me falta algo o he entendido algo mal me dices.

Para tratar de explicarme mas he realizado un pequeño esquema. (Lo pongo como archivo)

Tambien he cambiado el codigo tratando de hacerlo mas simplificado y entendible.

La idea con todo esto basicamente es cuando funcione y haga los movimientos bien, contar cuantos grupos de 200 doy mientras subo, (ya que cada uno equivale a un milimetro) y como puede darse el caso de que el ultimo no sea completo pues tambien ese valor.

Pero como digo primero que funciones y despues ya añado y guardo valores.

bool medida;
int pasosGiroAculados;
int pasosAscensoAcumulados;

pasosGiroAculados = 0;
pasosAscensoAcumulados = 0;
medida=false;

while( (sensor0.readRangeContinuousMillimeters() < 180) && (pasosGiroAculados <= 200) && (medida==false) ) {
  while( sensor0.readRangeContinuousMillimeters() < 180 ) {
    // Veo pieza, subo
    pasosGiroAculados = 0;
    
    pasoAscenso();
    pasosAscensoAcumulados++;
      delay (500);
     Serial.println (pasosAscensoAcumulados);   
  }
  // No veo pieza asique giramos buscando
 
  pasoGiro();
  pasosGiroAculados++;
  delay (500);
    Serial.println (pasosGiroAculados);   
  
  if ( pasosGiroAculados=200){
    medida=true;
    }
   Serial.println (pasosAscensoAcumulados);   
   Serial.println (pasosGiroAculados);    
}
// Hemos hecho un giro completo y no hemos visto pieza, se acabo                           
  }

Seguro que aun tengo cosas mal pero poco a poco, y perdón por el tostón.

Hola
Continuaré estudiando los comandos que comentas para ver cómo hacerlo bien y si tengo que rehacer todo pues se hace sin problema. Ese ejemplo estaría genial para acabar de entender todo. :wink:

La cuestión esque puedo plantearlo como máquina de estados u otras opciones pero empece haciendo las funciones para cada cosa..... Y otras formas pero al principio pues no me lo propuse así. Pero lo dicho se cambia lo que haga falta.

Buenas tardes, efectivamente he visto el ejemplo y lo usa en el loop, directamente.

Yo en mis sistema tengo dos sensores, primero creo variables,... despues en el setup lo inicializo y configurao

y despues en el loop comienzo mi programa.

Por mis conocimientos de programación (Simatic S7) donde el programa principal se compone de un bloque de organizacion que va llamando a otros en funcion de necesidades estoy aconstumbrado a trabajar asi.

Es decir uso el loop como un OB1 en simatic. Este es el motivo principal de tener funciones que llamo despues, tambien es costumbre hacer que cada codigo que no use no tenga que leerlo siempre asi reduzco el tiempo de ciclo cuando el programa esta solo haciendo el loop.

¿Como suguieres que estructure mi problema?, por supuesto añadiendo todo el el loop si no lo he entendido mal.

Ok, vamos al lio.

Veremos que sale, la cosa es que inicialmente mi problema era mover dos motores,.... haciendo el diagrama que puse en la foto.
Usare el paso de usar el motor 1 al dos y viceversa gracias al ciclo del loop y listo, Activare el que necesite y ya esta.

@Josko85 sinceramente para alguien que dice trabajar con Simantic S7 no comprendo tu falta de comprensión de lo que se te explica.
Ve a Documentación => Indice de temas tutoriales => Clases de Youtube y mira los dos cursos que ahi hay. No lo subestimes. Te dará la base que ahora no tienes.

Si aún te falta mira los libros que también se sugieren.

Con ese background podrás encarar esto con otros aires. Y verás que lo que te dijo ArduMyth en el primer post era lo que necesitabas hacer.

Sin problema ninguno. Como he dicho vamos para adelante, tambien quiero dar por cerrado el post ya que mi problema inicial con las indicaciones dadas queda solucionado. Gracias.

Solucion: Faltaria definir funciones pasoAscenso y pasoGiro que estan en la respuestas anteriores. También lo dejo sin librerías y demas para que cada uno ponga las del sensor y demás elementos que quiera.
Saludos

bool medida; 
bool subir;
bool girar;
int pasosGiroAculados;
int pasosAscensoAcumulados;

int milimetros_totales=0;
int milimetros_parciales=0;

pasosGiroAculados = 0;
pasosAscensoAcumulados = 0;
subir=true;
girar=false;

void loop()
{ 
 if (Serial1.available()>0){
 Programa=Serial1.read();
 
 if (Programa==100){
 
 }
 if(Programa==200){
 while (subir == true) {
 pasoAscenso();
 pasosAscensoAcumulados++;
 girar=false;
 Serial.print ("pasosAscensoAcumulados"); 
 Serial.println (pasosAscensoAcumulados);  
 
 if (pasosAscensoAcumulados==200){
 milimetros_totales++;
 pasosAscensoAcumulados=0;
 }

 if (sensor0.readRangeContinuousMillimeters() >= 180){  // si doy una vuelta compelta guardo en milimetros_totales.
 subir=false;
 girar=true;
 }
 }
 while  (girar==true) {
 Serial.print ("pasosGiroAculados"); 
 Serial.println (pasosGiroAculados);
 
 if (sensor0.readRangeContinuousMillimeters() < 180){
 pasosGiroAculados=0;
 girar=false;
 subir=true;
 }
 
 if (sensor0.readRangeContinuousMillimeters() >= 180){
 pasoGiro();
 pasosGiroAculados++;
 if (pasosGiroAculados >= 200) {
 girar=false;
 subir=false;
 Programa=0;
 }
 }
 }     

 Serial.print ("milimetros_totales");
 Serial.println (milimetros_totales);
 Serial.print("pasosAscensoAcumulados"); 
 Serial.println(pasosAscensoAcumulados) ;
 

 }
     
 }
}