Salir y continuar de blucle for

Hola buena tarde ¿Me pueden ayudar a integrar un bucle for a mi código? Adjunto mi código abajo: el bucle for se repite de forma infinita, y no continua el código no sé cómo hacer para salir del bucle, ya intente abrir y cerrar llaves, ({}) agregando (;), tampoco lo conseguí poniendo el bucle for en void setup(){ el código copila sin mensaje de error.
Les agradezco su ayuda.

type or paste code
 //robojax 
#include "max6675.h"
#include<Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20 , 4); //  variantes .
// 0x27 0x3F , 0x20 , 0x38 ,  16 , 2 20 , 4

const byte thermoDO  = 6;
const byte thermoCS  = 5;
const byte thermoCLK = 4;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
int i  = 0;
int boton = 10;
const byte vccPin     = 3;
const byte gndPin     = 2;
const byte gndPinf    = 8;
const byte vccPinr    = 9;
const byte relePinA   = 12;
const byte relePinB   = 13;
float temprelePinA;
float temprelePinB;
unsigned long instanteAnterior;
bool enfriando = false;

void setup() {

  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("D. Marmo Servicios"); // Mensaje a desplegar
  lcd.setCursor(0, 2);
  lcd.print("    Secadora Do 6 "); // Mensaje 2 a desplegar
  delay(3000); // espera 3 segundos con el mensaje estatico

  Serial.begin(9600);

  pinMode(vccPin, OUTPUT);
  digitalWrite(vccPin, HIGH);

  pinMode(gndPin, OUTPUT);
  digitalWrite(gndPin, LOW);

  pinMode(vccPinr, OUTPUT);
  digitalWrite(vccPinr, HIGH);

  pinMode(gndPinf, OUTPUT);
  digitalWrite(gndPinf, LOW);

  pinMode(relePinA, OUTPUT);
  pinMode(relePinB, OUTPUT);
  pinMode(boton, INPUT);
  Serial.println("temperatura  ");
  delay(3000);

}

void loop() {

   // inicio del bucle for 
  for (int i = 0; i < 3; i++) {
    if (thermocouple.readCelsius() > 36.00)
      digitalWrite(i = 12, HIGH); 
    delay(50);
    if (thermocouple.readCelsius() < 34.00)
      digitalWrite(i = 12, LOW); 
    delay(50);
 }

  //el ciclo se repite infinita mente no pasa a la siguirnte etapa 

  if (millis() - instanteAnterior > 2500UL) {
    instanteAnterior = millis();
    temprelePinA = thermocouple.readCelsius();

    Serial.println( thermocouple.readCelsius());
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print(" Temperatura  ");
    delay(500);

    lcd.setCursor(4, 2);
    lcd.print("C = " + String(temprelePinA));
    lcd.print((char)223);
    Serial.println();

    if (temprelePinA > ((digitalRead(boton) == HIGH) ? 40.00 : 42.0)) { 
      digitalWrite(relePinA, HIGH); 

      enfriando = true;
    }
    if (enfriando) {
      if ( temprelePinA < 29.00) {
        digitalWrite(relePinB,  HIGH);  
      }
    }
  }
}
 

Hola @silvia96
No entiendo qué querías hacer con el valor de i = 12.
Al hacerlo, cambió el valor de i del for.
Explica mejor tu idea dentro de este foro para que podamos entender tu propósito y poder ayudarte.

RV mineirin

Para mi

digitalWrite(i = 12, X);

está mal, no se que hace el compilador con eso, a que pin lo asigna y que resulta luego.

Mas allá de eso, aunque i tomara el valor 12 de todos modos saldría del bucle porque se cumpliria la condición

Saludos

Hola ruilviana, el valor i=12. fue uno de tantos intentos de separar el bucle for del resto del código, porque digitalWrite(relePinA, HIGH); es también el pin digital12 en el código, que he usado para secar frutas y algunas verduras, (básica mente tomates) `si comentas esta sección del código que posteo abajo veras que funciona, El código funciona así, la temperatura sube 40° o a 42° dependiendo del estado del pin 10, y apaga la resistencia de calentamiento, y enfría la fruta hasta regresar el 29°, y el ciclo solo se inicia cuando se reinicia el arduino uno. Pero me he dado cuenta que si desconecto la resistencia al alcanzar los 36° y la conecto al bajar la temperatura a 34° varias veces la fruta queda más suave y con mejor sabor, original mente escribí el código con relePinA en el bucle for, pero como no funciono, y una de tantas pruebas fue (I = 12, LOW); (no todo lo que se ve en google es ortodoxo). Te pido una disculpa por postear tal aberración. La idea de agregar el bucle for, es evitar conectar y desconectar la resistencia de forma manual, que lo haga arduino esa es la idea, no se si sea posible en teoría si.

type or paste code // inicio del bucle for 
  for (int i = 0; i < 3; i++) {
    if (thermocouple.readCelsius() > 36.00)
      digitalWrite( relePinA,HIGH); 
    delay(50);
    if (thermocouple.readCelsius() < 34.00)
      digitalWrite(relePinA,  LOW); 
    delay(50);
 }

  //el ciclo se repite infinita mente no pasa a la siguirnte etapa 

`

Hola gatul, fue algo que encontré en google, y si se ejecutaba el bucle for en el pin digital 12 solo que de forma infinita, no e conseguido que termine el resto del código. También intente meter el bucle for en el viod setup(){, pero tampoco funciono, creo que solo funciona para imprimir resultados en monitor Serial
saludos

Para mi sí que sale del for() y es fácil de probarlo.
Pon por ejemplo

lcd.print("Salio");

a continuación del lazo for(), si se imprime el mensaje es porque sale (si, ya se que es obvio...) :wink:

Hola, ya le agregue, lcd.print("salio"); y se imprime, sin iniciar el lazo for() como si no existira el bucle for, pero el rele, no sale del lazo se apaga a 36° y se enciende a 34°.
saludos

La verdad que ya me perdí.
Decías que no salía del for() pero si sale.
Ahora dices que no ejecuta el for() pero si mueve el relé, entonces si ejecuta el for().
No entiendo en definitiva que es lo que esperas que haga y te parece que no hace.

Tampoco entiendo lo que haces luego,

    if (temprelePinA > ((digitalRead(boton) == HIGH) ? 40.00 : 42.0)) { 
      digitalWrite(relePinA, HIGH); 

      enfriando = true;
    }
    if (enfriando) {
      if ( temprelePinA < 29.00) {
        digitalWrite(relePinB,  HIGH);  
      }
    }

No entiendo por qué cambias el rango de temperatura por el que pones relePinA en alto si para esas temperaturas ya estaría en alto cuando se ejecutó el for().
No veo una condición que ponga en bajo a relePinB, o sea, una vez que pasa a alto nunca más vuelve a bajo si no apagas el arduino.

Recuerda que puedes usar la consola para saber por donde anda el programa o controlar valores, simplemente haz que imprima por serial mensajes tipo "estoy en el for", "sali del for", "estoy dentro del 1er if".
Antes te lo hice imprimir en el lcd pero es mas practico usar la consola.

Saludos

Hola, si imprimió en la lcd y en el monitor Serial "salio de for" justo en el momento de encender el arduino. RelePInA y relePinB también inician encendidos, (el tipo de relé que uso se activa en LOW y se apagan en HIGH), sin el bucle for, el código funciona de la siguiente forma, inicia con reles A y B encendidos, al alcanzar los 40° o 42° segun el estado del pin 10 a 40° si el pin 10 recibe 0v y 42° si recibe 5v, en este momento apaga el releA (resistencia, y el ventilador releB, continua encendido, cuando la temperatura baja a menos 29° apaga el ventilador, y termina el ciclo de secado. Solo al reiniciar el arduino se repite el ciclo, lo que seco son tomates. Y he comprobado que si apago la resistencia, que calienta la maquina a 36°, y enciendo la resistencia al bajar la temperatura a 34°, varias veces ejemplo 5 veces luego dejo que la temperatura alcance los 42° la maquina sola termina el ciclo, los tomates secos quedan mas suaves y con mejor sabor, y de hay nace la idea de agregar el lazo for, es para no estar encendiendo y apagando la resistencia, de forma manual. En la ciudad en que vivo la temperatura inicial ronda los 23° y al encender la maquina tarda unos 20 minutos en alcanzar los 36° y bajar a 34° unos 12 minutos la primera vez, a la quinta vez encender y apagar tarda unos 4 minutos el ciclo entre los 36° y 34° al estar menos húmedo el producto el código tiene la función enfriar al final del código y apaga el releB con HIGH`

//robojax 

#include "max6675.h"
#include<Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20 , 4); //  variantes .
// 0x27 0x3F , 0x20 , 0x38 ,  16 , 2 20 , 4

const byte thermoDO  = 6;
const byte thermoCS  = 5;
const byte thermoCLK = 4;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
int i  = 0;
int boton = 10;
const byte vccPin     = 3;
const byte gndPin     = 2;
const byte gndPinf    = 8;
const byte vccPinr    = 9;
const byte relePinA   = 12;
const byte relePinB   = 13;
float temprelePinA;
float temprelePinB;
unsigned long instanteAnterior;
bool enfriando = false;

void setup() {

  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("D. Marmo Servicios"); // Mensaje a desplegar
  lcd.setCursor(0, 2);
  lcd.print("    Secadora Do 6 "); // Mensaje 2 a desplegar
  delay(3000); // espera 3 segundos con el mensaje estatico

  Serial.begin(9600);

  pinMode(vccPin, OUTPUT);
  digitalWrite(vccPin, HIGH);

  pinMode(gndPin, OUTPUT);
  digitalWrite(gndPin, LOW);

  pinMode(vccPinr, OUTPUT);
  digitalWrite(vccPinr, HIGH);

  pinMode(gndPinf, OUTPUT);
  digitalWrite(gndPinf, LOW);

  pinMode(relePinA, OUTPUT);
  pinMode(relePinB, OUTPUT);
  pinMode(boton, INPUT);
  Serial.println("temperatura  ");
  delay(3000);

}

void loop() {

   // inicio del bucle for 
  for (int i = 0; i < 3; i++) {
    if (thermocouple.readCelsius() > 36.00)
      digitalWrite(relePinA, HIGH); 
    
    if (thermocouple.readCelsius() < 34.00)
      digitalWrite(relePinA, LOW); 
    
 }
    Serial.println("termina bucle for");
    lcd.println("fin del lazo for);
  //el ciclo se repite infinita mente no pasa a la siguirnte etapa 

  if (millis() - instanteAnterior > 2500UL) {
    instanteAnterior = millis();
    temprelePinA = thermocouple.readCelsius();

    Serial.println( thermocouple.readCelsius());
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print(" Temperatura  ");
    delay(500);

    lcd.setCursor(4, 2);
    lcd.print("C = " + String(temprelePinA));
    lcd.print((char)223);
    Serial.println();

    if (temprelePinA > ((digitalRead(boton) == HIGH) ? 40.00 : 42.0)) { 
      digitalWrite(relePinA, HIGH); 

      enfriando = true;
    }
    if (enfriando) {
      if ( temprelePinA < 29.00) {
        digitalWrite(relePinB,  HIGH);  
      }
    }
  }
}

Hola.
Con este ultimo post aclaras muchas cosas que antes no veia. Creo que la eleccion del if dentro del for no es la adecuada y ademas creo que deberias añadir una variable que contenga si ya se ha ejecutado alguna vez dicho bucle, Yo lo haria mas o menos asi:

// inicio del bucle for
  if (!bucle && thermocouple.readCelsius() > 36.00) {
    for (int i = 0; i < 3; i++) {
      digitalWrite(relePinA, HIGH);
      while ( thermocouple.readCelsius() > 34.00) {}
      digitalWrite(relePinA, LOW);
      while ( thermocouple.readCelsius() < 36.00) {}
    }
    bucle = true;
  }
  // fin del bucle for

A, me podeis explicar que diablos hace esto:

if (temprelePinA > ((digitalRead(boton) == HIGH) ? 40.00 : 42.0))

No me he topado nunca con esos modificadores y por mas que busco no encuentro nada.
Saludos.

Si boton es HIGH compara con 40, sino con 42.

Agrego:
¿Qué "diablos" quisiste hacer con tu código? :crazy_face:
Con bucle en false, si la temperatura es mayor a 36° entra al for(), y dentro haces un while() mientras la temperatura sea mayor a 34°, y ahí se queda porque 36 es mayor que 34. :man_facepalming:t2:

1 Like

@silvia96 Revisa el código porque yo no encuentro la sentencia que enciende el ventilador, solo veo ésta

digitalWrite(relePinB,  HIGH);

que lo apaga.

O sea, dónde está el

digitalWrite(relePinB,  LOW);

que lo enciende?

Agrego:
¿Qué sentido tiene el lazo for()?
¿Para qué lees 3 veces la temperatura y actúas sobre reléA también 3 veces?
No lo entiendo... :thinking:

Yo, personalmente, creo que lo mejor sería resolver el problema con una máquina de estados, que controle en qué secado se encuentra a la vez que en qué parte está del proceso de cada secado. Porque me temo que no sólo quiere que active o desactive cada relé, sino que también se muestre la temperatura en el LCD. Aunque siempre podemos poner dentro del for el que muestre la temperatura. Pero insisto, nada de for y más máquinas de estados. Además, con máquinas de estados, sería fácil implementar el uso de botones de inicio o la parada de todo el proceso, mostrar en que paso está, un botón para saltarse el paso en que está o muchas cosas más.

[OFF-TOPIC]

Respecto a:

Ya lo ha dicho @gatul, pero por si no está claro, el operador ternario:

<expresión condición> ? <expresión si es verdadero> : <expresión si falso>

devuelve el valor de <expresión si es verdadero> en el caso de que el valor de <expresión condición> sea verdadero. Y devuelve <expresión si es falso> en el caso de que al valor de <expresión condición> sea falso.

En la línea de código:

if (temprelePinA > ((digitalRead(boton) == HIGH) ? 40.00 : 42.0))

digitalRead(boton) == HIGH) es la <expresión condición>
40.00 es la <expresión si es verdadero>
42.0 es la <expresión si es falso>

Con lo que la expresión ternaria tendrá el valor 40.00 si el pin boton está a nivel alto y el valor 42.0 si ese pin está a nivel bajo.

Por lo que el if verifica si el valor de temprelePinA es mayor que 40.00 cuando el pin de boton está a nivel alto y verifica si el valor de temprelePinA es mayor que 42.0 cuando el pin de boton está a nivel bajo. Así de "sencillo" :wink:.

1 Like

Ojo que apago la "calefaccion". Mejor comento el código:

 if (!bucle && thermocouple.readCelsius() > 36.00) { // en la subida se detecta 36 .Entramos en el for
    for (int i = 0; i < 3; i++) {
      digitalWrite(relePinA, HIGH); // apagamos la "calefaccion", empieza a bajar la temperatura
      while ( thermocouple.readCelsius() > 34.00) {} // quietecitos hasta que T = 33,999999999
      digitalWrite(relePinA, LOW); // encendemos la calefacción
      while ( thermocouple.readCelsius() < 36.00) {}// quietecitos otra vez hasta llegar a los 36
     // se marea al tomate las veces que el bucle for diga
    }
    bucle = true; // una vez bien curado el tomate bloqueamos futuras activacion del for
  }
// continua el programa subiendo hasta los 42 despues bajara hasta finalizar sin activar el for

Creo que es lo que queria hacer. Y gracias por la explicación, curioso lo de la doble comparación no lo habia visto nunca.
Saludos.

Si yo entendí la intención pero el programa queda bloqueado ahí, eso es lo que veo mal.

Fijate que hasta que no baje de 34 se planta ahí e inmediatamente se planta otra vez hasta llegar a 36.
Pero si la temp está bajando, cómo sube a 36?
Y encima lo hace 3 veces.

Saludos

Hola ,Gonpezzi fue un regalo de RIG, hace un par años en este foro. y funciona así, el pin Digital 10 como (entrada INPUT), si recibe 0 voltios el relePinA se apaga a 40° centígrados, y si el pin Digital 10 recibe 5 voltios apaga el relePinA a 42° su nombre es algo de triunvirato. Yo lo uso con un interruptor de tres vías el pin derecho 0 voltios, el pin izquierdo gnd, y el pin central va a pin digital 10 por eso en el codigo esta el pin 8 tiene programada salida gnd y el pin 9 5 voltio. Por cierto no e visto al señor RIG por el foro, es todo un genio de la programación y si me comento que es muy poco conocida esa función. Nos ayudo mucho en su momento a mi y a mis compañeras de la escuela .
Bueno Ginpezzi voy ha ver como funciona tu idea y te comento.

Saludos.

Hola gatul; si también actúa sobre el relepinA tres veces

Yo creo que IgnoranteAbsoluto, tiene toda la razón, la maquina de estados es la mejor opción, ya intente con for while , con switch case, es mas dentro de mi código hay una maquina de estados (unsigned long instante anterior;) o estoy equivocada?. Alguna sugerencia, me recomendó un par de enlaces, así que me aplico a trabajar en ello.
saludos

Hola gonpezzi, ya lo agregue al código, y subió la temperatura de 29° a 36° y se paralizo la lectura de la temperatura, ni en LCD ni en el monitor Serial, y el relePinA se quedo apagado. como puedo hacer para que se muestre la temperatura dentro del bucle for.
La función se llama "operador ternario" no triunvirato disculpa el error de mi memoria, andaba en la época de los Romanos. (Sistema de gobierno).
Saludos.

Hola ignoranteabsoluto, gracias por la explicación, ya no recordaba con claridad como funcionaba el operador ternario. Y tiene razón el código debo agregarle una máquina de estados, (unsigened long intanteanterior;) es una maquina de estados?.

Si así, es tenia la solución dentro del mismo código sin darme cuenta.
saludos.