TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: bigluis en 24 de Julio de 2011, 16:38:24
-
El siguiente proyecto consiste en un reloj calendario que utiliza el TIMER2 como base de tiempo para realizar un reloj calendario por software. Es decir, no es necesario utilizar un RTC como el DS1307 para este reloj y tampoco un módulo interno en el PIC.
Para ello vamos a hacer uso de la libreria rtcimer.c que nos provee el compilador PIC-C Compiler de CCS.
El funcionamiento del circuito consiste en tres botones:
- Set: este sirve para configurar la hora y la fecha
- Incrementar: este sirve para incrementar los valores que se asignaran a cada elemento de la fecha.
- Decrementar: este sirve para decrementar los valores que se asignaran a cada elemento de la fecha.
A continuación muestro el código del circuito:
#include <16f887.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No brownout reset
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brownout reset at 4.0V
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//#include <time.h> //standard C time library
#include <rtctimer.c> //library for time.h that uses timer2 as time base
#include <stdlib.h>
#include <input.c> //needed for the rs232 input routines
#define LCD_DATA_PORT getenv("SFR:PORTB")
#include <lcd.c>
/*La siguiente funcion retorna el valor que se
*/
char get_val(char v_ini,char v_final){
char cont=v_ini; //Inicializamos cont con el valor inicial
do{
if(input(PIN_A1)){ //Si se presiona el boton incrementar
if(cont<v_final)cont++; //Y si cont es menor que v_final incrementar cont (ej: si v_final=30 => cont incrementa si cont<30)
else cont=v_ini; //de lo contrario cont sera igual a v_ini (ej: si v_ini=0 y cont>=30 => cont=0)
}
if(input(PIN_A2)){ //Si se presiona el boton decrementar
if(cont>v_ini)cont--; //Y si cont es mayor que v_ini incrementar cont (ej: si v_ini=0 => cont decrementa si cont>0)
else cont=v_final; //de lo contrario cont sera igual a v_final (ej: si v_final=30 y cont<=0 => cont=30)
}
delay_ms(500); //Retardo de 500ms para disminuir la velocidad de los cambios
lcd_gotoxy(14,1); //Ubica el cursor en la posicion 14,1
printf(lcd_putc,"%2u",cont); //Imprime el valor actual del contador
}while(!input(pin_a0)); //Espera a que presionen el boton set
delay_ms(10); //Retardo de 10ms para evitar rebotes
while(input(pin_a0)); //Espera a que liberen el boton set
lcd_gotoxy(1,1); //Ubica el cursor en la posicion 1,1
return cont; //retorna el valor de la variable cont
}
void ChangeTime(void)
{
struct_tm t;
delay_ms(10); //Retardo de 10ms para evitar rebotes
while(input(pin_a0)); //Espera a que liberen el boton set
//tm_year is years since 1900.
lcd_gotoxy(1,1); //Ubica el cursor en la posicion 1,1
lcd_putc("Aîo (0-30): 0"); //Escribe en el lcd "Año (0-30):" (î es el valor ASCII de la ñ en el LCD)
t.tm_year = get_val(0,30) + 100; //add 100 to put is into 2000
lcd_putc("Mes (1-12): 1");
t.tm_mon = get_val(1,12) - 1;
lcd_putc("Dia (1-31): 1");
t.tm_mday = get_val(1,31) - 1;
lcd_putc("Hora (0-23): 0");
t.tm_hour = get_val(0,23);
lcd_putc("Min (0-59): 0");
t.tm_min = get_val(0,59);
SetTime(&t); //A partir de los valores obtenidos comfigura el tiempo en el RTC.
lcd_putc("\f"); //Borra el LCD
}
void main(){
char tString[24];
time_t tTime = 0;
//struct_tm t1;
/* Setup the LCD */
lcd_init();
setup_timer_2(T2_DIV_BY_1,250,4);
/* Enable the timer 2 interrupt, or it will not fire */
enable_interrupts(INT_TIMER2);
/* Enable interrupts globally too, otherwise no interrupt will fire */
enable_interrupts(GLOBAL);
setup_adc_ports(sAN4|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);
while(1){
tTime = time(NULL); //Obtiene los segundos que han pasado desde 1970
localtime(&tTime); //convierte el tiempo en segudos al tiempo en forma natural y lo almacena en la estructura g_lTime.
//g_lTime guarda los valores de hora, minutos, segudos y fecha.
lcd_gotoxy(1,1);
//Escribe en el LCD la hora, los minutos y segundos.
printf(lcd_putc,"%02u:%02u:%02u\n",g_lTime.tm_hour,g_lTime.tm_min,g_lTime.tm_sec);
//Escribe en el LCD la fecha en formato corto.
printf(lcd_putc,"%02u-%02u-%02Lu",g_lTime.tm_mday+1,g_lTime.tm_mon+1,g_lTime.tm_year);
if(input(pin_a0))
changeTime();
}
}
Cabe mencionar que la librería rtctimer.c utiliza las siguientes funciones:
- tTime() que se encarga de obtener los segundos que han transcurrido desde 1970.
- *ts = localtime(*t) converite los segundos de tiempo a hora, minutos, segundos, dia, mes, año, etc y se almacena en la variable g_lTime
- *char cTime(*t, *char) convierte los segundos de tiempo a una cadena de caracteres legibles en formato Dia de semana, Mes, Dia del mes, Hora, minutos, segundos y Año
- SetTime(*ts) convierte la estructura de hora, minutos, segundos, dia, mes, año, etc a segundos de tiempo.
Y el esquema del circuito:
(http://img155.imagenar.com/155/9bc5b9d0/a763ed37/reloj.png) (http://imagenar.com/i/Descarga-Reloj/IGy)
Y finalmente el archivo adjunto del Código fuente y el Esquema.
-
muy lindo, voy a montarlo a ver que onda ;-), se ve muy interesante, gracias por compartirlo :-/
Saludios.-
-
¿Cómo calculo los valores para la función setup_timer_2 para cristales de diferentes frecuencias?
-
Ya que el Timer2 es el que se encarga de generar los ciclos de reloj, debes usar este para realizar los calculos.
Si tienes un cristal de 4MHz y configuras el Timer2 para q se desborde cada 1000 ciclos de reloj no debes hacer nada. Sin embargo, si tienes una frecuencia de 8MHz y configuras el TIMER2 para que se desborde cada 1000 ciclos entonces debes definir lo siguiente al inicio del programa justo antes de los #include ...
...
#define CLOCKS_PER_SECOND 2000
#include
...
en otras palabras debes hacer lo siguiente
CLOCKS_PER_SECOND = Fosc / 4MHz * 1000
-
Gracias por la info, yo lo estoy usando con un PIC18f2550 a la vez que uso la comunicación USB (clock a 48 MHz), es info que puede serle útil a quien no tenga a la mano un cristal de 4 MHz para probar el proyecto :).
-
Si lo se, :oops: olvide mencionarlo anteriormente.
-
Lo olvidaba, muchas gracias por compartir, ya lo pude probar en Proteus, a ver si después lo puedo armar :).
-
Hola Luis!!!
Te molesto en relación al proyecto q publicastes en todopic:
http://www.todopic.com.ar/foros/index.php?topic=35555.0
"...un reloj calendario que utiliza el TIMER2 como base de tiempo para realizar un reloj calendario por software. Es decir, no es necesario utilizar un RTC como el DS1307 para este reloj y tampoco un módulo interno en el PIC."
Me parece muy útil ya q no usa otra cosa más q el pic. El costo del DS1307 aquí es de unos 6 U$S además de los costos q trae asociados (PBC, componentes, etc).
La idea es instalarlo en un controlador pre-existente que esta hecho precisamente con el 16F887 pero con un Display 2x8.
La idea es poder manejar un relay para encendido/apagado de iluminación con una tabla de días. Ejemplo: día 5 enciende a las 4:30 hs. y apaga a las 18:45 hs.
En mi controlador ya tengo 4 pulsadores de y una rutina para manejarlos al igual q una para el LCD.
Al final de la nota dice q incluís el código y el esquema pero no aparece.
¿Podrías enviármelos al igual que los comentarios que consideres necesarios para inplementarlo?
¿Podrás indicarme dónde ubicar la función para el uso del relay? Por ejemplo ya tengo un menu.c que es donde va el main.c ni bien arranca
Desde ya muchas gracias por tu atención
Un saludo
Daniel
-
¿Podrías enviármelos al igual que los comentarios que consideres necesarios para inplementarlo?
¿Podrás indicarme dónde ubicar la función para el uso del relay? Por ejemplo ya tengo un menu.c que es donde va el main.c ni bien arranca
El codigo esta en el pie del mensaje (siempre ha estado ahi). Ademas contiene basicamente lo mismo que miras en la pagina web. Pero de todos modos este es el link:
http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=35555.0;attach=16285
Lo de la funcion para el uso del relay no tengo la menor idea ya que no se como es tu codigo.
-
Control de un motor de 220V
He visto tu sistema para el calentador de agua. Excelente.
En otro tema preciso tu ayuda ya que dominas mucho el tema de manejo de triacs
Sólo necesito reemplazar un Relay por un Triac y hacerlo variable en potencia. Mi código actual consiste en habilitar el relay con un 1 en el PIN_A7 y apagarlo con un 0.
Ya tengo puesto un opto MOC3020 y funciona de maravillas en la pata RA7 del 16F887.
Tengo habilitado el Timer_2 para otras tareas pero no consigo meter allí el ejemplo de BrunoF.
http://www.todopic.com.ar/foros/index.php?topic=40301.0
Casi seguro tienes algún truquillo para esto ....
¿podrás echarme una soga?
Muchas gracias!!!!
Daniel
friniar@hotmail.com
-
Hola!
Tengo un pro. de retraso de unos 20' cada hora.
Tengo el timer_2 así:
setup_timer_2(T2_DIV_BY_16,125,10); // 0.5us*16*125*10=10mS
en lugar de tu set:
setup_timer_2(T2_DIV_BY_1,250,4);
También usé el #define CLOCKS_PER_SECOND 200
pero no logro solución
¿Algún consejo?
-
Prueba a configurar el timer a 11ms o a cambiar CLOCKS_PER_SECOND 220