Como primera medida hay que destacar que se debe realizar un circuito externo para poder medir la frecuencia de por ejemplo: un motor. Con lo cual veremos ese circuito a continuación, el cual será conectado a una entrada del pic16f877a y podremos visualizar su frecuencia para su posterior conversión a rpm.
Este circuito no es mas que un detector de obstáculos, en cual si tenemos por ejemplo: un motor con una o mas hélices, el circuito este detectará cuando esta hélice se interpongan, por lo tanto generara que el circuito se cierre y de esta forma enviaremos la salida del comparador a la entrada del pic.
Respecto del Pic16f877A, la entrada funcionará de la siguiente forma, cuando se detecte el primer flanco ascendente de la señal, este comenzará la cuenta del Timer 1, el cual contara hasta que este detecte el segundo flanco ascendente. Con esto obtendremos el periodo de la señal entrante, pudiendo tener lo más exacta posible la frecuencia que ingresa.
Con la siguiente imagen ilustraremos como seria:
Programa Principal:
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdio.h>
#include "RPM.h"
#include "LCD_control.h"
#include "LCD_NUMEROSGRANDES.h"
/*========================================================================
FUNCTION: main()
DESCRIPTION: Devuelve el valor de las rev por minuto(entero sin signo)
PARAMETERS: Ninguno
RETURNS: Nada
REQUIREMENTS: Ninguno
========================================================================*/
void main(void)
{
//Configuracion de puertos
TRISD = 0x00;
PORTD = 0x00;
//Inicializaciones
LCD_init();
RPM_init();
LCD_command(CLEAR);
LCD_array(1,1,"* PIC16F877A *");
LCD_array(2,1,"* MEDIDOR DE RPM *");
LCD_array(4,1,"* **** *");
__delay_ms(2000);
LCD_command(CLEAR);
LCD_array(2,1,"* REV POR MINUTO *");
LCD_array(1,1,"* **** *");
LCD_array(3,1,"* *");
LCD_array(4,1,"* **** *");
while(1)
{
char buffer[10];
//Carga el valor de rpm en una cadena de texto
sprintf(buffer,"%4u",(int)RPM_read());
LCD_array(3,8,buffer); //Imprime valor de rpm(entero)
__delay_ms(1000);
}
return;
}
/*******************************************************************************
| CLASS: Desarrollo
| PROGRAM: LCD_RPM
| AUTHOR: Agustin; Lautaro
| DESCRIPTION: Lee las revoluciones por minutos de una determ. frecuencia,
| mediante las interrupciones por RB0 con flanco ascendente.
| REQUIREMENTS: Ingreso de pulsos por entra RB0
| ADDITIONAL: Valor flotante "%(cant enteros).(cant decimales)f","sin (int)"
|
*******************************************************************************/
RPM.H :
#include <xc.h>
#include <stdint.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
/*------------------------------------------------------------------------------
FUNCTION PROTOTYPES
-----------------------------------------------------------------------------*/
void RPM_init(void);
float RPM_read(void);
void interrupt ventana(void);
RPM.C :
#include "RPM.h"
/*------------------------------------------------------------------------------
VARIABLE DECLARATIONS GLOBAL
------------------------------------------------------------------------------*/
bit pulso=0; //Detecta cuando se produce el primer y segundo pulso por RB0
bit flag=0;
unsigned int T1=0,T2=0;
/*========================================================================
FUNCTION: RPM_init()
DESCRIPTION: Inicializa los registros y configuraciones necesarios
PARAMETERS: Ninguno
RETURNS: Nada
REQUIREMENTS: Ingreso de pulso por RB0
========================================================================*/
void RPM_init(void)
{
//Configuracion de Puertos
TRISBbits.TRISB0 = 1;
//Configuracion de timer 1 como contador de oscilador interno
T1CONbits.T1CKPS1 = 1; //Preescaler en 1:8
T1CONbits.T1CKPS0 = 1; //Preescaler en 1:8
T1CONbits.TMR1CS = 0; //Reloj interno/4
T1CONbits.TMR1ON = 1; //Hablita timer1
//Configuracion de interrupcion por RB0
INTCONbits.INTE = 1; //Habilita interrupcion por RB0
INTEDG = 1; //Por flanco ascendente
INTF = 0; //Bandera en 0
}
/*========================================================================
FUNCTION: RPM_read()
DESCRIPTION: Genera el valor de frecuencia y rpm
PARAMETERS: Ninguno
RETURNS: Flotante --> variable rpm
REQUIREMENTS: Ninguno
========================================================================*/
float RPM_read(void)
{
/*-----------------------------------------------------------------------
VARIABLE DECLARATIONS
-----------------------------------------------------------------------*/
float freq=0,rpm=0;
TMR1IF = 1;
//Habilita interrupcion global
INTCONbits.GIE = 1;
while(flag == 0);
//Calcula la frecuencia y la transforma en rpm
freq = 1/((T2-T1) * 0.000008); //Calcula la frecuencia de los pulsos
rpm = freq * 60; //Calcula los rpm
//Devuelve el valor de rpm
return rpm;
}
/*========================================================================
FUNCTION: ventana()
DESCRIPTION: Genera una ventana que depende de la frecuencia que ingresa
PARAMETERS: Ninguno
RETURNS: Nada
REQUIREMENTS: Ingreso de pulsos por RB0
========================================================================*/
void interrupt ventana(void)
{
char band = 0;
band = 0;
//Inicializa el timer1
if(TMR1IF == 1)
{
TMR1 = 0; //Inicia el timer1 en 0
T1 = TMR1;
TMR1IF = 0; //Inicia el timer1
}
//Guarda el valor de T1
if(pulso == 1)
{
//Guarda el valor del segundo flanco ascendente
TMR1ON = 0; //Detiene el timer1
T2 = TMR1; //Guarda el valor obtenido
INTCONbits.GIE = 0; //Deshabilita las interrupciones
TMR1 = 0;
TMR1IF = 1;
TMR1ON = 1;
pulso = 0;
band = 1;
flag = 1;
}
if(band == 0) pulso = 1;
INTF = 0;
}
/*******************************************************************************
| LIBRERIE: RPM.c
| DESCRIPTION: Lee las revoluciones por minutos de una determ. frecuencia,
| mediante las interrupciones por RB0 con flanco ascendente.
| REQUIREMENTS: Ingreso de pulsos por entra RB0
|
*******************************************************************************/
LIBRERIA LCD.H :
#include <xc.h>
#define _XTAL_FREQ 4000000
/*------------------------------------------------------------------------------
PROGRAM DEFINES
-----------------------------------------------------------------------------*/
#ifndef LCD_16X2
#define LCD_16X2 0x01
//Configuraciones de pines
#define RS_PIN PORTDbits.RD1
#define RS_TRIS TRISDbits.TRISD1
#define RW_PIN PORTDbits.RD2
#define RW_TRIS TRISDbits.TRISD2
#define E_PIN PORTDbits.RD3
#define E_TRIS TRISDbits.TRISD3
#define BITS_PIN PORTD
#define BITS_TRIS TRISD
//Funciones del lcd
#define CLEAR 0x01 //Limpiar el display
#define CURSOR_OFF 0x0C //Desactiva el cursor
#define CURSOR_ON 0x0E //Actva el cursor solo
#define CURSOR_BLINK_ON 0x0F //Activa el cursor y el destello
#define HOME 0x02 //Vuelve a la posicion home 0,0
#define DISPLAY_RIGHT 0x1C //Corrimiento de pantalla a la derecha
#define DISPLAY_LEFT 0x18 //Corrimiento de pantalla a la izquierda
#define CURSOR_RIGHT 0x14 //Movimiento del cursor a la derecha
#define CURSOR_LEFT 0x10 //Movimiento del cursor a la izquierda
#define PRIMERA_FILA 0x02
#define SEGUNDA_FILA 0xC0
#define TERCERA_FILA 0x94
#define CUARTA_FILA 0xD4
//Generacion de caracter
#define CARACTER_POS0 0x00 //Caracter posicion 0
#define CARACTER_POS1 0x01 //Caracter posicion 1
#define CARACTER_POS2 0x02 //Caracter posicion 2
#define CARACTER_POS3 0x03 //Caracter posicion 3
#define CARACTER_POS4 0x04 //Caracter posicion 4
#define CARACTER_POS5 0x05 //Caracter posicion 5
#define CARACTER_POS6 0x06 //Caracter posicion 6
#define CARACTER_POS7 0x07 //Caracter posicion 7
//Generacion de numero grandes
#define LCD_20X4 0x02 //Numero grandes para Lcd 20x4
#define JUST_RIGHT 0x10 //Numeros con justificacion derecha de la pantalla
#define JUST_LEFT 0x11 //Numeros con justificacion izquierda de la pantalla
#endif
/*------------------------------------------------------------------------------
FUNCTION PROTOTYPES
-----------------------------------------------------------------------------*/
void LCD_init(void);
void LCD_command(unsigned char cmd);
void LCD_array(int x,int y,const char *date);
void LCD_xy(int x,int y);
void LCD_date(char date);
void LCD_E(void);
void LCD_shift(unsigned char dir,unsigned char cant);
void LCD_character(unsigned char adress,char caracter[]);
void LCD_numerogrande(int valor);
LIBRERIA LCD.C :
#include "LCD_control.h"
//********************************************************************************
//Esta funcion inicializa el lcd con sus configuraciones; Debe utilizarse primero*
//********************************************************************************
void LCD_init(void)
{
//Tiempo de inicilizacion
__delay_ms(20);
for(char i=0;i<3;i++)
{
LCD_command(0x03); //Recomendado para inicializar el controlador
__delay_ms(5);
}
//Configuraciones del LCD 16x2
LCD_command(0x33); //Inicializa el controlador
__delay_us(100);
LCD_command(0x32); //Modo de 4 bits
__delay_ms(5);
LCD_command(0x28); //Modo 4 bits,2 lineas y fuente de 5x7
__delay_us(100);
LCD_command(0x0C);
__delay_us(100);
LCD_command(0x06);
__delay_us(100);
LCD_command(CLEAR); //Limpia la pantalla
__delay_ms(3);
return;
}
//********************************************************************************
//Esta funcion permite ingresar un comando al lcd; LCD_command(CLEAR);************
//********************************************************************************
void LCD_command(unsigned char cmd)
{
//Salidas en 0
BITS_TRIS &= 0x00; //Pone todo el puerto como salida,para poder escribir en el lcd
//Escribe los comandos
BITS_PIN &= 0x00; //Limpiar el puerto
BITS_PIN |= (cmd & 0xF0); //Envia el MSB del comando
LCD_E(); //Habilita el lcd para poder guardar los datos
BITS_PIN &= 0x00; //Limpia el puerto
BITS_PIN |= (cmd<<4 & 0xF0); //Envia el LSB del comando
LCD_E(); //Habilita el lcd para poder guardar los datos
BITS_TRIS &= 0xF0; //Vuelve a poner como entrada
__delay_ms(2);
return;
}
//********************************************************************************
//Esta funcion permite enviar los datos al lcd, para poder visalizar la letra*****
//********************************************************************************
void LCD_date(char date)
{
//Setea las configuraciones para poder escribir
BITS_TRIS &= 0x00; //Modo de salida
//Envia el dato
BITS_PIN &= 0x00; //Limpia el puerto
BITS_PIN |= (date & 0xF0); //Envia MSB
RS_PIN = 1; //Modo de escritura
LCD_E(); //Habilita los datos
BITS_PIN &= 0x00; //Limpiar el puerto
BITS_PIN |= (date<<4 & 0xF0); //Enviar LSB
RS_PIN = 1; //Modo de escritura
LCD_E(); //Habilita los datos
BITS_TRIS &= 0xF0; //Modo de entrada
__delay_ms(2);
return;
}
//********************************************************************************
//Esta funcion permite enviar el dato al lcd**************************************
//********************************************************************************
void LCD_E(void)
{
E_PIN = 1;
__delay_us(5);
E_PIN = 0;
__delay_us(5);
}
//********************************************************************************
//Esta funcion permite enviar una candena de caracteres***************************
//********************************************************************************
void LCD_array(int x,int y,const char *date)
{
//Ubica el lcd
switch(x)
{
case 1: LCD_command(0x80 | (0x00 + (y - 1)));
break;
case 2: LCD_command(0x80 | (0x40 + (y - 1)));
break;
case 3: LCD_command(0x80 | (0x14 + (y - 1)));
break;
case 4: LCD_command(0x80 | (0x54 + (y - 1)));
break;
}
//Envia la cadena
while(*date)
{
LCD_date(*date);
__delay_us(100);
date++;
}
}
//********************************************************************************
//Esta funcion permite ubicar en un lugar el lcd**********************************
//********************************************************************************
void LCD_xy(int x,int y)
{
switch(x)
{
case 1: LCD_command(0x80 | (0x00 + (y - 1)));
break;
case 2: LCD_command(0x80 | (0x40 + (y - 1)));
break;
case 3: LCD_command(0x80 | (0x14 + (y - 1)));
break;
case 4: LCD_command(0x80 | (0x54 + (y - 1)));
break;
}
}
//*********************************************************************************
//Esta funcion realiza un corrimiento de pantalla; El 10 representa la cantidad de*
//veces que se va a correr la pantalla*********************************************
void LCD_shift(unsigned char dir,unsigned char cant)
{
char i=1;
//Realiza el corrimiento de pantalla
while(i <= cant)
{
LCD_command(dir);
__delay_ms(250);
i++;
}
LCD_command(HOME); //Vuelve a la posicion inicial
i = 1;
}
//********************************************************************************
//Esta funcion genera un caracter que no se encuentra en la lista del lcd*********
//********************************************************************************
void LCD_character(unsigned char adress,char caracter[])
{
LCD_command(0x40 + (adress * 8));
for(char i=0;i<8;i++)
{
LCD_date(caracter[i]);
}
}
/*Ejemplo de uso de la funcion de creacion de caracter:
*char caracter1[8] =
{
0b00000000,
0b00001010,
0b00001010,
0b00001010,
0b00001010,
0b00010001,
0b00001110,
0b00000000,
};
LCD_command(CLEAR);
LCD_caracter(CARACTER_POS0,caracter1);
LCD_xy(0,0);
LCD_date(CARACTER_POS0);
__delay_ms(1000);
*/
FIN PROGRAMA.
No hay comentarios.:
Publicar un comentario