Tratando con el NE555

Hola:

Usando un transformador de 12Vdc, alimento un NE555 de 2 mintos monoestable. Al pulsar el botón que está conectado al pin 2, los ventiladores de 12V se quedan activos.

La idea es con un PIC16F84A controlar el pin 2 del 555.

Al encender el aparato, Debe estar activado los ventiladores de 12V.
Cuando apague el aparato, el PIC16F84A da el pulso al 555 para que siga 2 min. los ventiladores encendidos.
Puedo encender el aparato estando los ventiladores desactivados.
Si apago el aparato, los ventiladores siguen activos porque no ha pasado 2 min y se me ocurre volver a encender el aparato, que siga los ventiladores activos.


¿Se puede hacer?

Estoy haciendo pruebas tontas entre PIC y 555, se que con el PIC hago eso sin el 555.
 
ya sabes lo que hace el pic.
y a lo mucho tira 1 o cero.

asi que te recomiendo que te pongas a jugar con el 555 solo , a mi siempre me disgusto, pero ahora lo estoy usando a veces, ya que tiene pocas patas y lo puedo "ensartar " en placas que ya tengo como si fuese un transistor, , claro , puego de haberlo "asqueroseado" un poco doblandole algunas patas.

tiene sus aplicaciones utiles .
 
:) Te disgustó el 555 dices, ;).

El motivo que quiero hacer este tipo de experimentos es que el PIC16F84A digamos que es un módulo a parte y el 555 es otro módulo a parte. Los dos módulos pueden interactuar entre si, PIC y 555.

Es como un PC de sobremesa y un portatil, el PC de sobremesa tiene una placa madre, sus módulos a parte puedes ser la tarjeta gráfica, tarjeta de sonido, Memoria RAM, etc... En un portatil suele venir casi todo en la misma placa base (depende del portatil, también hay modular). Este es un ejemplo para que se entienda.

Un saludo.
 
cuando empece use el 555 y me dio algun problema, pase enseguida a compuertas que son mas modulares y un ci tiene varias y segui asi con modulos logicos.
nunca tuve lso problemas fantasmas que suelo leer aca con los CD4xxx , bueno, con el 555 si le agarras la mano tampoco .
ademas, el 555 atrae a "quiero armarlo pero no entenderlo" y eso fastidia mas.

de nuevo, como decis , si son modulos separados, algo totalmente factible , pues que te tenes que poner a jugar con el 555 , el otro ya sabes que hace.

como dije el 555 te puede servir para hacer modulitos simples y economicos, que quizas gobiernes con el pic.

es un inversor.
es un FF
es un comparador.


y con eso ......lo que tu imaginacion quiera.

igual, no pierdas mas que una tarde con el , por que hay una extensa gama de cis por 0,3 u$ para hacer modulos economicos y muy versatiles, como para andar revoloteando con el 555 ......es una perdida de aleteo en la vida.
hacete una lista de lso cis que te parecen interesantes, llama o manda unos mails a proveedores y cruza info a ver cuales son faciles de conseguir, y tene esa lista en mente .
que sera muy larga.
pero el 555 solo ..............no.,,,,seria como ponerle un ancla a Buzz Lightyear en vez de alas.
 
Última edición:
El 555 lo tengo montado a monoestable a 2 minutos de duración. Los ventiladores siempre están activados, cuando falta la alimentación principal, el PIC lo detecta y debe mandar una señal al 555 para activar los 2 minutos con los ventiladores activados mientras el aparato esté apagado, claro que usa una fuente alimentación externa al aparato para alimetar los ventiladores, el PIC y el 555.

¿Por qué no hago todo en un PIC16F84A?

Porque ya incluye todos los pines, tiene sensor de temperatura y LCD a parte de tener la memoria lleba.

¿Por qué no uso otro PIC?

Porque no tengo más y este me conformo. En caso de usar un PIC16F886 tendría que cambiar el ASM que no es tarea fácil.

¿Tengo otra posibilidad en vez de usar el 555?

Sí, también tengo en mente usar un PIC12F508 que haga de temporizador o 555. Claro que este me cuesta mucho entenderlo para programarlo, con el 16F84A su código mediente retardo es este:

Mediante retardos:
Código:
; El LED conectado a la línea 0 del puerto de salida se enciende durante 400 ms y se
; apaga durante 300 ms. Utiliza las subrutinas de la librería RETARDOS.INC.
;
; ZONA DE DATOS *********************************************************************

    LIST        P=16F84A
    INCLUDE        <P16F84A.INC>
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

    CBLOCK  0x0C
    ENDC
    
#DEFINE  LED    PORTB,0

; ZONA DE CÓDIGOS *******************************************************************

    ORG    0
Inicio
    bsf        STATUS,RP0                ; Acceso al Banco 1.
    bcf        LED                        ; Línea del LED configurada como salida.
    bcf        STATUS,RP0                ; Acceso al Banco 0.
Principal
    bsf        LED                        ; Enciende el LED
    call    Retardo_200ms            ; durante la suma de este tiempo.
    call    Retardo_200ms
    bcf        LED                        ; Lo apaga durante la suma de los siguientes
    call    Retardo_200ms            ; retardos.
    call    Retardo_100ms
    goto     Principal

    INCLUDE  <RETARDOS.INC>            ; Librería con subrutinas de retardo.
    END
En C he encontrado este código.

Código:
#include<16F84A.h>
#fuses XT,NOPROTECT,NOWDT,PUT
#use delay(clock=4000000)

int1 Temporizador=0;                            // Dada la escaces de  una variable booleana, usaremos un int1 que es el equivalente
int1 dSegundo=0;                                 // El Booleano dSegundo  indica 0 cada decima de segundo y el booleano Temporizador si es uno  activa el temporizador
int16 Contador=0;                               // Dado que 2 min = 120s  = 120s * 0.1s= 1200 conteos, usaremos una variable de 16bits


#INT_TIMER0
void timer0()
{
   set_timer0(60);                              // Se carga el valor inicial del timer0 para la siguiente interrupcion
   dSegundo++;                                  // Se incrementa el "Booleano" Segundo si era 0 ahora es 1, si era 1 ahora es 0
   if(!dSegundo) Contador++;                    // Si Segundo == 0, entonces Contador se incrementa.
   if(Contador == 1200)                         // Si ya pasaron 2  minutos se apaga el Temporizador y se desabilitan las interrupciones
   {
      Temporizador=0;
      disable_interrupts(GLOBAL);
   }
   output_bit(PIN_B0,Temporizador);             // Se refresca la salida del Relevador
}

void main()
{
  output_low(PIN_B0);                           // Estado bajo del pin B0 indica que el relé está desactivado.
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);    // Se configura el Timer0 como Temporizador y el divisor a 1:256
                                                // Dado que el Tiempo maximo del Timer0 con divisor de 1:256 es:
                                                // t=4/Fosc(Prescaler*(Dimension_Timer - Tiempo cargado))
                                                // t=4/4000000(256*(255-0))=0.06528s
                                                // Por lo que nos  conviene manejarlo a 0.05s, asi cada 2 interrupciones hace un segundo
                                                // Un valor muy cercano a 0.05
  enable_interrupts(GLOBAL);                // Se habilitan las interrupciones GLOBALES
  
  while(TRUE)
  {
    if(input(PIN_A4))                           // Si se presiona el PIN_A4
    {
      if(!Temporizador)                         // Si el temporizador esta desabilitado
      {
         output_high(PIN_B0);                   // Se habilita el Relevador
         set_timer0(60);                        // Se carga en el registro del Timer0 un 60 decimal dado que:
                                                // t=4/4000000(256*(255-60))=0.04992
                                                // Un valor muy cercano a 0.05
         enable_interrupts(INT_TIMER0);         // Se habilita la interrupcion del Timer0
         Temporizador=1;                        // Se habilita el Temporizador
         Contador=0;                            // Se restablece a 0 el indicador de decimas de segundo y el contador
         dSegundo=0;
      }
      else                                      // Si el temporizador esta habilitado
      {
         output_low(PIN_B0);                    // Se desabilita el Relevador
         Temporizador=0;                        // Se desabilita el temporizador
         disable_interrupts(INT_TIMER0);        // Se desabilita la interrupcion del Timer0
      }
      while(input(PIN_A4));                     // Se espera hasta que se deje de presionar el boton del PIN_A4
    }
  }
}

Ya se sabe que los retardos el PIC queda exclavo y no interrumpe su trabajo hasta acabar. Este código de arriba está bien para pasarlo al 12F508 si me interesaría, mejor usar un TIMER.

En cuanto al 555. Como módulo es posible hacerlo independiente del PIC de esta manera.

El 555 tiene un tiempo monoestable de 2 minutos, en este caso se usará astable. Para conectarlo como módulo al PIC se aconseja astable del 50% cicle duty, por ejemplo, 1 segundo en nivel alto a 5V y lo mismo para 0V, así durante un tiempo. Mientre el 555 a modo astable soltando señal cuadrada del pin 3.

555_astable.gif


La ventaja del PIC16F84A es que tiene un contador que puede contar las señales cuadradas que te puede dar en el pin 3 del famoso NE555 como astable. Ya empieza a contar el tiempo el PIC por cada pulso. Parece que el NE555 debe seguir dando señales hasta que el contador del PIC llegue a cuenta atrás a tope para saltar un condición.

120 pulsos son 2 minutos si el 555 tiene el T1 y T2 a cada segundo. Cuando el contador llegue a 0 a la salida del PIC se desactiva los ventiladores.

¿Se entiende el consepto de algo modular?

El aprender no es perder el tiempo, aunque te lo parezca ahora, en el futuro podrás tener otras ideas.
 
Por mas que me estrujo la cabeza no se para qué quieres el 555 en tu montaje si se soluciona con unas pocas líneas de código.
Si es por entretenerte poniendo hardware redundante vale.
 
¿Sabes sacar en ASM o C 2 ó 10 minutos con el Timer?

¿Y que tenga interrupción? Es decir, al pulsar un pulsador, si el temporizador está contado, se resetee a 0 otra vez, se ejecutará el tiempo cuando haya un disparo.

Todo esto para el 12F508 que el encapsulado es el mismo. La ventaja del 12F508 al 555 es ese, que no necesita tantos componentes externos como el 555.
 
Última edición:
Meta, veo que estás convencido de utilizar el 555, así que te doy una sugerencia.

Transistor, resistencias, un diodo, capacitor, y nada mas.

Si te parece interesante algo así de simple, esperame un momento y te hago un esquema.

La idea sería que cuando falte la electricidad, con el transistor detecte la pérdida de energía, y haga que el 555 empiece a contar..

Saludos

PD: Ahora hago un esquema...



Acá el esquema, los valores pueden ser cambiados para mejorar el desempeño...

idea555.JPG

Espero que te sirva, cualquier cosa, avisas...
 
Última edición:
¿Sabes sacar en ASM o C 2 ó 10 minutos con el Timer?

¿Y que tenga interrupción? Es decir, al pulsar un pulsador, si el temporizador está contado, se resetee a 0 otra vez, se ejecutará el tiempo cuando haya un disparo.

Todo esto para el 12F508 que el encapsulado es el mismo. La ventaja del 12F508 al 555 es ese, que no necesita tantos componentes externos como el 555.

Si que se hacer dos minutos por interrupciones, y dos años también. Con un pic no porque nunca los he usado, con el resto de microprocesadores/microcontroladores que he usado si. (6502, z80, 8085, 8052, hc11) Pero para el caso viene a ser lo mismo:

Se hace una rutina de interrupción cíclica con un timer, la duración la que te venga bien ya que el timer con suerte dará para 1/10 s o así. La rutina de interrupción rearma el timer e incrementa o decrementa según interese un contador de los bits que necesites, cuando llegue a cero o a la cuenta que quieras haces lo que toca; encender, apagar o lo que sea. Eso son unas 10 o 20 instrucciones todo lo mas y seguro que es mucho mas precisa y cómoda que un 555.
Usar un monoestable analógico para 120s es una barbaridad a no ser que sea "mas o menos unos dos minutos o por ahí" si necesitas 120" exactos te vas a tirar dos horas ajustando el potenciometro para que te salga regular; lo pones a un valor, esperas dos minutos, te has pasado, le quitas, esperas otros dos minutos, le falta, tocas otra vez, esperas otros dos minutos... práctico lo que se dice práctico no es. Luego si el condensador es electrolítico se secará con los años, el potenciometro se ensuciará y la temporización y el ajuste se van al carajo.
 
Última edición:
Hola gente:

Estoy de acuerdo del 555 te puedes pegar mucho tiempo para 120 seg. (2 min.). Hablo también del 555 porque el 12F508 lo veo complicado con int, jejeeje, si lo puedo hacer mediante retardos, claro que queda esclavo.

Sin usar el NE555 y centrándome en dos PIC. Sí, dos PIC, un PIC16F84A de control de temperatura con LCD incluido y pulsadores de configuración, lo quiero como módulo a parte. Otro PIC12F508 para el tema de temporización a 2 minutos, también hace funciones de otras cosas como, detecta la falta de alimentación en un pin y se activa el temporizador. Al volver la tensión con la INT interrupción, el temporizador vuelve a 0 sin contar, si se va la alimetación otra vez vuelve a temporizar hasta que se apague los ventiladores en dos minutos y se queda ahí.

Luego subo un esquema.

Gracias por el apoyo e ideas.
 
No te entiendo

¿Vas a poner un pic con solo 20 instrucciones de programa?¿No será mejor ponérselas al "master"?
Con el mismo pin que activas al módulo 555/pic-esclavo activas directamente el ahora "módulo tonto" que solo lleva un transistor y un relé (por decir algo)

Pseudocódigo:

-Al arrancar el pic configuras el timer y la interrupción, pero no lo arrancas

En el bucle principal, cuando se de la condición arrancas el timer. Ahí decides que pasa si ya está arrancado, si se para, si vuelve a empezar la cuenta o lo que sea.

A cada interrupción descuentas un valor prefijado y si no es cero rearmas el timer (dependiendo del timer puede que tenga rearme automático) y vuelves
Si si que es cero, activas la salida y decides si puede volver a pasar, si se bloquea o lo que sea.

Eso te da mucha mas flexibilidad ya que pueden ser dos minutos, cero minutos o lo que quieras reprogramando/configurando un solo pic y no dos diferentes, ocupa menos y es mas barato.
 
Meta, si no te interesó el esquema que puse mas arriba, te doy una idea en C.

Código:
...
[COLOR="DarkSlateBlue"]int[/COLOR] tiempo = [COLOR="DarkOrange"]20[/COLOR]; [COLOR="SeaGreen"]// cantidad de segundos[/COLOR]
[COLOR="darkslateblue"]int[/COLOR] cuenta;
[B][COLOR="Blue"]for[/COLOR]([/B]cuenta = [COLOR="darkorange"]0[/COLOR]; cuenta < tiempo; cuenta++[B])[/B]{
	delay_ms([COLOR="darkorange"]1000[/COLOR]); [COLOR="SeaGreen"]// Pausa de 1 segundo[/COLOR]
	[B][COLOR="blue"]if[/COLOR]([/B]condicion[B])[/B]{ [COLOR="SeaGreen"]// Condición, por ejemplo; Se pulsó un botón[/COLOR]
		hagoEsto = true;
		[B][COLOR="blue"]continue[/COLOR][/B];
	}
}
...

Espero que te sirva...

PD: Esto no está probado en lo absoluto...
 
Opinión personal; temporizadores a base de bucles vacíos solo para unos pocos (muy pocos) ms. Así tienes un sistema colgado dos minutos.
 
Scooter, podrías decir el por qué no bucles vacíos (aunque el código que puse, no está vacío)...

Pregunto, ya que tengo muy poca práctica y nada de teoría con los micros en general...:unsure:
 
Pues porque es absurdo comprar y pagar un micro de unos cuantos MIPS y ponerlo a dormir la siesta 20'. Durante ese tiempo no funcionará nada, no se referesca el display etc.
Siempre hay "cosas que hacer" en un sistema, ver si el usuario pulsa botones, actualizar la pantalla y mil cosas mas. Si se ponen condiciones dentro del bucle entonces será muy inexacto ya que según lo que pase durará mas o menos.

En mi modesta opinión, para casi cualquier equipo basado en un micro lo mejor es montar un "reloj del sistema" a base de un timer que haga 10 o 100 interrupciones por segundo (o un tiempo conocido). En la rutina de interrupción por defecto solo se rearma el timer y se vuelve (eso supone una pérdida de CPU mínima).
Ahora, con un solo timer puedes llevar todos los tiempos que te hagan falta con un error de 1 periodo. Cada vez que necesites temporizar algo, en el bucle principal activas un flag si se cumple la condición y cargas un registro con un valor a descontar.

La rutina de interrupción irá descontando ese/esos registro/s y cuando llegue a cero avisa o actúa. Con muy pocas instrucciones y muy poco tiempo de CPU se pueden controlar bastantes temporizaciones con una sola rutina de interrupción y un solo timer. Todo el resto de tiempo de CPU (la inmensa mayoría) lo puedes aprovechar en cosas útiles.
 
Eso pensé, claro que debe ser complejo en ASM. Al menos el esquema está hecho de un libro. lo que me preocupa es que el termoestato deje de ser fiable o se comporte raro o no adecuado.

Fig2808_DS18B20.gif


Si lo quieren puedo psar todo el código fuente, hex y simulación.

Código:
; Programa de control para un termómetro y termostato digital. Utiliza el sensor de
; temperatura DS1820 que transmite la información vía serie a través de un bus de una
; sola línea según un protocolo del fabricante de semiconductores Dallas Semiconductors.
;
; El ajuste de la temperatura a la que conmuta el termostato se logra mediante dos
; pulsadores: "MODO" e "INCREMENTAR", que se conectan a pines del Puerto B y cuyo
; funcionamiento se basa en interrupción por cambio en la línea del Puerto B.
;
; Se maneja de la siguiente forma:
; -    En estado de reposo funciona sólo como termómetro. Aparece la temperatura en pantalla
;    del módulo LCD. La salida del termostato está apagada.
; -    Pulsa "MODO" y se ajusta la temperatura deseada mediante el pulsador "INCREMENTAR".
; -    Vuelve a pulsar "MODO", se activa el termostato. Si la temperatura medida es menor
;    que la deseada enciende la carga, que puede ser un calefactor. Si la temperatura 
;    medida es mayor que la deseada, apaga la carga.
; -    Si se vuelve a pulsar "MODO", apaga la carga y pasa a funcionar sólo como termómetro.
;
; Así pues, en el circuito se distinguen tres modos de funcionamiento que se identifican
; mediante tres flags:
; A)    Modo "Termostato_OFF", donde funciona como termómetro normal sin termostato. Se
;        reconoce por el flag F_Termostato_OFF.
; B)    Modo "Termostato_Ajuste", donde se ajusta la temperatura deseada cuando funcione
;        como termostato. Se reconoce por el flag F_Termostato_Ajuste.
; C)    Modo "Termostato_ON", donde funciona como termómetro normal con termostato. Se
;        reconoce por el flag F_Termostato_ON.
;
; El programa consigue que esté activado uno solo de los flags anteriores.
;
; Al apagar el sistema debe conservar el valor de la temperatura deseada en el termostato
; para la próxima vez que se encienda.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F84A
    INCLUDE        <P16F84A.INC>
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

    CBLOCK    0x0C
    TemperaturaDeseada
    Registro50ms                            ; Guarda los incrementos cada 50 ms.
    FlagsModos                                ; Guarda los flags para establecer los
    ENDC                                    ; modos de trabajo.

    ORG    0x2100                                ; Corresponde a la dirección 0 de la zona
                                            ; EEPROM de datos. Aquí se va a guardar el
    DE    .24                                    ; la temperatura deseada. En principio 24 ºC.

#DEFINE  SalidaTermostato         PORTB,1        ; Carga controlada por el termostato.
#DEFINE  Zumbador                 PORTB,2        ; Aquí se conecta el zumbador.
#DEFINE  ModoPulsador            PORTB,7        ; Los pulsadores se conectan a estos
#DEFINE  IncrementarPulsador    PORTB,6        ; pines del puerto B.
#DEFINE  F_Termostato_ON        FlagsModos,2    ; Flags utilizados en el ajuste de la
#DEFINE  F_Termostato_Ajuste    FlagsModos,1    ; temperatura del termostato.
#DEFINE  F_Termostato_OFF        FlagsModos,0

TMR0_Carga50ms    EQU    d'256'-d'195'            ; Para conseguir interrupción cada 50 ms.
CARGA_2s        EQU    d'40'                    ; Leerá cada 2s = 40 x 50ms = 2000ms.    

; ZONA DE CÓDIGOS ********************************************************************

    ORG     0
    goto    Inicio
    ORG    4
    goto    ServicioInterrupcion

Mensajes
    addwf    PCL,F
MensajePublicitario
    DT "IES. ISAAC PERAL", 0x00
MensajeTermostato_ON
    DT "Termostato: ", 0x00
MensajeTermostato_Ajuste
    DT "Temper. deseada", 0x00
MensajeGradoCentigrado
    DT "ºC  ", 0x00                    ; En pantalla LCD: "ºC  "

Inicio    
    call    LCD_Inicializa
    bsf        STATUS,RP0
    movlw    b'00000111'                ; Prescaler de 256 para el TMR0 y habilita
    movwf    OPTION_REG                ; resistencias de Pull-Up del Puerto B.
    bsf        ModoPulsador            ; Se configuran como entrada.
    bsf        IncrementarPulsador
    bcf        SalidaTermostato        ; Se configuran como salida.
    bcf        Zumbador
    bcf        STATUS,RP0
    call    LCD_Linea1                ; Se sitúa al principio de la primera línea.
    movlw    MensajePublicitario
    call    LCD_Mensaje
    call    DS1820_Inicializa        ; Comienza la conversión del termómetro y pone
    call    ModoTermostato_OFF        ; este modo de funcionamiento.
    movlw    TMR0_Carga50ms            ; Carga el TMR0 en complemento a 2.
    movwf    TMR0
    movlw    CARGA_2s                    ; Y el registro cuyo decremento contará los 2 s.
    movwf    Registro50ms
    clrw                            ; Lee la posición 0x00 de memoria EEPROM de datos
    call    EEPROM_LeeDato            ; donde se guarda la temperatura deseada de la última
    movwf    TemperaturaDeseada        ; vez que se ajustó.
    movlw    b'10101000'                ; Activa interrupción del TMR0 (T0IE), por cambio de
    movwf    INTCON                    ; líneas del Puerto B (RBIE) y la general (GIE)
;
; La sección "Principal" es mantenimiento. Sólo espera las interrupciones.
; No se puede poner en modo de bajo consumo porque la instrucción "sleep" detiene el Timer 0.

Principal
    goto    Principal

; Subrutina "ServicioInterrupcion" ------------------------------------------------------
;
; Detecta qué ha producido la interrupción y ejecuta la subrutina de atención correspondiente.

ServicioInterrupcion
    btfsc    INTCON,T0IF                ; Si es una interrupción producida por el Timer 0
    call    Termometro                ; lee el termómetro y actualiza termostato.
    btfss    INTCON,RBIF                ; Si es una interrupción RBI lee los pulsadores.
    goto    FinInterrupcion
    btfss    ModoPulsador            ; ¿Está presionado el pulsador de "AJUSTE"?
    call    CambiarModo                ; Sí. Ajusta la temperatura deseada en el termostato.
    btfss    IncrementarPulsador        ; ¿Pulsado "INCREMENTAR"?
    call    IncrementarTempDeseada    ; Sí, pasa a incrementar la temperatura deseada.
FinInterrupcion
    bcf        INTCON,RBIF                ; Limpia los flags de reconocimiento.
    bcf        INTCON,T0IF
    retfie

; Subrutina "Termometro" ----------------------------------------------------------------
;
; Esta subrutina lee y visualiza el termómetro cada 2 segundos aproximadamente. Se ejecuta
; debido a la petición de interrupción del Timer 0, cada 50 ms. Para conseguir una
; temporización de 2 s, habrá que repetir 40 veces el lazo de 50 ms (40x50ms=2000ms=2s).
;
; También actúa sobre la salida del termostato posicionándola adecuadamente.

Termometro
    movlw    TMR0_Carga50ms
    movwf    TMR0                    ; Recarga el TMR0.
    decfsz    Registro50ms,F            ; Decrementa el contador.
    goto    FinInterrupcion            ; No han pasado 2 segundos, por tanto sale.
    movlw    CARGA_2s                ; Repone este contador nuevamente.
    movwf    Registro50ms
    call    DS1820_LeeTemperatura    ; Lee la temperatura.
    call    DS1820_Inicializa        ; Comienza conversión para la siguiente lectura.
    call    Termostato                ; Actúa sobre el termostato.
;    call    Visualiza                ; Como esta subrutina se escribe a continuación
;    return                            ; se ahorra estas dos instrucciones y ahorra 
                                    ; también espacio en la pila.
; Subrutina "Visualiza" -----------------------------------------------------------------
;
; Visualiza el termómetro en tres formatos posibles:
; A)    Con el termostato desactivado, modo "Termostato_OFF". Por ejemplo:
;                 "IES. Isaac Peral" (Primera línea)
;                "       24.5ºC   " (Segunda línea).
;        Donde en la primera línea se visualiza un mensaje publicitario y en la
;        segunda línea la temperatura medida actual.
; B)    Ajuste del termostato, modo "Termostato_Ajuste". Por ejemplo:
;                 "Temper. deseada" (Primera línea)
;                "        25ºC     " (Segunda línea).
;         Donde en la segunda línea visualiza la temperatura que se desea ajustar.
; C)    Con el termostato activado, modo "Termostato_ON". Por ejemplo:
;                 "Termostato: 25ºC" (Primera línea)
;                "      23.5ºC    " (Segunda línea).
;         Donde en la primera línea se visualiza la temperatura que se desea
;        ajustar y en la segunda línea la temperatura medida actual.
Visualiza
    btfsc    F_Termostato_OFF
    goto    VisualizaTermometro
    btfsc    F_Termostato_Ajuste
    goto    VisualizaTermostato_Ajuste
    btfsc    F_Termostato_ON
    goto    VisualizaTermostato_ON
    return

; "VisualizaTermostato_ON" --------------------------------------------------------------
;
; Visualiza el valor de la temperatura deseada en la primera línea y el valor de la
; temperatura medida en la segunda línea.
; 
VisualizaTermostato_ON
    call    LCD_Linea1
    movlw    MensajeTermostato_ON
    call    LCD_Mensaje
    call    VisualizaTemperaturaDeseada
    call    VisualizaTemperaturaMedida
    return

; "VisualizaTermostatoAjuste" y "VisualizaTemperaturaDeseada" ---------------------------
;
; Visualiza en la pantalla el formato propio de este modo.
; 
; Entradas:    (TemperaturaDeseada) temperatura ajustada en la subrutina Incrementar.

VisualizaTermostato_Ajuste
    call    LCD_Linea1                    ; Se sitúa al principio de la primera línea.
    movlw    MensajeTermostato_Ajuste    ; Visualiza mensaje en la primera línea.
    call    LCD_Mensaje
    movlw    .6                            ; Se coloca para centrar visualización en la 
    call    LCD_PosicionLinea2            ; segunda línea.
VisualizaTemperaturaDeseada
    movf    TemperaturaDeseada,W
    call    BIN_a_BCD                    ; La pasa a BCD.
    call    LCD_Byte                    ; Visualiza, apagando los ceros no significativos.
    movlw    MensajeGradoCentigrado        ; En pantalla aparece "ºC  ".
    call    LCD_Mensaje
    return

; "VisualizaTermometro" y ""VisualizaTemperaturaMedida" ---------------------------------
;
; En la primera línea se visualiza un mensaje publicitario y en la segunda línea la
; temperatura medida
;
; Entradas:
;      -    (DS1820_Temperatura), temperatura medida en valor absoluto.
;     -    (DS1820_TemperaturaDecimal), parte decimal de la temperatura medida.
;     -    (DS1820_Signo), registro con el signo de la temperatura. Si es igual a
;        b'00000000' la temperatura es positiva. Si es b'11111111' resulta que
;        la temperatura es negativa.
;
VisualizaTermometro
    call    LCD_Linea1                ; Se sitúa al principio de la primera línea.
    movlw    MensajePublicitario
    call    LCD_Mensaje
VisualizaTemperaturaMedida
    movlw    .5                        ; Se coloca para centrar visualización en la
    call    LCD_PosicionLinea2        ; segunda línea.
    btfss    DS1820_TemperaturaSigno,7 ; ¿Temperatura negativa?
    goto    TemperaturaPositiva        ; No, es positiva.
TemperaturaNegativa:
    movlw     '-'                        ; Visualiza el signo "-" de temperatura negativa.
    call    LCD_Caracter
TemperaturaPositiva
    movf    DS1820_Temperatura,W
    call    BIN_a_BCD                ; La pasa a BCD.
    call    LCD_Byte                ; Visualiza apagando los ceros no significativos.
    movlw    '.'                        ; Visualiza el punto decimal.
    call    LCD_Caracter
    movf    DS1820_TemperaturaDecimal,W ; Visualiza la parte decimal.
    call    LCD_Nibble
    movlw    MensajeGradoCentigrado    ; En pantalla LCD aparece "ºC  ".
    call    LCD_Mensaje
    return

; Subrutina "Termostato" ----------------------------------------------------------------
;
; Controla una carga en función del valor de la temperatura medida respecto de la temperatura
; deseada. Para evitar inestabilidad en la salida, tendrá un pequeño ciclo de histéresis.
; Así por ejemplo, si la temperatura deseada es 24 ºC la carga se activará cuando la
; temperatura baje o sea igual a 23,5 ºC y se apagará cuando la supere o sea igual a 25ºC.
; Si la temperatura medida está entre esos márgenes (23,5 y 25ºC), se queda en el estado
; anterior, tanto si está encendida como apagada.
;
; Para temperaturas negativas la salida se debe activar siempre.
;
; Entradas:
;         -    (DS1820_Temperatura), temperatura medida en valor absoluto.
;         -    (TemperaturaDeseada), temperatura a partir de la cual se tomarán
;            decisiones sobre la salida.
;         -    (DS1820_Signo), registro con el signo de la temperatura medida. Si es cero
;            la temperatura es positiva y todos sus bits son "1", es negativa.
;
; Salida:    -    Su funcionamiento:
;              -    Estando apagada, si la temperatura medida desciende por debajo de la
;                temperatura deseada la salida se activará.
;             -    Estando encendida, si la temperatura medida supera la deseada la
;                salida se apagará.
;             -    Si las temperaturas medidas y deseada son iguales se queda en estado
;                anterior, tanto si está encendida como si está apagada.
;             -    Para temperaturas negativas la salida se debe activar siempre.
Termostato
    btfss    F_Termostato_ON            ; Si el termostato no está activado salta a
    goto    ApagaCarga                ; apagar la carga.
    btfsc    DS1820_TemperaturaSigno,7    ; Con temperaturas negativas pasa a activar
    goto    EnciendeCarga            ; la carga.
    btfss    SalidaTermostato        ; Comprueba el estado actual de la salida para
    goto    SalidaEstabaApagada        ; actuar en consecuencia.
SalidaEstabaActivada                ; Pasa a comprobar si tiene que apagar la carga.
    movf    DS1820_Temperatura,W
    subwf    TemperaturaDeseada,W    ; (W)=(TemperaturaDeseada)-(DS1820_Temperatura).
    btfsc    STATUS,C                ; ¿(TemperaturaDeseada)<(DS1820_Temperatura)?    
    goto    FinTermostato            ; Sí, por tanto, lo deja encendido y sale.
    call    Pitido                    ; Pitido cada vez que conmuta la carga.
ApagaCarga
    bcf        SalidaTermostato        ; Apaga la salida y sale.
    goto    FinTermostato
SalidaEstabaApagada                    ; Pasa a comprobar si tiene que encender la carga
    movf    TemperaturaDeseada,W
    subwf    DS1820_Temperatura,W    ; (W)=(DS1820_Temperatura)-(TemperaturaDeseada).
    btfsc    STATUS,C                ; ¿(DS1820_Temperatura)<(TemperaturaDeseada)?    
    goto    FinTermostato            ; Sí, la deja apagada y sale.
EnciendeCarga
    call    Pitido                    ; Pitido cada vez que activa la carga.
    bsf        SalidaTermostato
FinTermostato
    return

; Subrutinas "CambiarModo" y "ModoTermostato_OFF" -----------------------------------------
;
; Subrutina de atención a la interrupción producida por el pulsador "MODO" que cambia el modo
; de funcionamiento. Cada vez que pulsa pasa por los modos "Termostato_Ajuste", "Termostato_ON",
; "Termostato_OFF" y vuelta repetir.
;
; El ajuste de la temperatura deseada en el termostato se logra mediante dos pulsadores: "MODO"
; e "INCREMENTAR" conectados a pines del Puerto B.

; Al principio aparecerá sólo el termómetro y el termostato estará desactivado: modo
; "Termostato_OFF"
;
; Para comprender el funcionamiento de esta subrutina, hay que saber que el registro FlagsModos
; contiene 3 flags que permiten diferenciar cada uno de los modos de funcionamiento:
; A)    Modo "Termostato_OFF", donde funciona como termómetro normal sin termostato. Se
;        reconoce por el flag F_Termostato_OFF, que es el bit 0 del registro FlagsModos.
; B)    Modo "Termostato_Ajuste", donde se ajusta la temperatura deseada cuando funcione
;        como termostato. Se reconoce por el flag F_Termostato_Ajuste, que es el bit 1 del
;        registro FlagsModos.
; C)    Modo "Termostato_ON", donde funciona como termómetro normal y, además, como termostato.
;        Se reconoce por el flag F_Termostato_ON, que es el bit 2 del registro FlagsModos.
;
; Así pues, el contenido del registro (FlagsModos) identifica los siguientes modos de
; funcionamiento:
; - (FlagsModos)=b'00000001'. Está en el modo "Termostato_OFF".
; - (FlagsModos)=b'00000010'. Está en el modo "Termostato_Ajuste".
; - (FlagsModos)=b'00000100'. Está en el modo "Termostato_ON".

; Pueden darse dos casos:
; -    Que pulse "AJUSTE" estando en el modo más alto, "Termostato_ON",
;    (FlagsModos)=b'00000100'. En este caso debe pasar al modo inicial 
;    "Termostato_OFF" poniendo (FlagsModos)=b'00000001'.
; -    Que pulse "AJUSTE" estando ya en cualquiera de los otros dos modos, en cuyo caso debe
;    pasar al siguiente modo. Esto lo hace mediante un desplazamiento a izquierdas. Así, por
;    ejemplo, si antes estaba en modo "Termostato_OFF", (FlagsModos)=b'00000001', pasará a
;    (FlagsModos)=b'00000010' que identifica al modo "Termostato_Ajuste".
;
CambiarModo
    call    Retardo_20ms            ; Espera a que se estabilicen niveles de tensión.
    btfsc    ModoPulsador            ; Si es un rebote, sale fuera.
    goto    FinCambiarModo
    call    PitidoCorto                ; Cada vez que pulsa se oye un pitido.
    btfss    F_Termostato_ON            ; Detecta si está en el último modo.
    goto    ModoSiguiente            ; Si no, pasa al modo siguiente.
ModoTermostato_OFF
    call    Pitido                    ; Pitido cada vez que conmuta la carga.
    bcf        SalidaTermostato        ; Apaga la carga.
    movlw    b'00000001'                ; Actualiza el registro FlagsModos pasando al
    movwf    FlagsModos                ; modo inicial "Termostato_OFF".
    goto    BorraPantalla
ModoSiguiente                        ; Desplaza un "1" a la izquierda del registro
    bcf        STATUS,C                ; FlagsModos para ajustar secuencialmente
    rlf        FlagsModos,F            ; cada uno de los modos de funcionamiento.
BorraPantalla
    call    LCD_Borra                ; Borra la pantalla anterior.
FinCambiarModo
    call    Visualiza
    btfss    ModoPulsador            ; Ahora espera a que deje de pulsar.
    goto    FinCambiarModo
    return

; Subrutina "IncrementarTempDeseada" ----------------------------------------------------
;
; Subrutina de atención a la interrupción por cambio de la línea RB6 a la cual se ha conectado
; el pulsador "INCREMENTAR". Estando en el modo "Termostato_Ajustar" incrementa el valor de
; la temperatura deseada entre unos valores máximo y mínimo.
;
; Al final debe guardar el valor de la temperatura deseada en memoria EEPROM de datos para
; preservar su valor en caso que desaparezca la alimentación.
;
TemperaturaMinima   EQU    .20
TemperaturaMaxima   EQU    .36

IncrementarTempDeseada
    call    Retardo_20ms            ; Espera a que se estabilicen niveles de tensión.    
    btfsc    IncrementarPulsador        ; Si es un rebote sale fuera.
    goto    FinIncrementar
    btfss    F_Termostato_Ajuste        ; Si no está en modo "Termostato_Ajuste" sale
    goto    FinIncrementar            ; fuera.
    call    PitidoCorto                ; Pitido cada vez que pulsa.
    incf    TemperaturaDeseada,F    ; Incrementa el valor de la temperatura deseada.
    movlw    TemperaturaMaxima        ; ¿Ha llegado a la temperatura máxima de ajuste?.
    subwf    TemperaturaDeseada,W    ; (W) = (TemperaturaDeseada) - TemperaturaMaxima.
    btfss    STATUS,C                ; ¿(TemperaturaDeseada)>=TemperaturaMaxima?
    goto    VisualizaIncremento        ; No, pasa a visualizarlo.
    movlw    TemperaturaMinima        ; Sí, entonces inicializa el registro.
    movwf    TemperaturaDeseada
VisualizaIncremento
    call    Visualiza                ; Visualiza mientras espera a que deje
    call    Retardo_200ms            ; de pulsar.
    btfss    IncrementarPulsador        ; Mientras permanezca pulsado,
    goto    IncrementarTempDeseada    ; incrementa el dígito.
    clrw                            ; Salva el valor de la temperatura deseada en la 
    movwf    EEADR                    ; posición 00h de la EEPROM de datos. Se conserva
    movf    TemperaturaDeseada,W    ; aunque se apague la alimentación.
    call    EEPROM_EscribeDato
FinIncrementar
    return

; Subrutina de pitidos ------------------------------------------------------------------
;
PitidoLargo
    bsf        Zumbador
    call    Retardo_500ms
Pitido
    bsf        Zumbador
    call    Retardo_200ms
PitidoCorto
    bsf        Zumbador
    call    Retardo_20ms
    bcf        Zumbador
    return
;
    INCLUDE  <BUS_1LIN.INC>            ; Subrutinas de control del bus de 1 línea.
    INCLUDE  <DS1820.INC>            ; Subrutinas de control del termómetro digital.
    INCLUDE  <RETARDOS.INC>
    INCLUDE  <BIN_BCD.INC>
    INCLUDE  <LCD_4BIT.INC>
    INCLUDE  <LCD_MENS.INC>
    INCLUDE  <EEPROM.INC>
    END
 
Más bien podría, depende como lo programes y si no te equivocas, `por ejemplos, la temperatura real es de 27ºC y en LCD te muestra otra cosa por poner un ejemplo tonto.

Por eso tanto lío con el NE555, ejjejejejeje, porque no se hacer eso con el código ya programado. Como dijeron arriba, mejor hacerlo con un goto y el código a parte, para eso usaré un CALL y meteré el resto del código (subrutina) en un archivo a parte llamado TEMPORIZADOR.INC o simplemente TEMP.INC.
 
Atrás
Arriba