[SOLUCIONADO] Detener funcion en loop

Buenas.

Tengo el siguiente problema. Dentro del loop tengo una comparación concretamente esta ;

 if (radio.state.frequency == 93.50)
          {               
  picones(); 
                                            
       }

funcona correcto, la función picones() resumida es esto;

void picones(){
  
#define u8g_ondacero1_width 128
#define u8g_ondacero1_height 64

static unsigned char u8g_ondacero1_bits[] U8G_PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
.... ... ... .. .. ..
   0x00, 0x00, 0x00, 0x00 };
                                   
             u8g.firstPage(); 
              do {
             u8g.drawXBMP( 0, 0, u8g_ondacero1_width, u8g_ondacero1_height, u8g_ondacero1_bits);
         
             } while(u8g.nextPage());
             delay(3000);  

             
             //    while(1) {
            //      picones(); 
            //    }
             
               
       }

Entra en bucle indefinidamente.cuando encuentra la comparación, y lo que deseo es detenerla (los 3 segundos que marca el delay)

He probado como se ve en el ultimo código while(1), pero se detiene todo el loop. A todo ello he investigado y encontré este código (no probado) concretamente este;

boolean stop_it = false;

void setup() {

   Serial.begin(9600);
   
  }
boolean stop_main_loop() {

    if (stop_it == false) {
     Serial.println ("Stpo detener una función en loop"); 
  }
  stop_it = true;
  return stop_it;
  
}

void loop() {

stop_it = stop_main_loop();
}

Alguna sugerencia?. Gracias.

Creo que hoy estoy un poco "acido". No me queda claro que es lo que quieres conseguir.

Entiendo que cuando la frecuencia de la radio es la de un canal, quieres mostrar en un lcd gráfico el logo de la radio, y por lo poco que deduzco del código es una especie de animación.

Y bien, si metes un delay se detiene la función y por ende el loop también 3 segundos y si haces un loop infinito, además de recursivo, ya se para del todo.

Lo que no sé es si pretendes que la animación se muestre durante tres segundos, pero el loop siga su curso normal; o por el contrario, todo se pare durante esos tres segundos.

Lo lógico lo primero. Así que deberías usar una variable que tenga en cuenta que vas a hacer con el lcd en cada momento. Por ejemplo: lcd_status, y con estado: mostrando_logo, mostrando_info, etc.. Y tratar cada estado haciendo que el lcd haga lo que tu quieres. En mostrando_logo puedes definir un temporizador y con millis() controlar el tiempo que quieres que esté en ese estado y luego lo cambias. De esta forma no detienes para nada el loop que seguira ejecutandose sin parar y hará la animación y luego seguirá donde tu lo deseas.

El último código (el que no has probado), lo único que veo que hace es que ejecuta una sola vez el Serial.println().

Es como tu dices victor porque si leyeras su proyecto.. que estaba terminado hasta que un amigo le dijo a @lightcalamar de porque no poner picones o logos en lugar de las frecuencias o ambas.
Asi que eso es lo que pretende.

Ahora veamos si ayudo con mi respuesta.
Suponiendo que el logo o picon estará 3 segundos no puedes dejar que cuando la comparación se cumpla siempre muestre el logo/picón porque eso si sería infinito. Entonces, yo por ejemplo usaría un flag que debo resetear o cambiar en otro sitio.. p.ej cuando sea otra frecuencia y digamos que ese flag lo uso para que si esta en false y se cumple que la frecuencia es la que tu quieres muestre el logo/picón por los 3seg y luego levanto el flag con lo que no me dejará accionarlo de nuevo por mas que sigas en la frecuencia.
Ahora el tema es que ese flag debe permanecer asi a menos que detectes otra frecuencia que active dicho flag cuando vueltas a esa radio.
Tal vez no sea el mejor modo porque lo estoy planteando como un flag por frecuencia... lo que se traduce en un array de flags.. pero es una idea que puede mejorarse.

Gracias @Victor y Surbyte.

Lo que no sé es si pretendes que la animación se muestre durante tres segundos, pero el loop siga su curso normal

Exactamente Victor esta es la idea.

He ido avanzando y es como muestra el nuevo vídeo el código que he usado después de mucho releer para parar una parte de una función en el loop es esta que he incluido;

int esperaLogo;
            esperaLogo = 87;
                while ( esperaLogo =(radio.state.frequency == 93.50))  {    
                  delay(300);
                     picones();
                        esperaLogo++;
                 break;
              }

El código tiene que ir en el loop para que compare la frecuencia en ese momento y ponga la imagen de la emisora durante los 3 segundos, pero vuelve al bucle infinito.

Voy a probar realizarle un switch ... case definiendo las frecuencias predefinidas a ver que pasa.
Había pensado incluso de realizar la función que muestra la imagen (picon) definirla como boolean, lo he realizado, pero luego al volver al loop ni la reconoce. a seguir investigando...

Puedes poner todo el loop?
Aprovecha ese esperaLogo en 87 para hacerlo solo esa vez

int esperaLogo;

// no se de donde viene
//............

         esperaLogo = 87;
         while ( esperaLogo =(radio.state.frequency == 93.50))  {    
                  if (esperaLogo == 87) {
                      picones();
                      delay(300);
                  } 
                  esperaLogo++;
                  break;
          }

Este es el loop del Radio;

void loop() {

        radio.updateStatus();
            if (!radio.state.isTunedToChannel && currentDisplay == SHOW_STATION) {
        currentDisplay = SHOW_TUNING;
        displayTimeout = 0;
          } else if (currentDisplay == SHOW_TUNING && radio.state.isTunedToChannel) {
        currentDisplay = SHOW_STATION;
        setEepromFreq(radio.state.frequency);
           }
                                        
        byte x = readButton(analogRead(2));   // -2- PIN ANALOGICO PARA EL TECLADO -"MENUBACKEND"-
             if ( x != 116)  {
                readChoose(x);
           x = 1;  }
             if (Serial.available() )  {
           byte read = Serial.read();
        readChoose(read);
       }

          tecladoRadio();         // LEE EL TECLADO PRINCIPAL DEL MANEJO DEL RADIO
          updateDisplay();
             delayMicroseconds(5);

         // CONTADOR PARA APAGAR EL LCD 20x4
         if (millis()-time > 480000) {  // SI HAN PASADO 4 MINUTOS (60*2*2) SE APAGA LA LUZ DEL LCD DE MENUS
         lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
         lcd.setBacklight(LOW);
             luzEncendida=false;
         }
                              
         // FIN DEL CONTADOR
         // OJO QUE SE EJECUTA IGUALMENTE SIN CONTAR EL TIEMPO
            
         //      if (millis()-(time=dimmer) >= 150000){
         //      SI HAN PASADO 55 SEGUNDOS SE RALIZA FADING A LOS LCD´s
         //      fade();
         //      }
         //      dimmer = 150000;
                           
         empiezaMiReloj();    // RUTINA HORAS, MINUTOS, SEGUNDOS
         u8g.setPrintPos(10, 53);
         u8g.print(radio.state.stationName);


       // ******************************************************************** 
       //   AQUI EL PROBLEMA DEL BUCLE INFINITO
       // ********************************************************************    
          /*
               esperaLogo = 87;
                 while ( esperaLogo =(radio.state.frequency == 90.50))  {    
                  delay(300);
                     picones();  
                       esperaLogo++;                                                      
                               break;                                                                                                            
              } 

//  pic(); // PARA PROBAR EL switch .. case
              
            */                                                          
                             
         // CONTADOR PARA IMPRIMIR EL RELOJ
         if (millis()-time > 10000) {  // SI HAN PASADO 10 SEGUNDOS SE IMPRIME EL RELOJ
         printNum(hr/10,0);
         printNum(hr%10,3);
         printColon(6);
         printNum(mn/10,7);
         printNum(mn%10,10);
         printColon(13);
         printNum(se/10,14);
         printNum(se%10,17);
      }
    
         // --------------------------------------------------------------------------------
         //  int lastCount = 0;  // OJO CON ESTO !!!!!!!!!!!!!!!!!!!!!! SI NO ES COMENTADA
                                 //   NO FUNCIONA LA SINTONIA FINA DEL RADIO (ENCODER)
         // ---------------------------------------------------------------------------------                         
         //                        AQUI EL ROTARY  PARA SINTONIA FINA  
          
           if (virtualPosition != lastCount) {
           if (lastCount < virtualPosition)
            {
              radio.seekUp();
          }
            if (lastCount > virtualPosition)
             {
              radio.seekDown();
          }
        }
      lastCount = virtualPosition;
     

 }  // FIN DEL LOOP

Con un swith … case me hace lo mismo;

#define ONDACERO   93
#define M80RADIO    90

void pic(){

    
     esperaLogo = radio.state.frequency;
     
     switch (esperaLogo) {
         case ONDACERO:
         if (radio.state.frequency == 93.50) {
           
           picones();
         }
         
           break;
           case M80RADIO:
           radio.state.frequency == 90.50;
           break;  
     }   
}

Le puse el valor 87 (frecuencia mas baja) para que fuera aumentando el valor y al llegar aumentando dejaría y loop pero ahora que lo copio, veo que no.

Esta es mi sugerencia pero parte de ciertas premisias que aclaro en tu código con comentarios

void loop() {
  bool flagpicon = false;

  radio.updateStatus();
  if  (!radio.state.isTunedToChannel && currentDisplay == SHOW_STATION) {
       currentDisplay = SHOW_TUNING;
       displayTimeout = 0;
  } else 
  if (currentDisplay == SHOW_TUNING && radio.state.isTunedToChannel) {
      currentDisplay = SHOW_STATION;
      setEepromFreq(radio.state.frequency);
      flagpicon = true; // supongo que este if se ejecuta solo una vez cuando es sintonizada y el display muestra la sintonia
                        // aca activo el flag para que se muestre cuando coincida con la frecuenca X 
                        // da igual cual flag porque el picon se mostrará según la freq, asi que tendras que 
                        // direccionar ahi.
  }
                                  
  byte x = readButton(analogRead(2));   // -2- PIN ANALOGICO PARA EL TECLADO -"MENUBACKEND"-
  if ( x != 116)  {
       readChoose(x);
       x = 1;  
  }
  
  if (Serial.available() ) {
     byte read = Serial.read();
     readChoose(read);
  }

  tecladoRadio();         // LEE EL TECLADO PRINCIPAL DEL MANEJO DEL RADIO
  updateDisplay();
  delayMicroseconds(5);

  // CONTADOR PARA APAGAR EL LCD 20x4
  if (millis()-time > 480000) {  // SI HAN PASADO 4 MINUTOS (60*2*2) SE APAGA LA LUZ DEL LCD DE MENUS
      lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
      lcd.setBacklight(LOW);
      luzEncendida=false;
  }
                        
  // FIN DEL CONTADOR
  // OJO QUE SE EJECUTA IGUALMENTE SIN CONTAR EL TIEMPO
      
  //      if (millis()-(time=dimmer) >= 150000){
  //      SI HAN PASADO 55 SEGUNDOS SE RALIZA FADING A LOS LCD´s
  //      fade();
  //      }
  //      dimmer = 150000;
                     
  empiezaMiReloj();    // RUTINA HORAS, MINUTOS, SEGUNDOS
  u8g.setPrintPos(10, 53);
  u8g.print(radio.state.stationName);


  // ******************************************************************** 
  //   AQUI EL PROBLEMA DEL BUCLE INFINITO
  // ********************************************************************    
  if ( radio.state.frequency == 90.50 && flagpicon)  {    
          picones();  //supongo que debe verse por 3 segundos y no mas 
          delay(300);
          flagpicon = false;                                                                                               
  } 

  //  pic(); // PARA PROBAR EL switch .. case
        
                       
  // CONTADOR PARA IMPRIMIR EL RELOJ
  if (millis()-time > 10000) {  // SI HAN PASADO 10 SEGUNDOS SE IMPRIME EL RELOJ
      printNum(hr/10,0);
      printNum(hr%10,3);
      printColon(6);
      printNum(mn/10,7);
      printNum(mn%10,10);
      printColon(13);
      printNum(se/10,14);
      printNum(se%10,17);
  }

  // --------------------------------------------------------------------------------
  //  int lastCount = 0;  // OJO CON ESTO !!!!!!!!!!!!!!!!!!!!!! SI NO ES COMENTADA
                          //   NO FUNCIONA LA SINTONIA FINA DEL RADIO (ENCODER)
  // ---------------------------------------------------------------------------------                         
  //                        AQUI EL ROTARY  PARA SINTONIA FINA  
    
  if (virtualPosition != lastCount) {
      if (lastCount < virtualPosition) {
            radio.seekUp();
      }
      if (lastCount > virtualPosition)  {
          radio.seekDown();
      }
    }
    lastCount = virtualPosition;
 }  // FIN DEL LOOP

Si señor!!!
Funcionando perfecto!!! Hoy has hecho feliz a una persona, esta que lleva todo el fin de semana con este tema...

Pues bien ya queda difinir los logos de cada emisora, que tiene lo suyo... Terminamos el Radio y no lo voy a enseñar a nadie, para que me complique la vida :slight_smile: :slight_smile: :slight_smile: :slight_smile: Enormes gracias @surbyte
Tema solucionado. Ya se puede cerrar.

P.D. Gracias a Victor también por su colaboración