Go Down

Topic: Mi arduino se sale del Loop (Aparentemente) (Read 8785 times) previous topic - next topic

AlexLPD

Hola a todos, muchas gracias por la información que recibi de todos ustedes en post anterior. Esta vez algo raro esta pasando y me pregunto si tiene que ver con que me haya brincado algun truquito, o en que realidad soy muy malo programando =)

Bueno, larga historia corta, uso el arduino para controlar los ventiladores dentro de una camara de refrigeración. Esta dentro de mi tablero, como pueden ver. Tiene su fuente y sus relevadores.
La cosa es que asi de repente parece que se quedara "pegado".

Me explico; la subrutina void refrigeracion(); depende exclusivamente de que la variable termostato, este en HIGH... y le he visto con mis propios ojos... le medi 4.46V... por lo que debio entrar la subrutina.... me llamo la atencion, conecte mi celular, para ver que tiraba el serial (gracias Android)... y nada... nada de nada... sin mover ningun dato, oprimí el rest del arduino y voila... todo funciono normal.

Detalle extra... estuvo funcionando sin problemas por una semana.... despues comenzo a tirarse al rededor de las 5pm... tres dias consecutivos, en los que tuvo que ser reiniciado manualmente, y ahora por lo que me dicen... dura unas tres horas de operacion efectiva.

Ideas?
Quizas alguna variable?
Quizas el loop encuentra en una fraccion de segundo que no se cumplen
ninguna de las condiciones logicas?
Y como evitarlo??


Les dejo el código tal cual esta...
Code: [Select]

//TODAS LAS SALIDAS ESTAN INVERIDAS PARA PODER OPERAR LA TABLILLA DE RELAYS
//EJEMPLO, SI NECESITO ENCENDER UN FOCO EN LUGAR DE
// digitalWrite(focoDes, HIGH);
//ESCRIBIMOS;
//digitalWrite(focoDes, LOW);
//DEBIDO A COMO OPERAN LOS RELEVADORES.


// DECLARACION DE PINES A SER USADOS EN EL PROGRAMA
int comp =13;                 // Pin para control del compresor
int sol = 12;                 // pin para el control de la solenoide
int motores[4] = {8,9,10,11}; //Pines controlar motores del difusor 
int focoRef= 6 ;              //Pin para encender el foco de la refrigeracion
int focoDes= 5 ;              //Pin para encender el foco deshielo
int Term = 4;                 //Pin para leer el estado del termostato
int SW2 = 3;                  //pin para leer el switch principal
int SW1 = 2;                  //pin para leer el switch principal

//DECLARACION DE VARIABLES GLOBALES
int Switch = 0;               //variable para almacenar el estado del switch
int EdoSW1 = 0;
int EdoSW2 = 0;
int EdoTerm = 0;             //para alamcenear el estado del termostato
int caso = 1;                //variable de 1 a 4 para alternar los motores difussor
boolean Encendido = false;   //Variable para comparar si se ha encendio o apagado el termostato


//            fila / columna                 
int ArrayMotores[6][4] ={{HIGH, HIGH, HIGH,  HIGH  } , //Primer arreglo de encendio de motores
                         {LOW,  HIGH, HIGH,  HIGH  } ,// Segundo... cada 1 y 0 corresponden a un motor
                         {HIGH, LOW , HIGH,  HIGH  } , //encendido o apagado.
                         {HIGH, HIGH, LOW ,  HIGH  } ,
                         {HIGH, HIGH, HIGH,   LOW } ,
                         {LOW,  LOW,  LOW,   LOW } , 
                          };

void setup(){
  Serial.begin(9600);
  pinMode(comp, OUTPUT);
  pinMode(sol, OUTPUT);
  pinMode(focoRef, OUTPUT);
  pinMode(focoDes, OUTPUT);
  pinMode(Term, INPUT);
  pinMode(SW1, INPUT);
  pinMode(SW2, INPUT);

  for(int b; b<4; b++){            //inicia contador de 1 a 4
    pinMode(motores[b], OUTPUT);   //declara cada motor como pin de salida
    digitalWrite(motores[b], HIGH); //Apaga cada motor
  }
}

void loop(){
EdoSW1 =  digitalRead(SW1);
EdoSW2 =  digitalRead(SW2);

  if(EdoSW1 ==1 && EdoSW2 ==0){
     Switch=1;
     }
     if(EdoSW1 ==0 && EdoSW2 ==1){
         Switch=2;
      }
        if(EdoSW1 ==0 && EdoSW2 ==0){
          Switch =0;
        }

  switch(Switch){
  case 0:
    Serial.println("El switch esta apagado");
    delay(200); //remover en la verson final
    digitalWrite(focoRef, HIGH);
    digitalWrite(focoDes, HIGH);
    AllOff();
    break;

  case 1:
    Serial.println("El switch esta en refrigeracion");
    delay(200); //remover en la version final
    digitalWrite(focoRef, HIGH);
    digitalWrite(focoDes, LOW);
    refrigeracion();
    break;
   
  case 2:
    Serial.println("El switch esta en deshielo");   
    delay(200);// remover en la version final
    digitalWrite(focoRef, LOW);
    digitalWrite(focoDes, HIGH);
    deshielo(); 
    break;
  }
  delay(250);
}

// subrutina de deshielo, deja encendido solo los motores del evaporador.
void deshielo(){
  digitalWrite(sol,LOW);  //enciende la solenoide
  delay(1000); //remover en version final);
  digitalWrite(comp, HIGH); //apaga el compresor
  delay(1000); //remover en version final

  for(int a; a<4 ; a++){
    digitalWrite(motores[a], ArrayMotores[5][a]);
    delay(1000);
  }
}


// subrutina para apagar todo; compresor, solenoide, evaporador.
void AllOff(){
  digitalWrite(sol,HIGH);  //Apaga  la solenoide
  delay(500);           //remover en version final);
  digitalWrite(comp, HIGH); //apaga el compresor
  delay(200); //remover en version final
  for(int u; u<4; u++){
    digitalWrite(motores[u], ArrayMotores[0][u]);
  } 
}

//subrutina que encendera la refrigeracion y alternara los motores del
//difusor.

void refrigeracion(){
  EdoTerm = digitalRead(Term);
       
            if(caso >= 5){
            caso=1;}       
 
        if(EdoTerm == HIGH){
          digitalWrite(sol, HIGH);   //Apaga la solenoide, deja pasar liquido
           for(int d; d<4; d++){
              digitalWrite(motores[d], ArrayMotores[5][d]);
              delay(1000);
              }
              delay(1000);               //retraso en la entrada del compresor
              digitalWrite(comp, LOW);  //enciende el compresor
              Serial.print("El termostato esta encendido  "); Serial.println(caso);
              Encendido = true;
              }
           
      if(EdoTerm == LOW){
             if(Encendido == true){
             caso++;}
             Serial.print("El termostato esta apagado ");
             Serial.print("comienza subrutina"); Serial.println(caso);
             digitalWrite(sol, LOW);  //Enciende solenoide, no pasa liquido
             delay(1000);              //retraso en la entrada del compresor
             digitalWrite(comp, HIGH);  //Apaga el compresor
             for(int e; e<4; e++){
             digitalWrite(motores[e], ArrayMotores[caso][e]);
            }     
            Encendido = false;
            }
}
 


Y algunas fotillos para que vean a que nos enfrentamos, en ellas esta el diagrama, combina los 5v del arduino con controles 220V etc etc..

Si lo requieren hago un video explicativo de que funciones realiza el pequeño aparato, aunque creo que esto es mas centrado en el codigo..  ::)

Muchas gracias de antemano!!!!



PeterKantTropus

Es mas que probable que se trate de un caso de ruido, pero para descartar problemas deberías ver si no se esta acabando la memoria de tu arduino por algún Bug. Para ello puedes usar la librería MemoryFree.h
agregando:

#include <MemoryFree.h> al principio  y     Serial.println(freeMemory()); en el loop .
 No se debería producir cambios en la memoria.

Saludos
"Si no entra como tornillo, entra como clavo"

AlexLPD

Es mas que probable que se trate de un caso de ruido, pero para descartar problemas deberías ver si no se esta acabando la memoria de tu arduino por algún Bug. Para ello puedes usar la librería MemoryFree.h
agregando:

#include <MemoryFree.h> al principio  y     Serial.println(freeMemory()); en el loop .
 No se debería producir cambios en la memoria.

Saludos
Muchas gracias, haré la prueba como me lo indicas, de casualidad, tengo que dejar esas instrucciones en el programa final?

Puede ser que en algún momento no se cumpla con ninguna de los tres criterio lógicos? y necesite un else que reinicie el loop?.

Gracias!!!

PeterKantTropus

Leyendo el post veo que te falta el caso que edoSw1 y edoSw2  ambos sean igual a 1   ¿ no se pueden dar al mismo tiempo ese caso?
una pequeña critica: evita utilizar palabras reservadas como variable. A pesar que es valido utilizar  Switch con mayúscula como variable, puede dar lugar a equivocaciones.

Controla también la temperatura del armario donde se encuentra el arduino.

Saludos
"Si no entra como tornillo, entra como clavo"

AlexLPD

Bueno, he agregado la librerria free memory en caso de que me permita ver que sucede.

Tambien he agregado;
Code: [Select]

if(EdoSW1 ==1 && EdoSW2 ==0){
     Switch=1;
     }
     else if (EdoSW1 ==0 && EdoSW2 ==1){
         Switch=2;
      }
     else if (EdoSW1 ==0 && EdoSW2 ==0){
          Switch =0;
        }
        else(loop());


en caso de que por cualquier cosa, no tenga logica ninguno de esos estados... regresar al loop.. e intentarlo de nuevo.


Muchas gracias.  les comento cualquier cosa.

AlexLPD

Leyendo el post veo que te falta el caso que edoSw1 y edoSw2  ambos sean igual a 1   ¿ no se pueden dar al mismo tiempo ese caso?
una pequeña critica: evita utilizar palabras reservadas como variable. A pesar que es valido utilizar  Switch con mayúscula como variable, puede dar lugar a equivocaciones.

Controla también la temperatura del armario donde se encuentra el arduino.

Saludos
Gracias, efectivamente, en teoria no se podria, ya que estos estados estan en un switch de tres posiciones, de manera que solo pueda existir uno de los dos en 1, o los dos en 0, sin emabrgo en la practica, parece que cualquier voltaje parasito, puede llegar a interpretarse como 1 y 1 ... en cuyo caso me imagino que el pregrama se detendria, que es justo lo que pasa.

Lo acabo de notar, por que despues de hacer las modificaciones arriba señaladas, la cargue en un UNO y lo instale, la primera vez todo magnifico, pero al reinicial los termicos generales, empezaron a activarse y apagarse varias cosas, me imagino que la subita subida de corriente indujo estados en los pines, y dio paso a este error, para evitarlo estoy agregando pequeñas pausas en el programa;
Code: [Select]

if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(200);
    Switch=1;
     }
     else if (EdoSW1 ==0 && EdoSW2 ==1){
        delay(200);
        Switch=2;
      }
     else if (EdoSW1 ==0 && EdoSW2 ==0){
        delay(200);   
        Switch =0;
        }
     else{
       delay(200);
       loop();
     }


Bueno, ire a probarlo y les mantengo informados, gracias.
Y si... procurare no usar palabras parecidas a las reservadas XD.
Saludos!!!!

AlexLPD

Bueno, pues resulta que durante las 4 horas que estuvimos  ahi, al pie del tablero, todo funciono normal todo funciono perfectamente, sin embargo unas 4 hr después, me llamaron que por que había habido una falla... al llegar... lo mas extraño, es que esta vez no solo todos los ventiladores estaban apagados, sino que tambien, el compresor estaba encendido...

A saber, el compresor, entra una linea y un delay despues de que todos los ventiladores se han encendido.



Ahora que he quitado que sea una lectura incorrecta de el SW, y que falle por un tercer estado logico...

Sera que falta... Serial.flush() ??? y se llena la memoria??
Intente conectar el serial cuando estaba en la falla... pero no pude leer nada... simplemente se detiene en algun punto...

Ahora en cuanto al hardware... tendra que ver que la tablilla de relays es alimentada de la misma fuente... recuerdo haber leído que habia un jumper para hacer que funcionara completamente optoisolada...

Alguna otra idea???

Gracias.

surbyte

Tienes ruido, ruido y mas ruido.
Comiena mostrando como son las conexiones al Arduino de todas las entradas digitales.

AlexLPD

Parece ser el caso.
Bueno, lo que me pides sería;

Pin 2    INPUT     lee 5V del Switch principal
Pin 3    INPUT     lee 5V del Switch principal
Pin 4    INPUT     Lee 5v del termostato
Pin 5    OUTPUT  enciente relevador del foco refrigeracion
Pin 6    OUTPUT  enciende relevador del foco de deshielo

Pin 8    OUTPUT  enciende relevador del motor 1 
Pin 9    OUTPUT  enciende relevador del motor 2
Pin 10  OUTPUT  enciende relevador del motor 3
Pin 11  OUTPUT  enciende relevador del motor 4
Pin 12  OUTPUT  enciende relevador del compresor
Pin 13  OUTPUT  enciende relevador del solenoide
 
Ahora bien del Pin 5 al 13... todos van a la tablilla de relevadores que se ubica a unos 5 cm del arduino. Son los cablesillos que se ven volando en la foto.


El pin 2 y 3... van a lo que es la tapa del gabinete, esos si pasan por unos 70cm entre otros cables
que pueden ser desde focos piloto 220V hasta alguna de las bonidas a 220 de los contactores.
Cre que se alcanzan a distinguir, un cable azul y uno amarillo en el manojo inferior de la tapa del gabinete, en alguna de  las fotos.
Ambos cables tienen su resistencia a tierra para no dejar un voltaje flotante.

Ahora bien, cureseandole en el foro en este thread;
http://forum.arduino.cc/index.php?topic=119683.0

Quote
las entradas que no estén conectadas a ninguna lados las pongas en pullup o como salidas, principalmente para reducir consumo y ruido electrico (no es bueno dejar entradas flotantes en tecnología CMOS).
Eso tiene cierto sentido, pero no se hasta que punto el arduino se detenga o se salga del programa cuando recibe un voltaje o señal en los pines que no están siendo usados.
Ahora bien, algo interesante en el mismo hilo;

Quote
Yo lo he solucionado con un simple delay justo después de comprobara la entrada y acto seguido otra comprobación.

Adjunto trozo del código:

if(digitalRead (pullbano) == 0 ) {
           delay (100);
           if(digitalRead (pullbano) == 0 ) {
Quizás tambien falle la lectura de los pines, ya que por ejemplo; los 5V que lee el pin del termostato, pasan por un el contacto de un contacto, me imagino que dependiendo del caso, en el momento del cierre puede producirse un a variación en el voltaje que no sea ni 5V no 0V, pero no se como lo tomaría el arduino.

Creo que haré ese pequeño debounce que proponen en las tres lecturas, ademas de declarar los pines no usados como salidas. Curiosamente son los analogicos.

De cualquier manera espero me puedan dar mas ideas, para ir cerrandole el paso a esta falla tan extraña.

Gracias!!!!!

AlexLPD

Bueno he hecho las modificaciones al codigo como quede, lo probe en una proto, y como es buena hora, ire a ponerlo, asi me da tiempo regresar a manual, en caso de que haya una falla en un rato.


Les dejo el codigo, a ver si le notan algo;
Code: [Select]

//TODAS LAS SALIDAS ESTAN INVERIDAS PARA PODER OPERAR LA TABLILLA DE RELAYS
//EJEMPLO, SI NECESITO ENCENDER UN FOCO EN LUGAR DE
// digitalWrite(focoDes, HIGH);
//ESCRIBIMOS;
//digitalWrite(focoDes, LOW);
//DEBIDO A COMO OPERAN LOS RELEVADORES.

//DECLARACION DE LIBRERIAS
#include <MemoryFree.h>


// DECLARACION DE PINES A SER USADOS EN EL PROGRAMA
int comp =13;                 // Pin para control del compresor
int sol = 12;                 // pin para el control de la solenoide
int motores[4] = {8,9,10,11}; //Pines controlar motores del difusor  
int focoRef= 5 ;              //Pin para encender el foco de la refrigeracion
int focoDes= 6 ;              //Pin para encender el foco deshielo
int Term = 4;                 //Pin para leer el estado del termostato
int SW2 = 3;                  //pin para leer el switch principal
int SW1 = 2;                  //pin para leer el switch principal


//DECLARACION DE PINES QUE NO SERAN USADOS
int pinesNoUsados[6] ={A0, A1, A2, A3, A4, A5};

//DECLARACION DE VARIABLES GLOBALES
int Switch = 0;               //variable para almacenar el estado del switch
int EdoSW1 = 0;
int EdoSW2 = 0;
int EdoTerm = 0;             //para alamcenear el estado del termostato
int caso = 1;                //variable de 1 a 4 para alternar los motores difussor
boolean Encendido = false;   //Variable para comparar si se ha encendio o apagado el termostato


//            fila / columna                
int ArrayMotores[6][4] ={{HIGH, HIGH, HIGH,  HIGH  } , //Primer arreglo de encendio de motores
                         {LOW,  HIGH, HIGH,  HIGH  } ,// Segundo... cada 1 y 0 corresponden a un motor
                         {HIGH, LOW , HIGH,  HIGH  } , //encendido o apagado.
                         {HIGH, HIGH, LOW ,  HIGH  } ,
                         {HIGH, HIGH, HIGH,   LOW } ,
                         {LOW,  LOW,  LOW,   LOW } ,  
                          };

void setup(){
  delay(500);
  Serial.begin(9600);
  pinMode(comp, OUTPUT);
  pinMode(sol, OUTPUT);
  pinMode(focoRef, OUTPUT);
  pinMode(focoDes, OUTPUT);
  pinMode(Term, INPUT);
  pinMode(SW1, INPUT);
  pinMode(SW2, INPUT);
  delay(250);
  for(int b; b<4; b++){            //inicia contador de 1 a 4
    pinMode(motores[b], OUTPUT);   //declara cada motor como pin de salida
    digitalWrite(motores[b], HIGH); //Apaga cada motor
   }
 for(int z; z<5; z++){
   pinMode(pinesNoUsados[z], OUTPUT); //declara cada pin sin usar como salida
   pinMode(pinesNoUsados[z], HIGH);   //pone cada pin no usado a 5V
   }
 delay(500);
}

void loop(){
  Serial.print("freeMemory()=");
  Serial.println(freeMemory());
  delay(50);
  Serial.println("Inicia Lectura de SW");
  EdoSW1 =  digitalRead(SW1);
  EdoSW2 =  digitalRead(SW2);

  if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(100);
    if(EdoSW1 ==1 && EdoSW2 ==0){
    Switch=1;
     }}
     else if (EdoSW1 ==0 && EdoSW2 ==1){
        delay(100);
        if (EdoSW1 ==0 && EdoSW2 ==1){
        Switch=2;
      }}
     else if (EdoSW1 ==0 && EdoSW2 ==0){
        delay(100);  
        if(EdoSW1 ==0 && EdoSW2 ==0){
        Switch =0;
        }}
     else{
       delay(200);
       loop();
     }

  Serial.println("Termina lectura de SW");
  delay(50);
  Serial.flush();

  switch(Switch){
  case 0:
    Serial.println("SW apagado");
    delay(100); //remover en la verson final
    digitalWrite(focoRef, HIGH);
    digitalWrite(focoDes, HIGH);
    AllOff();
    break;

  case 1:
    Serial.println("SW en refrigeracion");
    delay(100); //remover en la version final
    digitalWrite(focoRef, HIGH);
    digitalWrite(focoDes, LOW);
    refrigeracion();
    break;
    
  case 2:
    Serial.println("SW en deshielo");  
    delay(100);// remover en la version final
    digitalWrite(focoRef, LOW);
    digitalWrite(focoDes, HIGH);
    deshielo();  
    break;
  }
  delay(150);
}

// subrutina de deshielo, deja encendido solo los motores del evaporador.
void deshielo(){
  digitalWrite(sol,LOW);  //enciende la solenoide
  delay(1000); //remover en version final);
  digitalWrite(comp, HIGH); //apaga el compresor
  delay(1000); //remover en version final

  for(int a; a<4 ; a++){
    digitalWrite(motores[a], ArrayMotores[5][a]);
    delay(1000);
  }
}


// subrutina para apagar todo; compresor, solenoide, evaporador.
void AllOff(){
  digitalWrite(sol,HIGH);  //Apaga  la solenoide
  delay(500);           //remover en version final);
  digitalWrite(comp, HIGH); //apaga el compresor
  delay(200); //remover en version final
  for(int u; u<4; u++){
    digitalWrite(motores[u], ArrayMotores[0][u]);
  }  
}

//subrutina que encendera la refrigeracion y alternara los motores del
//difusor.

void refrigeracion(){
  EdoTerm = digitalRead(Term);
        
            if(caso >= 5){
            caso=1;}      
  
        if(EdoTerm == HIGH){
          delay(100);
          if(EdoTerm == HIGH){
          digitalWrite(sol, HIGH);   //Apaga la solenoide, deja pasar liquido
           for(int d; d<4; d++){
              digitalWrite(motores[d], ArrayMotores[5][d]);
              delay(1000);
              }
              delay(1000);               //retraso en la entrada del compresor
              digitalWrite(comp, LOW);  //enciende el compresor
              Serial.print("Termostato encendido  "); Serial.println(caso);
              Encendido = true;
              }}
          
      if(EdoTerm == LOW){
        delay(100);
        if(EdoTerm == LOW){
             if(Encendido == true){
             caso++;}
             Serial.print("Termostato apagado ");
             Serial.print("Comienza subrutina "); Serial.println(caso);
             digitalWrite(sol, LOW);  //Enciende solenoide, no pasa liquido
             delay(1000);              //retraso en la entrada del compresor
             digitalWrite(comp, HIGH);  //Apaga el compresor
             for(int e; e<4; e++){
             digitalWrite(motores[e], ArrayMotores[caso][e]);
            }      
            Encendido = false;
            }}
}


Asi mismo, por ahi acabo de leer que es mejor que la fuente de unos 9V a la entrada del arduino, la mia estaba rateada a 5V, me supongo que eso puede llevar a errores... no lo se todavia, intentare solo con el nuevo programa... ojala haya suerte.

Gracias.

AlexLPD


Bueno, fui la instale y la probé y cual fue mi sorpresa cuando no funciono, nada de nada
no entraba al loop, no leia el SW... estuve un rato verifacando conexiones. Y nada... decepcionado de esta cosa
me traje la tarjeta q tiene los pulldowns de el switch de pres posiciones por que pense que tendria algun error y es que... al SW... si le llegaban los 5V,,, salían del otro lado del SW... 5V pero al llegar a  donde se leen los pines me llegaban 2.0V... asi que no leia el ON... en fin la baje y cual fue mi sorpresa... el cable de tierra estaba roto... creo que esto hacia variar el estado del switch, en fin... mañana le re hare con cable flexible, por que esta cosa de alambre es muy frágil... espero que mejore.

Ya había funcionado una semana completa...  :smiley-sad-blue:  :smiley-sad-blue:  :smiley-sad-blue:

surbyte

#11
Nov 24, 2014, 01:26 am Last Edit: Nov 24, 2014, 05:52 am by surbyte
Tu sketch se comporta un poco raro, no digo que mal porque apenas lo analizo.
Veamos algunas cuestiones para poder ayudarte debidamente.

Todas serán preguntas eléctricas o electrónicas:
A. HARDWARE
1. Alimentación del ARDUINO UNO
1.1. Como alimentas el arduino? Esta es una pregunta muy importante. Intenta ser lo mas detalliasta posible. Todo lo que puedas decir de la fuente. Si es comprada indica el modelo como para investigar su comportamiento ante ruido de línea.
1.2 Tienes filtros RFI en la entrada de la fuente?

2. ENTRADAS DIGITALES
2.1 como cableas las entradas desde los termostatos, Sw1 y 2. Usas cable común, cable con malla ?
2.2 Usas optoacoplador a la entrada? VEO QUE NO según esquema eléctrico

3. SALIDAS DIGITALES
3.1 la salida del arduino es a través de optoacoplador si o no? VEO QUE NO según esquema eléctrico

4. PUESTA A TIERRA
Tienes una puesta a tierra para tu circuito?

OPTOACOPLADORES: por el momento olvidemos su uso. No harían gran cambio.
Si me preocupa el cableado.

B. SOFTWARE
Habia hecho una observación al rebote pero veo que si has tomado la precaución correspondiente.
Lo que no me gusta es el uso de delay, pero antes hay que resolver el problema de funcionamiento.

No entiendo para que vuelves a llamar a Loop() en este pasaje del código?

Code: [Select]
if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(100);
    if(EdoSW1 ==1 && EdoSW2 ==0){
    Switch=1;
     }}
     else if (EdoSW1 ==0 && EdoSW2 ==1){
        delay(100);
        if (EdoSW1 ==0 && EdoSW2 ==1){
        Switch=2;
      }}
     else if (EdoSW1 ==0 && EdoSW2 ==0){
        delay(100);   
        if(EdoSW1 ==0 && EdoSW2 ==0){
        Switch =0;
        }}
     else{
       delay(200);
       loop();              // nunca habia visto esto
     }


Posible error.
Se que te basaste en una rutina de otro HILO pero no siempre las cosas de otros hilos estan bien.
Yo no estoy de acuerdo con esto

Code: [Select]
if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(100);
    if(EdoSW1 ==1 && EdoSW2 ==0){
    Switch=1;
     }
}


mi interpretación de este código me dice lo siguiente.
Instante 0, leo Sw1 y Sw2, ok
Llego al if y pregunto sobre sus estados no importa cuales porque para el caso da lo mismo.
Supongomos son verdaderos los que copie y pegué o sea

EdoSW1 ==1 && EdoSW2 ==0
Luego del primer if viene un delay de 100mseg. Hasta ahi BIEN.
Pero luego vuelves a preguntar
si EdoSW1 ==1 && EdoSW2 ==0 y si en elprimero caso lo fueron en el segundo tambien.
No importa que pase, siempre lo serán. Porque? Porque no volvieron a leerse, son los mismos 100mseg atrás.
Entonces lo que está mal es el código del debounce.
Y por lo tanto, trabajando con contactores y con relés, con rebotes por doquier, no sabes nunca que está tomando el arduino como estado de esos u otros switches.
Ahora te sugiero una rutina debounce que mejore la situación pero sin delay.
La busco y la pego acá.

AlexLPD

Efectivamente hay un detalle muy extraño, por que la primera ocasion, funciono perfectamente durante una semana completa, después daba un error cada 12 hr, despues cada 4... en fin.

A.HARDWARE
1.- La fuente es comprada. Una fuente swichada 110/220 a 5V con una salida maxima de acuerdo a lo que dice; 2.0A.
      Me lei un poco y vi que la alimentacion recomendada para el UNO es de 9 a 12V... lo cual tiene       
      sentido ya que estabamos un poco abajo de los 5V en el retorno de algunos cables.
      Hoy, pensando que ese sería una de las fallas, la he cambiado por otra fuente 110/220 9V 2.0A .
      el unico cambio significativo fue que cambie el VCC de la tablilla de relay a la salida de 5V del     
      arduino.

1.2 No tengo filtros RFI en la salida de la fuente, crees que un par de capacitores de unos 4500uF estén    bien?

2.1- Entradas digitales
Si hay tres cables comunes que van al switch... uno lleva 5V, los otros dos tienen una resitencia pull down en una tablilla adyacente. De esos dos cables, solo uno regresa con 5V a la vez, dando lugar a
tres estados; refrigeracion, apagado, deshielo.

2.2 No tengo optoacopladores.

3.- SALIDAS DIGITALES;
No tengo optoacopladores, del pin, se va directo al pin de control de la tablilla de relays de controles.

4.- Puesta a tierra.- En este apartado, quiero creer que me señalas una tierra física para el circuito, no no la tengo, solo la que sale de la fuente, que es comun entre el arduino y la tablilla de relays.

B. SOFTWARE.-
Debounce... intente implementarlo mediante un sencillo, codigo;
Code: [Select]

 if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(100);
    if(EdoSW1 ==1 && EdoSW2 ==0){
    Switch=1;
     }}
     else if (EdoSW1 ==0 && EdoSW2 ==1){
        delay(100);
        if (EdoSW1 ==0 && EdoSW2 ==1){
        Switch=2;
      }}
     else if (EdoSW1 ==0 && EdoSW2 ==0){
        delay(100);   
        if(EdoSW1 ==0 && EdoSW2 ==0){
        Switch =0;
        }}
     else{
       delay(200);
       loop();
     }


He leido que hay una biblioteca para este tipo de trabajos, me encontre estas dos;
https://www.pjrc.com/teensy/td_libs_Bounce.html

http://playground.arduino.cc/Code/Bounce


Sin embargo me parece un poco mas facil de usar la primera, salvo alguna otra sugerencia. creo que intentare implementar esa.

Muchas gracias, quedo en espera de tus observaciones e ideas, por que a mi francamente este problema ya me comienza a exasperar.




AlexLPD

@surbyte

Tu sketch se comporta un poco raro, no digo que mal porque apenas lo analizo.
Veamos algunas cuestiones para poder ayudarte debidamente.

No entiendo para que vuelves a llamar a Loop() en este pasaje del código?

Code: [Select]
if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(100);
    if(EdoSW1 ==1 && EdoSW2 ==0){
    Switch=1;
     }}
     else if (EdoSW1 ==0 && EdoSW2 ==1){
        delay(100);
        if (EdoSW1 ==0 && EdoSW2 ==1){
        Switch=2;
      }}
     else if (EdoSW1 ==0 && EdoSW2 ==0){
        delay(100);   
        if(EdoSW1 ==0 && EdoSW2 ==0){
        Switch =0;
        }}
     else{
       delay(200);
       loop();              // nunca habia visto esto
     }


Posible error.
Se que te basaste en una rutina de otro HILO pero no siempre las cosas de otros hilos estan bien.
Yo no estoy de acuerdo con esto

Code: [Select]
if(EdoSW1 ==1 && EdoSW2 ==0){
    delay(100);
    if(EdoSW1 ==1 && EdoSW2 ==0){
    Switch=1;
     }
}


mi interpretación de este código me dice lo siguiente.
Instante 0, leo Sw1 y Sw2, ok
Llego al if y pregunto sobre sus estados no importa cuales porque para el caso da lo mismo.
Supongomos son verdaderos los que copie y pegué o sea

EdoSW1 ==1 && EdoSW2 ==0
Luego del primer if viene un delay de 100mseg. Hasta ahi BIEN.
Pero luego vuelves a preguntar
si EdoSW1 ==1 && EdoSW2 ==0 y si en elprimero caso lo fueron en el segundo tambien.
No importa que pase, siempre lo serán. Porque? Porque no volvieron a leerse, son los mismos 100mseg atrás.
Entonces lo que está mal es el código del debounce.
Y por lo tanto, trabajando con contactores y con relés, con rebotes por doquier, no sabes nunca que está tomando el arduino como estado de esos u otros switches.
Ahora te sugiero una rutina debounce que mejore la situación pero sin delay.
La busco y la pego acá.
La llamada a loop es por que en cierto momento que conecte el monitor serial al arduino, no me devolvio nada, no se movía ni caminaba el programa, luego entonces pensé que quizás, algun voltaje parasito hubiera podido montarse en el cable que no deberia llevar voltaje, dando como resultado

EdoSW1 = 1, EdoSW2=1 , para lo cual no había ninguna opcion en el codigo, pudiendo ser que esto fuera lo que lo "trabara"... no tengo experiencia en caso que una cosa asi hubiera pasado, es por eso que pensé en que si no se cumplian con ninguno de los 3 estados definidos, se regresara al loop para hacer un nuevo intento.

//

Ahora bien, que me haces ver las cosas tienes toda la razón, esa doble "verificación" no es nada mas que repetir un error, ya que la medida de los pines se hace una vez y se asigna a la variable, paso seguido se compara por la rutina logica. Como bien dices, el detalle esta entonces en la lectura que se hace de los pines, ya que efectivamente... El estado del termostato se lee como sigue;

Un termostato digital a 220V, una vez que alcanza la temperatura de inicio"caliente"... cierra su contacto auxiliar, alimentando una bobina de un contactor. Entre dos de los NO del contactor estan respectivamente; Un VCC que viene de la fuente, y el cable con Pull Down a tierra que lleva la señal al pin  que respectivamente lee el estado del termostato.


surbyte

#14
Nov 24, 2014, 03:13 pm Last Edit: Nov 24, 2014, 03:16 pm by surbyte
Bien, entonces dentro de los posibles errores el primero es que no tienes debounce. Asi que esperame un tiempo y te posteo una modificación con esa parte resuelta.
Luego veré que le ocurre al resto.
Eso de llamar al loop NOOOO DE NINGUNA MANERA. No se que implicancias puede tener pero no es para nada bueno.
Si tienes dudas del funcionamiento o del comportamiento y maneja tareas críticas que impliquen riesgo de algún tipo, lo que se hace es activar el watchdog del microcontrolador.

Yo uso una librería para manejar los switches que hace el debounce y algunas otras cosas mas.
Se llama Switch y mas abajo agregaré los archivos para que la agregues a tu libraries en el directorio Arduino de tu PC.


Go Up