Go Down

Topic: Prevenir que un Switch case se interrumpa antes de completar su funcion?  (Read 3418 times) previous topic - next topic

AlexLPD

Hola buen día...

El asunto es que tengo un controlador de temperatura que es gobernado por un DS1822... no habia porblemas pero;

El control tiene 3 estados, todos dependen de la temperatura

1-.- enciende compresor (A los 7°C)
2.- Apaga compresor (a los 3°C)
3.- Venitacion controlada.

Cada una es una maquina de estado finito, pero estando aqui con el cliente me platico que el control hace cosas raras... lo estuve observando y cuando la temperatura llego a 6.75°C ... inicio el ciclo de refrigeracion... pero se detuvo por que la sonda marco 7.00 y despues 6.75... con el consiguiente descontrol.

Me gustaria saber si esta es la manera decuada de agregar una guarda boleana para que el programa  una vez que inicia la maquina de estado finito... no se detenga hasta completarla...

(solo les dejo el codigo correspondiente, el completo es demasiado grande)

Code: [Select]

void thermostat()
{
//---------------thermostat sequence
     
     if(tempC >= highTemp )
     {
       turnOnCompressor();
       refrigerationBegin = true;
     }
     
     if(tempC <= lowTemp  )         
     {
       turnOffCompressor();
       refrigerattionEnd = true;
     }
     
     
     if( cycleFansvar == true &&  refOff == false )       // to cycle only once the set of the instructions per cycle.)
     {
       if(tempC < highTemp -0.25)  cycleFans();
     } 
     
      Serial.print("temperatura =  "); Serial.println(tempC); 


}


Y aqui esta la supuesta guarda booleana en la maquina de esta finitio.. es correcto?


Code: [Select]

void turnOnCompressor(){

/*
This subrutine is intended to stop the refrigeration cycle
in the most ordered way, and keeping the refrigerant on
the high side of the system.
*/

// boolean refrigerattion = false; // var to handle ref status only once
// byte compOn = 0;
// byte pascomOn = 0; //to chek if the variable has updated.
// unsigned long  comOnTime  = 0;
// unsigend long  comOnDelay = 1500;
// unsigend long  comOnCT    = 0;     //the current time of the compressor.

//------for debug only
//Serial.print("comOnCT  =             "); Serial.println(comOnCT);
//Serial.print("comOnCT - millis()  =  "); Serial.println(millis() - comOnTime );

// Serial.println("INICIANDO REFRIGERACION");


if(refrigerationBegin == true )
{


if(refrigerattion == true && millis()- comOnTime  >= comOnDelay ){
   compOn ++;
   comOnTime = millis();
 /*
 //--------for debug only
 Serial.println("---------------------");
 Serial.print("Var compOn "); Serial.println(compOn);
 Serial.print("comoON  "); Serial.println(compOn);
 Serial.print("pascomON"); Serial.println(pascomOn);
 Serial.println("---------------------");
*/
}

if(compOn > pascomOn ){

  switch(compOn){
 
  case(1):
  lcd.setCursor(0,0);  lcd.print(F("      CICLO DE      "));
  lcd.setCursor(0,1);  lcd.print(F("    REFRIGERACION   "));
  lcd.setCursor(0,2);  lcd.print(F("                    "));
  break;
 
  case(2):
  lcd.setCursor(0,0);  lcd.print(F("    REFRIGERACION   "));
  lcd.setCursor(0,1);  lcd.print(F("     ENCENDIENDO    "));
  lcd.setCursor(0,2);  lcd.print(F("       VENT 1       "));
  digitalWrite(dif1, LOW);
  break;
 
  case(3):
  lcd.setCursor(0,0);  lcd.print(F("    REFRIGERACION   "));
  lcd.setCursor(0,1);  lcd.print(F("     ENCENDIENDO    "));
  lcd.setCursor(0,2);  lcd.print(F("       VENT 2       "));
  digitalWrite(dif2, LOW);
  break;

  case(4):
  lcd.setCursor(0,0);  lcd.print(F("    REFRIGERACION   "));
  lcd.setCursor(0,1);  lcd.print(F("     ENCENDIENDO    "));
  lcd.setCursor(0,2);  lcd.print(F("      SOLENOIDE     "));
  digitalWrite(solenoid, LOW);
  break;

  case(5):
  lcd.setCursor(0,0);  lcd.print(F("    REFRIGERACION   "));
  lcd.setCursor(0,1);  lcd.print(F("     ENCENDIENDO    "));
  lcd.setCursor(0,2);  lcd.print(F("      COMPRESOR     "));
  digitalWrite(compressor, LOW);
  break;
 
  case(6):
  lcd.setCursor(0,1);  lcd.print(F("                    "));
  lcd.setCursor(0,2);  lcd.print(F("                    "));
  refrigerattion = false;
  refOff = true     ;       // to cycle only once the set of the instructions per cycle.
  compOn = 0;
  cycleFansvar = false;        //bool to chek the refrigerattion has stop
  //--------------------------------
  //refrigerattion = true; add this variable at the end of the off routine to cycle the
  //operation otherwise will just start once
}
}
}

refrigerationBegin = false;
}



Gracias de antemano.

-Alex.

surbyte

Lo que veo que estas dentro del error LSB del sensor y no lo previste?
Otra cosa al final de tu switch case veo que no pusiste break;

Code: [Select]
      case 6: // ERROR
              // porque entre paréntesis case(6) nunca lo había visto

            lcd.setCursor(0,1);  lcd.print(F("                    "));
            lcd.setCursor(0,2);  lcd.print(F("                    "));
            refrigerattion = false;
            refOff = true     ;       // to cycle only once the set of the instructions per cycle.
            compOn = 0;
            cycleFansvar = false;        //bool to chek the refrigerattion has stop
            //--------------------------------
            //refrigerattion = true; add this variable at the end of the off routine to cycle the       
            //operation otherwise will just start once

            //FALTA EL BREAK ???????
            break; // FALTABA ESTE BREAK
        }
  }


No se a que llamas guarda boleeana?

AlexLPD

Hola Surbyte... tanto tiempo..

No entiendo las siglas LSB... pero tengo otro control instaldo en una farmaceutica y ese no tiene problemas
el detalle creo yo... surge cuando se interrumpe...

la guarda boleana en la que habia pensado es;

Code: [Select]


  if(tempC >= highTemp )
     {
       turnOnCompressor();
       refrigerationBegin = true; //inicia la maquina de estado finito
     }

case 6:
refrigerattionbegin = false; // solo se interrumpe esta funcion hasta que haya terminado de arranacar.



Ahora... es curioso lo de los parentisis... lo copie del ide.. es tal como lo tengo aca... te da error?

Estoy usando un arduino mega y la ultima districución del ide.


En otras palabras... como puedo hacer para que una vez que se incie refrigeracion... no se intettumpa el proceso  hasta que se complete el ciclo de encendido...
Igual con el apagado...


Gracias.
-Alex.


AlexLPD

Otra cosa que supogo que se puede hacer... es

If (temC == highTem)
{
if(millis() - temptime > tempDelay )
{
refrigerattionON
}
}


Como ves?

Un pequeño debounce para que la sonda no nos ande con sus loqueras..
o ... quizas tambien poner un delay de digamos 500ms entre cada lectura
(actualmente el codigo corre solo, es decir tantas veces por loop como pueda)


Pero no se.. en tu experiencia que es mejor?

Que me recomiendas mas?

Gracias.
-Alex

surbyte

No me da error, solo lo vi y me resulto que estaba mal. 
Igualmente viste que el ultimo case no tiene break?
No te diste cuenta de ese detalle. Lee el código donde te pongo ERROR.
Si funciona con () me disculpo. No lo sabía. Tampoco lo voy a probar. Hay cosas con las que estoy acostumbrado a trabajar y si no es necesario no me sirve ni aporta nada usar ().
Es cuestion de gustos.

LSB es dígito menos significativo. Todo AD cuando convierte tiene un error que se expresa en funcion de su dígito LSB. a veces es +-1 a veces es +- 2. En tu caso, tu DS18B20 oscila en las lecturas en 0.25 grados asi que debes considerar eso. 
Normalmente se agrega una histeresis, o banda de cambio. Entonces si baja de 7 grados accionas pero para que se restaure la situación debe superar 7 mas un Delta que puede ser 0.5 grados. Asi evitas ese cambio molesto.
Todo depende de la inercia termica de tu sistema. Pero el sensor siempre puede estar dando valores proximos y bascular entre estos.
hasta donde vi tu máquina de estados estaba bien, la haces diferente a mi, pero me gustó tu enfoque.
El debounce no se si funcione...  yo lo que haria sería tratar de loggear la situación y luego cuando veas lo loggeado intentar resolverlo.
Pero encararía esto que te dije. 

AlexLPD

Si... Revisaré el código.... Agregare el break... Cuando dices loggear.. Te refieres a imprimir lo q pasa en la terminal serial?

Gracias.
Gracias.
Alex

surbyte

No. 
Me refería a registrar todo en una SD para luego graficarlo con algo.

AlexLPD

Pues si.. Tengo un datalogger pero creó q para esto fuera útil necesitaría... Grabar el voltaje a cada contacto (para saber cual esta encendido) la temperatura..... Y en q línea aproximadamente del programa estamos. (Para verificar dnd se congela)

Revise el código... Si le faltaba un break al original. Subiré  alguna otra subrutina a ver si le ves q me falta algo.

Gracias
Alex

AlexLPD

Hola de nuevo... bueno pues algo muy raro pasa aqui...
Decidi hacer un programa para un amigo con un arduino y unos reles que le voy a regalar para que se interese en el mundo del arduino y cual fue mi sorpresa cuando estaba escribiendo;

Code: [Select]
switch (program)
{
  case (1):
  lucesSecuenciales = true;
  lucesMovimiento = false;
  lucesMovimientoSonido = false;
  demo = false;
  break;

  case (2):
  lucesMovimiento = true;
  break;

  case (3):
  lucesMovimientoSonido = true;
  break;

  default:
  demo = true;
  break;


y  el complilador me da ERROR!!!!

Lo configure para uno en la mañana por que tuvimos ue improvisar un sensor de temperatura, para una maquina que el suyo se descompuso y tuve que destripar el datalogger... ya no tenia mas placas a la mano...

Lo curioso es que el codigo original puesto aqui, si compila... y se sube a MEGA.. incluso esta funcionando!!!!!

Que cosas de la vida... !!!!

-Alex.

AlexLPD

Bueno les cuento que les agregue las guardas boleanas a las maquinas de estado finito.. algo mas pasa... algo que no tenía contemplado... Igual es error de la programacion... (el mentado swich case) Igual es algo mas..
pero ahora... digamos que esta encendiendo o apagado ... se reincia el control. Normalmente tiene el watchdogtimer a 8 segundos pero nunca hasta ahora habia entrado, igual el break que faltaba hacia cosas raras... o no terminaba el programa y quizas no habia pero tampoco habia continudad en la programacion.

Mañana le cambiare los parentesis. Y veremos que sucede. Ahora bien... el asunto de las guardas boleanas puede ser usado para reiniciar la maquina de estado finito. Me imagino algo asi;

Code: [Select]
if (completeFSMref == true){

If (refrigerattionON == true)
{
//comienza FST
case 1...
case 2...
case 3...
case 4: refrigerattionON = false;
           completeFSMref = true;
{
else
{
timporefrigeracion = millis()
refrigeracionSM = 0;
//reinicia las variables de la maquina de estado... de maner que si no se termina e ciclo
}


Lo de arriba es pseudocodigo, es solo otra redundancia en caso de que algo salga mal.

Bueno, me despido buenas noches.

Gracias por sus comentarios.
-Alex

surbyte

Hola de nuevo... bueno pues algo muy raro pasa aqui...
Decidi hacer un programa para un amigo con un arduino y unos reles que le voy a regalar para que se interese en el mundo del arduino y cual fue mi sorpresa cuando estaba escribiendo;

Code: [Select]
switch (program)
{
  case (1):
  lucesSecuenciales = true;
  lucesMovimiento = false;
  lucesMovimientoSonido = false;
  demo = false;
  break;

  case (2):
  lucesMovimiento = true;
  break;

  case (3):
  lucesMovimientoSonido = true;
  break;

  default:
  demo = true;
  break;


y  el complilador me da ERROR!!!!

Lo configure para uno en la mañana por que tuvimos ue improvisar un sensor de temperatura, para una maquina que el suyo se descompuso y tuve que destripar el datalogger... ya no tenia mas placas a la mano...

Lo curioso es que el codigo original puesto aqui, si compila... y se sube a MEGA.. incluso esta funcionando!!!!!

Que cosas de la vida... !!!!

-Alex.
o sea que case (1) no es válido o si?
Nunca lo había visto, pero me puedo equivocar. Lo mas justo sería decir que jamas YO lo he usado.

noter

No son necesarios en este caso, pero los paréntesis no afectan. Tan sólo "aislan". Donde se recomiendan típicamente, por ejemplo, es en las expresiones en define, por eso mismo: para aislar la expresión.

AlexLPD

El detalle ... es que en el mega todo marchaba "bien"
Pero en cuanto me puse a hacer un porgrama similar en UNO

El compilador me decia que algo estaba mal en switch case... no le vi nada malo, hasta que quite los parentesis del primero y entonces me marco el segunto... le removi todos y dejo de darme error...

Saben si es diferente para uno que para mega?

Lo mejor va  a ser como dice surbyte... no usar los parentesis.

Alex.

uargo

Sin entrar en detalles en todas las aplicaciones de temperatura deberias hacer una histeresis con codigo
si no sabes lo que es histeresis busca en google

AlexLPD

Hola que tal!

Incialmente lo tenía.. lo he buscado creo que te refieres a esto;

Code: [Select]
IF ((temp>=21) | (temp<=28)){
output_low(RELE);
}
IF ((temp<21) | (temp>28)){
output_high (RELE);



Entiendo que comunmente le denomina hiterisis a un "espacio" para tomar le desicion en este tipo de aparatos, sin emabargo tuve probelamas para implementarlo... por ejemplo... si el cuarto por alguna razón estuviera mas caliente de lo normal no arrancaría.. ya me ha pasado.

Quizas agregar alguna otra condición... la verdad hemos tenido muchas carreras y no me he sentado a ver esto..

Gracias por la sugerencia.

En un comentario en general... la gurada boleana funciona, la maquina de estado finito no se interrumpe mas, asi que solo queda quitarle los parentesis y esperar a ver que sucede.

Gracias.
-Alex.



Go Up