Autor Tema: Apagar un led despuès de varias horas  (Leído 15862 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado AcoranTf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1099
Re:Apagar un led despuès de varias horas
« Respuesta #45 en: 06 de Enero de 2017, 23:11:07 »
inclusive los transistores funcionan mal funcionan  como si estuvieran en corto o con fugas

Retovil lo que comentas no tiene mucho sentido. Es cierto que el Proteus tiene algunos "bugs", pero no hasta el punto de no funcionar correctamente varios componentes tan comunes como reles y transistores de uso generico.
Podria ser un problema de la instalacion de Proteus en tu caso particular.
Hay una forma facil de salir de dudas, adjunta el proyecto de Proteus que te da los problemas y tratare de hacer un hueco y probarlo en el mio. No olvides el programa del PIC, para poder simular.

Saludos.

Desconectado retovil

  • PIC10
  • *
  • Mensajes: 43
Re:Apagar un led despuès de varias horas
« Respuesta #46 en: 08 de Enero de 2017, 18:59:23 »
La verdad es que tenes razon , me puse a mirar con mas detalle y hay elementos de dibujo y otros de simulacion . probe con otro rele y funciona bien asi mismo probe parte de la electronica digital y funciona .
Lo que no puedo hacer funcionar es que dos transistores bc548 funcionen como oscilador.
en configuracion emisior comun .Pero la verdad es que no se como ahora funcionan antes daban un corto .En el caso de que quiero conectar en el pin MCLR de 16f628a un transistor
para resetear no me lo permite . A lo mejor si me explicas porque no puedo meter un reseteador simplemente para probar ,no lo permite queda todo trabado .

Desconectado retovil

  • PIC10
  • *
  • Mensajes: 43
Re:Apagar un led despuès de varias horas
« Respuesta #47 en: 11 de Enero de 2017, 00:59:56 »
No se si funcionara, deberias probarlo.

Código: C
  1. #include <16f628A.h>
  2. #Fuses xt,nowdt,NOPROTECT, PUT, NOLVP,NOMCLR
  3. #use delay(clock=4000000)
  4. #use fast_io(b)
  5.  
  6. volatile int1    activo;
  7. volatile int16   contador=0;
  8. int8    indice;
  9. int16   tiempo[4] = {1000,2000,3000,4000};
  10. volatile int16   limite;
  11.  
  12. #int_timer1
  13. void TIMER1_isr(void)
  14. {
  15.     set_timer1(192);
  16.     if(activo)
  17.     {
  18.         contador++;
  19.     }
  20.  
  21.     if(contador>=limite)
  22.     {
  23.         output_bit(PIN_B7,0);                   // Apago Rele
  24.         contador=0;
  25.         activo= false;
  26.     }
  27. }
  28.  
  29.  
  30. void main()
  31. {
  32.    
  33.     int8 i;
  34.    
  35.     // Inicializacion de variables
  36.     indice = 0;
  37.     limite = tiempo[0];
  38.     activo = true;
  39.    
  40.     // Configuracion de los modulos
  41.    
  42.     set_tris_b(0x0F);                               // RB0 a RB3 entradas, RB4 a RB7 salidas
  43.     output_bit(PIN_B7,1);                           //Inicia con el rele encendido
  44.     setup_timer_1(RTCC_INTERNAL| RTCC_DIV_4);
  45.     set_timer1(192);
  46.     enable_interrupts(INT_TIMER1);
  47.     enable_interrupts(GLOBAL);
  48.  
  49.     while(1)
  50.     {
  51.         /*
  52.          * Boton de reset
  53.          */
  54.         if(input(PIN_B0))                       // Boton de reset
  55.         {
  56.             contador = 0;                           // Reinicio el tiempo
  57.             output_bit(PIN_B7,1);                   // Activo rele
  58.             activo = true;
  59.         }
  60.        
  61.         /*
  62.          * Boton de tiempo
  63.          */
  64.        
  65.         if(input(PIN_B1))                       // Boton seleccion de tiempo
  66.         {
  67.             while(input(PIN_B1));
  68.             indice++;
  69.             limite = tiempo[indice];
  70.             if(indice>=sizeof(tiempo))
  71.             {
  72.                 indice = 0;
  73.             }
  74.             for(i=0;i<=indice;i++)
  75.             {
  76.                 output_bit(PIN_B6,0);
  77.                 delay_ms(200);
  78.                 output_bit(PIN_B6,1);
  79.                 delay_ms(200);
  80.             }
  81.         }
  82.        
  83.         /*
  84.          * Led indicador
  85.          */
  86.         output_bit(PIN_B6,activo);
  87.     }
  88. }
Funciona muy bien !  :)
Cuando tengas tiempo me lo podes explicar



Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Apagar un led despuès de varias horas
« Respuesta #48 en: 11 de Enero de 2017, 02:57:51 »
Simple, divido el problema en 2 partes.

- Lo que necesito que sea rapido/constante en el tiempo y que no sea bloqueado por nada lo hago en la interrupcion.
- Lo que no necesita velocidad lo hago en el while.

¿Que necesito que se haga de forma constante?

Solamente necesito el timer y contar la cantidad de veces que requiere entrar, nada mas. Por eso esta el codigo del if(contador>= limite), limite en este caso es el punto donde se va a apagar por lo cual necesito cambiar ese valor para cambiar los tiempos ( cantidad de veces que entra a la interrupcion ).
Necesito ademas que cuando llegue al punto que corte deje de contar, por lo tanto uso esa variable de 1 solo bit (activo), para decir que deje de contar o no. Si observas cuando apago la salida tambien deshabilito este bit, de esa forma deja de contar.. Me aseguro de esa forma.
Esto en la interrupcion se va a ejecutar si o si por mas que ponga cualquier cosa en el while

Ahora vamos al while... Es decir las entradas manejadas por la persona o leds, donde no requiero requerimientos de velocidad o responder de manera instantanea.
En el while tenemos 3 secciones definidas con comentarios cada una independiente de la otra.

El primero es el boton de reset, Este boton lo que hace es poner el tiempo transcurrido ( contador ) a 0, activar el rele (por si ya habia terminado el tiempo), y permitir que en la interrupcion se siga aumentando contador (al poner activo a 1). Es decir que el TIEMPO CORRA!, se puede observar que mientras este presionado este boton se va a seguir reseteando a 0 a contador, ya que simplemente no me molesta si tarda 1s mas la persona presionando, si quisiera evitar esto simplemente le pongo un while.

Otra seccion del while es el boton de seleccion de tiempo, Tiene 2 partes, la seleccion de tiempo y la muestra en el led de la velocidad seleccionada.

- La primera parte:
Como pediste tenemos varios tiempos, como con este boton lo que hago es incrementar un numero ( indice ) yo no quiero que incremente varias veces por eso mismo esta el while luego del if, lo cual bloquea el programa hasta que la persona suelte y asi cuenta 1 solo. ¿Pero bloquea algo importante? Me bloquea unicamente la funcion del reset, pero resulta dificil que la persona tenga presionado el boton de velocidad y luego presione el de reset, si lo hace simplemente no logra nada.
En fin la "tecnica" aca es que con cada presion del boton aumente indice, indice me va a decir que valor del array uso, el if(indice>=sizeof(tiempo)) es una proteccion para que si indice es 3 que apunta al ultimo valor y se presiona de nuevo, pase a 0 y no 5 que seria un valor que no existe.

- La segunda
Finalmente para no usar otro led, uso el mismo led que indica que esta corriendo, y le hago hacer pulsos segun la velocidad elegida.

Al final de todo del while llegamos a una ultima instruccion, si recordas usabamos el led que indica que la salida esta activa para indicar la velocidad, que pasaria si presionamos el boton y mantenemos, corta la salida, soltamos, cambia de velocidad y muestra en el led, la ultima instruccion es poner el led a 1. Pero ya esta cortado, no puedo dejarlo encendido al led, por eso actualizo contantemente el led segun si esta la salida activa o no.

------------------------------------------

Estoy mas que seguro que posiblemente la parte de mostrar la velocidad con el led este mal, ya que mi idea era contar los pulsos en que esta encendido y no los que esta apagado.

Y tambien otro "error" que podria llegar a aparecer es que mientras se mantenga presionado un boton y se termine el tiempo, el led no pase a apagado hasta que no se suelte el boton.
Esto se podria solucionar, no creo que sea tan problematico.

Otra cosa mas, debido a que son de 16 bits las variables existe una minuscula posibilidad de que ocurra un error si es que la interrupcion del timer ocurre cuando se presiona el boton de tiempo, se puede salvar simplemente deshabilitando la interrupcion ANTES de asignar el valor a limite y luego habilitarla. O directamente eliminar la variable limite y usar indice solo, teniendo en cuenta que primero se debera calcular sobre otra variable temporal antes de asignarsela a indice. y en la interrupcion usar tiempo[indice], ya que esto es una variable de 8 bits, no necesita actualizar 2 registros sino uno solo, pero hay que posee precauciones de cuando se suma y quede en 4 que es un indice que no posee el array.

------------------------------------------

O por ahi resumentes de que son cada variables:

activo - es un bit o flag que me indica si debo o no seguir contando las entradas a la interrupcion.
contador - es la variable donde voy contando cuantes veces entro a la interrupcion.
indice - como su nombre lo dice me sirve para apuntar a cada elemento del array de tiempos es decir tiempo[2] seria 3000.
tiempo - es un array con todas los tiempos, o mejor dicho con la cantidad de entradas a la interrupcion, si quisiera agregar alguno simplemente pongo una coma mas y el numero.
limite - El tiempo seleccionado lo guardo aca, y lo comparo con la cantidad de veces que entro a la interrupcion.

----------------------------------------

¿Se puede complicar aun mas?

Si, se podria complicar en el punto de que no asigne el tiempo hasta no pasado cierta cantidad de segundos... Esto es por si por ejemplo tenes el corte de 10min, 20min, 30min , tenias seleccionado 20min, iban 15min y querias pasar a 30min, y de golpe porque ocurrio presionaste 2 veces y lo pasaste a 10min, esto automaticamente cortaria y la unica forma que te queda es activarla de nuevo por otros 10min.
Con esta complicacion en el programa podrias tener unos 30 segundos supongamos para seguir presionando y volver a seleccionar los 30min sin que se corte. No es simple de aplicar pero es posible.

Tampoco definimos una parada de emergencia. Que ocurriria si quisieramos pararlo ?, podriamos usar el boton de reset, el cual si esta presionado 5 segundos o mas proceda a detener todo. Y si es menos apagar, o viceversa en caso de se que quiera tener proteccion al activarlo de nuevo.
Tambien podrias hacer que si esta marchando, corte, y si esta parado resetee el tiempo sin esperar segundos.
« Última modificación: 11 de Enero de 2017, 03:15:36 por KILLERJC »

Desconectado retovil

  • PIC10
  • *
  • Mensajes: 43
Re:Apagar un led despuès de varias horas
« Respuesta #49 en: 16 de Enero de 2017, 11:18:43 »
Exelente , debo decir que el parpadeo del led por RB6 ,funciona perfectamene ,un relojito .
Pero trato de saber como funciona este codigo que hace parpadear varias veces depende de
la seleccion de tiempo y no puedo .
Quise poner un display de 7 segmentos ,con un arreglo y acoplarlo de alguna forma para que esos parpadeos se conviertan en un 1 ,2 ,3 o 4 . Cosa que quede   mas vistoso y manejable .No pude hacerlo pues salia cualquier cosa menos un numero .
Como funciona este codigo? como hace parpadear al led uno ,dos o tres veces ? :)
Código: [Seleccionar]
if(input(PIN_B1))                       // Boton seleccion de tiempo
        {
            while(input(PIN_B1));
            indice++;
            limite = tiempo[indice];
            if(indice>=sizeof(tiempo))
            {
                indice = 0;
            }
            for(i=0;i<=indice;i++)
            {
                output_bit(PIN_B6,0);
                delay_ms(200);
                output_bit(PIN_B6,1);
                delay_ms(200);
            }

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Apagar un led despuès de varias horas
« Respuesta #50 en: 16 de Enero de 2017, 14:53:50 »
Bien, el codigo que pase tiene algunos errores importantes luego te lo doy corregido, pero miremos este codigo que me preguntas
.. separemos el codigo..

Código: C
  1. if(input(PIN_B1))                       // Boton seleccion de tiempo
  2.         {
  3.             while(input(PIN_B1));

Eso simplemente es lo del boton, nada mas, pide que este presionado y luego que se suelte para poder continuar. Esta parte no tienen nada que ver con el parpadeo

Código: C
  1. indice++;
  2.             limite = tiempo[indice];

Esta parte del codigo es donde procedo a cambiar la velocidad, aumento indice, y con el nuevo indice encuentro el tiempo que me dice el array, el indice simplemente es un numero que me dice que posicion del array tomar, 0,1,2,3, etc. Esto no tiene nada que ver con el parpadeo.

Código: C
  1. if(indice>=sizeof(tiempo))
  2.             {
  3.                 indice = 0;
  4.             }

A pesar que este es un error donde esta ubicado pero funciona correctamente, porque deberia ir entre medio de las 2 instrucciones anteriores, en si este codigo te dice que si por algun motivo al incrementar indice pasamos la cantidad de datos que tiene el array tiempo[] paso a 0, es decir los valores en el ejemplo son de 0 a 3 ( 4 elementos ) al llegar indice a 4, deberia pasarse a 0. Con el mayor o igual directamente me aseguro que sea cualquier valor incorrecto ( 100, 124, etc ) pase a 0. Y no me quedo con simplemente == 4. Esto no tiene nada que ver con el parpadeo.

Por ultimo la parte del parpadeo.

Código: C
  1. for(i=0;i<=indice;i++)
  2.             {
  3.                 output_bit(PIN_B6,0);
  4.                 delay_ms(200);
  5.                 output_bit(PIN_B6,1);
  6.                 delay_ms(200);
  7.             }

Un simple for... desde i = 0, hasta que la condicion i <= indice sea falsa. Por que menor o igual y no directamente menor solo ? Porque sino al ser indice = i = 0, no ejecutaria el ciclo for 1 vez. Tambien podria haber realizado una condicion como esta i < (indice +1), cuestion de gustos.

Entonces supongamos que indice era 2. (recorda que el primer elemento es indice 0, por lo tanto seria el 3er elemento)
Comienza el for con i = 0, la condicion es true entonces realiza el codigo
Termina la vuelta e i pasa a valer 1, sigue siendo true y realiza el codigo
Otra vuelta i = 2, sigue siendo true y realiza el codigo, aca ya fueron 3 veces que parpadeo el led, ( los del 0, 1 y 2 )
proxima vuelta i = 3, por lo que ya la condicion pasa a ser false y sale del for.

En todo esto el for se repetio (indice + 1) veces o mejor dicho el numero del elemento elegido si es que empezamos a contar desde 1 y no 0.

-------------------------------

Codigo con unas cuantas cosas corregidas.

Código: C
  1. #include <16f628A.h>
  2. #Fuses xt,nowdt,NOPROTECT, PUT, NOLVP,NOMCLR
  3. #use delay(clock=4000000)
  4. #use fast_io(b)
  5.  
  6. volatile int1    activo;
  7. volatile int16   contador=0;
  8. volatile int8    indice;
  9. int16   tiempo[4] = {1000,2000,3000,4000};
  10. int8   temp;
  11.  
  12. #int_timer1
  13. void TIMER1_isr(void)
  14. {
  15.     set_timer1(192);
  16.     if(activo)
  17.     {
  18.         contador++;
  19.     }
  20.  
  21.     if(contador>=tiempo[indice])
  22.     {
  23.         output_bit(PIN_B7,0);                   // Apago Rele
  24.         contador=0;
  25.         activo= false;
  26.     }
  27. }
  28.  
  29.  
  30. void main(void)
  31. {
  32.    
  33.     int8 i;
  34.    
  35.     // Inicializacion de variables
  36.     indice = 0;
  37.     activo = true;
  38.    
  39.     // Configuracion de los modulos
  40.    
  41.     set_tris_b(0x0F);                               // RB0 a RB3 entradas, RB4 a RB7 salidas
  42.     output_bit(PIN_B7,1);                           //Inicia con el rele encendido
  43.     setup_timer_1(RTCC_INTERNAL| RTCC_DIV_4);
  44.     set_timer1(192);
  45.     enable_interrupts(INT_TIMER1);
  46.     enable_interrupts(GLOBAL);
  47.  
  48.     while(1)
  49.     {
  50.         /*
  51.          * Boton de reset
  52.          */
  53.         if(input(PIN_B0))                       // Boton de reset
  54.         {
  55.             contador = 0;                           // Reinicio el tiempo
  56.             output_bit(PIN_B7,1);                   // Activo rele
  57.             activo = true;
  58.         }
  59.        
  60.         /*
  61.          * Boton de tiempo
  62.          */
  63.        
  64.         if(input(PIN_B1))                       // Boton seleccion de tiempo
  65.         {
  66.             while(input(PIN_B1))
  67.             {
  68.                 output_bit(PIN_B6,activo);
  69.             }
  70.  
  71.             temp = indice + 1;
  72.             if(temp>=sizeof(tiempo))
  73.             {
  74.                 indice = 0;
  75.             }
  76.             else
  77.             {
  78.                 indice++;
  79.             }
  80.  
  81.             for(i=0;i<=indice;i++)
  82.             {
  83.                 output_bit(PIN_B6,0);
  84.                 delay_ms(200);
  85.                 output_bit(PIN_B6,1);
  86.                 delay_ms(200);
  87.             }
  88.         }
  89.  
  90.     /*
  91.      * Led indicador
  92.      */
  93.     output_bit(PIN_B6,activo);        
  94.     }
  95. }

En este codigo soluciono los anteriores errores.

- No asigno "limite" en el while, solo indice que es de 8 bits, Tambien debo usar una variable temporal para un calculo, para saber si se va a exceder o no del valor correcto, de esa forma nunca indice tendria un valor fuera de rango.

- Como recordas mientras se mantenga presionado el boton es posible que no se actualize el led, si es que termina, entonces para eso la solucion mas simple fue ponerlo dentro del while del boton, podria haberlo puesto en el timer tambien, ya que este ultimo siempre se esta ejecutando, pero este interferiria en el for de muestra de velocidad. Por eso no lo hice alli.
« Última modificación: 16 de Enero de 2017, 14:59:53 por KILLERJC »

Desconectado retovil

  • PIC10
  • *
  • Mensajes: 43
Re:Apagar un led despuès de varias horas
« Respuesta #51 en: 28 de Febrero de 2017, 01:42:21 »
hola KillerJC ,me aucente un poco . Debo agradecerte por la explicaciòn circuito parpadeo y de todo el programa ,debo decirte que el reset no funciono pero si lo hiciste aproposito ya lo solucione .
Para que se le pone a las variables la expresion volatile
?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Apagar un led despuès de varias horas
« Respuesta #52 en: 28 de Febrero de 2017, 08:28:51 »
hola KillerJC ,me aucente un poco . Debo agradecerte por la explicaciòn circuito parpadeo y de todo el programa ,debo decirte que el reset no funciono pero si lo hiciste aproposito ya lo solucione .
Para que se le pone a las variables la expresion volatile
?

No fue mi intencion que no funcionara, asi que fue un error.

El volatile usalo cuando tengas una variable que se acceda en la interrupcion y en tu programa principal. Esto hace que el compilador omita la optimizacion de esa variable. Ya que de no ser asi es posible que  el compilador al detectar que nada lo cambia a la variable (tomando la interrupcion y el programa como 2 funciones distintas que nunca se llaman) la elimine y comienzen los problemas. Para eso te aseguras y le pones volatile, pidiendole que lea si o si el registro que contiene la variable.

Si no usa optimizaciones, el volatile no hace nada es lo mismo que no estuviera, pero con optimizaciones es necesario.