Autor Tema: usar timer como retardo????  (Leído 5046 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
usar timer como retardo????
« en: 14 de Noviembre de 2005, 10:58:00 »
hola, estoy tratando de hacer que el pic cuente 2 tiempos a la vez , me explico: usando un 16f84A quiero que al dejar pulsado el boton en RA0 se active un timer que espere 30 segundos si el boton lo suelto el timer se detenga y se vuelva a cero, si pasan los 30 segundos que verifique que el boton de RA1 este pulsado si no es asi que encienda RA2, y apague RB2 cuando se suelte RB0, la idea es hacer eston con todos los timer que posea el 16f84.


¿es posible hacer esto?
si fuera posible me podrian dar ejemplos de uso del timer por que los que estan en el foro no los e podido hacer trabajar como quiero.


saludos...RebotadoRebotado

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #1 en: 14 de Noviembre de 2005, 16:32:00 »
Hola

te puedo proponer la solución, el programa tú te lo imaginas Sonrisa

Botón 1 en RB0 (con capacitor para filtrar rebotes del botón)
Botón 2 en donde quieras
LED 1 y 2 donde quieras

Usa interrupción externa con flanco izquierdo, es decir, interrumpe cuando RB0 pase de 0 a 1, ese será tu botón 1.

En la subrutina de interrupción configura la activación del timer0 para que cuente los 30s y también configura el flanco derecho (1 a 0) de la int por RB0, así detectará la liberación del botón 1.

Si se libera el botón 1 antes de los 30s, vuelve a habilitar el flanco izquierdo y apaga tu timer0, que deje de contar.

Si llegas a 30s, haz lo que tengas que hacer con el botón 2. El led que indica que el botón 1 sigue oprimido podrá apagarse con el flanco derecho del botón 1 (que es cuando se libera).

Suerte Vacilando

Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #2 en: 14 de Noviembre de 2005, 17:22:00 »
hola migsantiago, tu idea me parece buenisima si no fuera por eso de los flancos que no entiendo podria hacer mas codigo, aqui te dejo lo que entendi y codifique

#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT
#nolist
#byte port_A=05
#byte port_b=06
#use fixed_io(A_OUTPUTS=PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A4)
#use fixed_io(B_OUTPUTS=PIN_B1,PIN_B2,PIN_B3,PIN_B6,PIN_B7)

#INT_EXT
boton_RB0()
{
/* aqui tendria que abilitar el timer, pero como lo ago???
   como se cuando el timer llego a los 30 segundos, donde devo colocar
   el codigo para sensar el segundo boton.*/

}

void main()
{
   enable_interrupts(global);
   enable_interrupts(INT_EXT);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_2);// asi se declara el timer???, esta bien para 30 segundos????.
   port_a=0;
   port_b=0;

   while(TRUE)
   {
     
   }
}


si esta muy mal perdon.

para que son los flancos?

y sobre lo que mencionas de un capacitor, ¿¿¿¿¿el capacitor es un condensador?????, y si es asi de cuanto tendria que ser para cada boton, serviria uno de 33Pf el mismo que uso para el pic?.

saludos...

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #3 en: 14 de Noviembre de 2005, 19:58:00 »
Ahí te va la explicación...

En RB0 puedes conectar un botón. Existe una interrupción externa en esa terminal.

El PIC se va a interrumpir cuando...
- RB0 pase de 0 a 1, flanco izquierdo _|
o
- RB0 pase de 1 a 0, flanco derecho |_

es decir, no importa que esté haciendo el PIC, cuando haya cambio de 0 a 1 o viceversa, va a saltar a una subrutina de interrupción y hacer otra cosa.

Para configurarla necesitas primero decir que flanco va a interrumpir al PIC en RB0, ¿subida o bajada?:

EXT_INT_EDGE(L_to_H); //interrumpe cuando pasa de 0 a 1 SUBIDA

o

EXT_INT_EDGE(H_to_L); //interrumpe cuando pasa de 1 a 0 BAJADA

luego habilitas la int ext y luego la global, en ese orden

enable_interrupts(INT_EXT);
enable_interrupts(global);

ya en #INT_EXT metes el código que deba suceder en el evento de una interrupción.

Cuando quieres detectar la presión de RB0 pon L to H y cuando sea liberación pon H to L.

Ahora sobre el timer... nunca vas a lograr que te cuente 30s de un sólo jalón... necesitas hacer conteos de 5ms (por ejemplo) y contar cuantas veces ya pasaron 5ms, de esa forma llegarás a 30s.

Cada que el PIC se te interrumpa porque ya pasaron 5ms, incrementa un contador. Cuando tu contador llegué a 6000 (6000x5ms=30s) sabrás que ya pasaron 30s.

Es un programa un poco complejo pero no imposible. Te explico lo básico únicamente. Te recomiendo visites el link de Ejemplitos para PIC16F84a, está interesante y puedes empezar desde cero.

Ahora el capacitor... así les decimos por acá. También conocidos como condensadores Sonrisa

La conexión del capacitor de 1uF debe ser así




Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #4 en: 14 de Noviembre de 2005, 20:10:00 »
hola, el pin del pic ba conectado al condensador??

cuando se active la int_ext de L_to_H la tengo que volver a setear de H_to_L

pero como sabre cuando va de L_to_H o H_to_L.



saludos

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #5 en: 14 de Noviembre de 2005, 20:20:00 »
El positivo del capacitor va al pin del PIC. Sonrisa Esto te lo recomiendo porque cuando presionas un botón, éste nunca hace un cambio de 0 a 1 inmediato, el botón "rebota" varias veces hasta que se queda en 1.

Lo primero que esperas es que el usuario presione el botón, es decir, que pase de 0 a 1. Entonces lo primero que programas es Low to High.

Ya que el botón se apretó y estando en la subr de interrupción, cámbialo a High to Low, porque ahora esperas que desapriete el botón. Ya luego sal de la subrutina.


Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #6 en: 14 de Noviembre de 2005, 20:37:00 »
HOLA, ESTE CODIGO SERVIRA?

#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT
#nolist
#byte port_A=05
#byte port_b=06
#use fixed_io(A_OUTPUTS=PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A4)
#use fixed_io(B_OUTPUTS=PIN_B1,PIN_B2,PIN_B3,PIN_B6,PIN_B7)
INT X;

retardo()
{
   FOR(X=0;X<=6000;X++)
   {
      DELAY_MS(5);
   }
}

#INT_EXT
boton_RB0()
{
         
   if(input(pin_b0)==1)
   {                     
      EXT_INT_EDGE(H_to_L);
      RETARDO();    
   }else{
      EXT_INT_EDGE(L_to_H);
      X=6001;
   }
}

void main()
{
   enable_interrupts(global);
   enable_interrupts(INT_EXT);
   port_a=0;
   port_b=0;

   while(TRUE)
   {
      OUTPUT_HIGH(PIN_A0);
      DELAY_MS(100);
      OUTPUT_LOW(PIN_A0);
      DELAY_MS(100);
   }
}

MI PREGUNTA ES LA SIGUIENTE CUANDO EL USUARIO SUELTYE EL BOTON Y EJECUTE ESTE CODIGO

EXT_INT_EDGE(L_to_H);
      X=6001;

Y EL PROGRAMA SALTO DE LA FUNCION RETARDO() A LA INTERRUPCION Y X TOME EL VALOR DE 6001 Y EL PROGRAMA VUELVA A LA FUNCION DE RETARDO EL CICLO FOR SE INTERRUMPIRA?

SALUDOS..

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #7 en: 14 de Noviembre de 2005, 20:52:00 »
No es muy recomendable empezar a programar en C sin saber programar en ensamblador. Hay muchas cosas que se asumen se hacen en C, pero que en ensamblador hay que considerar. Si no has aprendido ensamblador, te recomiendo que empieces porque C te va a costar mucho trabajo.

Cuando hagas una subrutina de interrupción, nunca metas delays ahí, las subrutinas de interrupción están para indicar eventos al PIC, no para llevar a cabo tareas muy tardadas.

No es buena idea poner delay de 5ms... en ese caso mejor pon uno así

delay_ms(30000);

¿no crees?

Haz un diagrama de flujo de tu algoritmo. Calcula la escala del predivisor del timer0 y el número a cargarle.

Empieza por lo básico, genera una subrutina de tiempo de 5ms por timer0, no con delay. Cuando la tengas postéala. invasor

Por favor dime si sabes programar en assembler, porque si no, habrá muchas cosas que no te puedo explicar en C.

Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #8 en: 14 de Noviembre de 2005, 20:56:00 »
ASM PARA PIC MICRO NO PROGRAMO EN ASM PARA PROCESADORES DE INTEL DE MAQUINAS GRANDES, NO CREO QUE SEA MUY DISTINTO.


SALUDOS...

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #9 en: 14 de Noviembre de 2005, 21:03:00 »
El problema es que necesitas familiarizarte con el assembler de los PIC.

Bueno, por ahora crea un código que te genere un retardo de 5ms mediante timer0. Iremos construyendo tu programa paso a paso. Giño

Escríbelo en C y postéalo para revisarlo. Empieza calculando el predivisor y el dato a cargar en el contador. Idea

Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #10 en: 14 de Noviembre de 2005, 21:37:00 »
hola, nose si estara bien pero creo que aqui el rtcc cada 4ms

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

#int_RTCC
RTCC001() {

}

#int_EXT
EXT001() {

}

#int_TIMER0
TIMER001() {

}

void main()
{
   setup_counters(RTCC_EXT_L_TO_H,RTCC_DIV_16); /cada 4ms (4000000/(4*256*256)) lo aproxime a 16

   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(global);

}

es asi sierto.

saludos..

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #11 en: 15 de Noviembre de 2005, 19:12:00 »
Eso de

setup_counters(RTCC_EXT_L_TO_H,RTCC_DIV_16);

no va a funcionar, lo estás configurando para ponerle un oscilador externo... mejor ponle así:

setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
set_timer0(valor_tmr0); //carga TMR0

La fórmula para el timer0 es:

t=(256-N)*Tosc*4*pred

N lo propones (8bit). Digamos que tienes 90...

t=(256-90)(1/4MHz)(4)(16)=2.656ms

Ahora propon un valor_tmr0 para que te de 5ms... Divertido

Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #12 en: 15 de Noviembre de 2005, 19:50:00 »
hola, en necesario usar setup_counters(RTCC_INTERNAL,RTCC_DIV_16);  para que funcione el timer0 ??
o asi como lo estoy tratando de usar funciona?
con respecto al calculo del timer0 el tiempo mas alto que me dio fueron 4ms no 5ms asi que lo deje asi, nose si estabien.

#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT
#nolist
#byte port_A=05
#byte port_b=06
#use fixed_io(A_OUTPUTS=PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A4)
#use fixed_io(B_OUTPUTS=PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7)
int x;

#INT_EXT
boton_RB0()
{
   if(input(pin_b0)==1)
   {
       EXT_INT_EDGE(H_to_L);
   }else{
      EXT_INT_EDGE(L_to_H);
   
   }
}

#int_TIMER0
TIMER001()
{
   x++;
}

void main()
{
   enable_interrupts(global);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_TIMER0);
   set_timer0(0);
   port_a=0;
   port_b=0;
   x=0;
   while(TRUE)
   {
      if(x==5000)
      {
         port_a=1;
      }  
     
      if(x==10000)
      {
         port_a=0;
         x=0;
      }
   }
}

saludos...

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: usar timer como retardo????
« Respuesta #13 en: 16 de Noviembre de 2005, 17:38:00 »
y qué valor hay que cargar en el contador del timer0 para que se interrumpa cada 4ms? Sonrojado

Desconectado Sebascl

  • PIC12
  • **
  • Mensajes: 73
RE: usar timer como retardo????
« Respuesta #14 en: 16 de Noviembre de 2005, 20:55:00 »
hola,
use un valor 16,
t=(256-16)(1/4MHz)(4)(16)=3.84ms

lo que no entiendo que valor tengo que poner en el set_timer0(16); puse el valor que utiliza en el calculo.

#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT
#nolist
#byte port_A=05
#byte port_b=06
#use fixed_io(A_OUTPUTS=PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A4)
#use fixed_io(B_OUTPUTS=PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7)
int x;

#INT_EXT
boton_RB0()
{
   if(input(pin_b0)==1)
   {
      EXT_INT_EDGE(H_to_L);
      disable_interrupts(INT_TIMER0);
   }else{
      EXT_INT_EDGE(L_to_H);
      enable_interrupts(INT_TIMER0);
   }
}

#int_TIMER0
TIMER001()
{
   x++;
}

void main()
{
   enable_interrupts(global);
   enable_interrupts(INT_EXT);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
   enable_interrupts(INT_TIMER0);
   

   port_a=0;
   port_b=0;
   x=0;
   while(TRUE)
   {
      if(x==5000)
      {
         port_a=1;
      }

      if(x==10000)
      {
         port_a=0;
         x=0;
      }
   }
}

saludos...