TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: zoolander36 en 22 de Febrero de 2010, 19:28:01
-
Hola, soy nuevo por aquí pero he seguido mucho este foro.
Estoy realizando un proyecto y ando muy atascado con la programación del PIC. Yo estudié en la Universidad en lenguaje ASM pero a la hora de hacer este proyecto decidí hacerlo en C debido al uso de decimales y otras cosas muy complejas de hacer en ASM.
Mi proyecto se trata de la medición de caudal de agua mediant fibra óptica, utilizando para ello un led que emite luz infrarroja y un fotodiodo que recibe dicha luz y la transforma en corriente eléctrica.
Para la medición del caudal utilizo una helice que corta el haz de luz y hace que el circuito emita pulsos, se genera una señal de tipo alterna creando flancos de subida y bajada.
Mi problema viene al utilizar esos flancos para mediante el pic16f877 determinar el caudal de agua y enseñarlo por un display 1x16.
Llevo varios días con la programación en PICC y simulación en Proteus pero no consigo que me muestre nada en el display en la simulación, a ver si alguien puede ayudarme por favor, estoy muy perdido.
----------------------------------------------------------------------------------------------------------------------
#include<16f877.h>
#use delay(clock=8000000)
#define use_portb_lcd TRUE
#fuses HS,xt,noprotect,nowdt,nolvp
#include <lcd.c>
#BYTE PORTA=5
#define LCD_ENABLE_PIN PIN_B2 ////
#define LCD_RS_PIN PIN_B0 ////
#define LCD_RW_PIN PIN_B1 ////
#define LCD_DATA0 PIN_D1 ////
#define LCD_DATA1 PIN_D2 ////
#define LCD_DATA2 PIN_D3 ////
#define LCD_DATA3 PIN_D4
const int cte=218;
void main()
{
lcd_init();
printf(lcd_putc," \n Medición de caudal");
while(true)
{
float frec;
float caudal;
//////////////////// configuracion de puertos //////////////////////////////////
set_tris_d(0b11111111);
set_trs_b(0x00);
set_tris_a(0x00);
while (!input(PIN_A5))
{
setup_timer_1 ( T1_EXTERNAL );
for (;!input(PIN_A5);)
{
frec=get_timer1();
caudal=cte*frec;
lcd_init();
printf(lcd_putc,"FREC. \n Hz %f ",caudal);
set_timer1(0);
}
}
}}
Muchas gracias.
-
porque no leeis un poco?? si casi todo esta en el foro
Click, Click. (http://www.todopic.com.ar/foros/index.php?topic=14427.0)
-
Los defines de los pines a utilizar por el LCD deben estar antes de incluir la librería. Igualmente utiliza el buscador, hay bastante información sobre los LCD.
Saludos!
-
Hola.
En los #fuses tienes HS y XT, debe ser solo HS.
La inicializacion de la lcd, solo la debes hacer una vez.
Debe ser con fibra óptica? Sería mas sencillo el montaje si en la hélice se pone un imán y se capta los pulsos del B con un sensor de efecto Hall.
Saludos
-
Gracias a todos por las respuestas.
MLO_ el proyecto tiene que ser utilizando fibra óptica pero esa parte está ya fabricada y ya pondré como se ha construido cuando acabe todo el proyecto.
Voy a probar lo que me habeis comentado.
Gracias.
-
Bueno, he revisado los consejos que me disteis y he cambiado una cosas en el programa pero aún no consigo que funcione la simulación, no se donde anda el fallo porque en la simulación paso a paso veo que el PIC recorre el programa pero no lo saca por la pantalla de la LCD.
Aqui pongo el código nuevo (He usado el programa de medición de pulsos completos que hizo RedPic)
#include<16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000)
#define use_portd_lcd TRUE
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA0 PIN_D3
#define LCD_DATA1 PIN_D4
#define LCD_DATA2 PIN_D5
#define LCD_DATA3 PIN_D6
#include <lcd.c>
const int cte=0.218;
int8 numFlancoQueLlega=0; // Número de Flanco que llega
int1 flagToggleFlanco=0; // Flag para cambiar de flanco
int16 t1=0x00,t2=0x00,t3=0x00; // Variables para guardar estados de ...
int16 tth=0x00,ttl=0x00,tt=0x00; // Timers y pulsos
float f=0.00; // Para hacer las restas oportunas en uS
int1 flagHayDatos=0; // Flag para indicar que ya hay datos de ..
// dos flancos (de subida y bajada)
void main()
{
float caudal;
set_tris_d(0x00);
set_tris_b(0xff);
ext_int_edge(L_TO_H);
flagToggleFlanco = 0; // inicializo el Flag para cambiar de flanco
enable_interrupts(int_ext);
enable_interrupts(global);
lcd_init();
lcd_putc("Medidor de caudal");
do {
if(flagHayDatos==1) // Detecto que ya hay datos de flancos ..
{
if((t3>t2)&&(t2>t1)) // Compruebo que estoy en la misma vuelta de TMR1
{
tth = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
ttl = t3 - t2; // Calculo en Tick's de TMR1 el tiempo en Bajo
tt = tth + ttl; // Calculo en Tick's de TMR1 el Periodo del Pulso
f = 1 / tt ; // Calculo la Frecuencia
}
flagHayDatos=0; // Indico que ya han sido procesados los datos.
}
caudal = f*cte;
lcd_putc(caudal);
} while(TRUE);
}
#int_ext
void handle_ext_int()
{
++numFlancoQueLlega; // Cuento flanco que nos llega
if(flagToggleFlanco==0)
{ // He recibido Flanco de Subida
if(numFlancoQueLlega==1)
{
set_timer1(0); // Reinicio TMR1
t1=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
}
if(numFlancoQueLlega==3)
{ t3=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
if(flagHayDatos==0)
{ // Si los datos anteriores han sido procesados ...
flagHayDatos=1; // Indico que ya hay nuevos datos de flancos para calcular
}
}
ext_int_edge(0,H_TO_L); // Configuro para capturar siguiente flanco de Bajada
flagToggleFlanco=1; // Indico que el siguiente flanco será de Bajada
}
else
{ // He recibido Flanco de Bajada
t2=get_timer1(); // Guardo en t2 el valor de TMR1 al Flanco de Bajada
ext_int_edge(0,L_TO_H); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco=0; // Indico que el siguiente flanco será de Subida
}
}
Añado también un imagen del circuito en Proteus.
-
Bueno, después de hacer unos cambios en la rutina lcd.c y un par de cosilla más logré que me empiece a mostrar algo por el display, como el mensaje de encendido y el mensaje en que iría la medida pero parece que no me hace correctamente la rutina de medir los pulsos porque me pone siempre 0.00. :(
Si alguien me hiciera el favor de ver donde puede ser el fallo le estaría muy agradecido.
#include<16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000)
#define use_portd_lcd TRUE
#byte lcd_d = 8
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA0 PIN_D3
#define LCD_DATA1 PIN_D4
#define LCD_DATA2 PIN_D5
#define LCD_DATA3 PIN_D6
#define LCD_TYPE 2
#include <lcd.c>
#use standard_io(B)
#use standard_io(D)
const int cte=0.218;
int8 numFlancoQueLlega=0; // Número de Flanco que llega
int1 flagToggleFlanco=0; // Flag para cambiar de flanco
int16 t1=0x00,t2=0x00,t3=0x00; // Variables para guardar estados de ...
int16 tth=0x00,ttl=0x00,tt=0x00; // Timers y pulsos
float f=0.00; // Para hacer las restas oportunas en uS
int1 flagHayDatos=0; // Flag para indicar que ya hay datos de ..
// dos flancos (de subida y bajada)
void main()
{
float caudal;
set_tris_d(0x00);
set_tris_b(0xff);
ext_int_edge(L_TO_H);
flagToggleFlanco = 0; // inicializo el Flag para cambiar de flanco
numFlancoQueLLega = 0;
enable_interrupts(int_ext);
enable_interrupts(global);
lcd_init();
lcd_putc("Encendido ");
do {
if(flagHayDatos==1) // Detecto que ya hay datos de flancos ..
{
if((t3>t2)&&(t2>t1)) // Compruebo que estoy en la misma vuelta de TMR1
{
tth = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
ttl = t3 - t2; // Calculo en Tick's de TMR1 el tiempo en Bajo
tt = tth + ttl; // Calculo en Tick's de TMR1 el Periodo del Pulso
f = 1/tt ; // Calculo la Frecuencia
}
flagHayDatos=0; // Indico que ya han sido procesados los datos.
}
caudal = f*cte;
printf(lcd_putc,"%f m^3/seg",caudal);
delay_ms(100);
lcd_putc(" ");
} while(TRUE);
}
#int_ext
void handle_ext_int()
{
++numFlancoQueLlega; // Cuento flanco que nos llega
if(flagToggleFlanco==0)
{ // He recibido Flanco de Subida
if(numFlancoQueLlega==1)
{
set_timer1(0); // Reinicio TMR1
t1=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
}
if(numFlancoQueLlega==2)
{ t3=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
numFlancoQueLLega == 0;
if(flagHayDatos==0)
{ // Si los datos anteriores han sido procesados ...
flagHayDatos=1; // Indico que ya hay nuevos datos de flancos para calcular
}
}
ext_int_edge(0,H_TO_L); // Configuro para capturar siguiente flanco de Bajada
flagToggleFlanco=1; // Indico que el siguiente flanco será de Bajada
}
else
{ // He recibido Flanco de Bajada
t2=get_timer1(); // Guardo en t2 el valor de TMR1 al Flanco de Bajada
ext_int_edge(0,L_TO_H); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco=0; // Indico que el siguiente flanco será de Subida
}
}
-
Hola de nuevo, he descubierto que el programa no salta a la interrupción, la variable flagToggle toma valores extraños y los timer no cuentan nada.
Pido ayuda, estoy muy perdido. :(
-
Estás declarando la constante cte como int y le pones un valor en que no es entero, declaralo como float.
esta instrucción "numFlancoQueLLega == 0;"no debería ser:
numFlancoQueLLega = 0;
-
Bueno, un nuevo avance flagToggle ya va cambiando de estado, de 0 a 1 y viceversa pero numflanco no para de aumentar y no hace correctamente el ciclo. Pongo el código por si alguien pudiera echarme una manita. Mucas gracias a todos los que me estais ayudando
#include<16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000)
#define use_portd_lcd TRUE
#byte lcd_d = 8
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA0 PIN_D3
#define LCD_DATA1 PIN_D4
#define LCD_DATA2 PIN_D5
#define LCD_DATA3 PIN_D6
//#define LCD_TYPE 2
#include <lcd.c>
#use standard_io(B)
#use standard_io(D)
const float cte = 21.8;
int numFlancoQueLlega = 0 ; // Número de Flanco que llega
int flagToggleFlanco = 0 ; // Flag para cambiar de flanco
int t1=0x00,t2=0x00,t3=0x00; // Variables para guardar estados de ...
int tth=0x00,ttl=0x00,tt=0x00; // Timers y pulsos
float f;
int flagHayDatos = 0; // Flag para indicar que ya hay datos de ..
float caudal; // dos flancos (de subida y bajada)
#int_ext
void handle_ext_int()
{
++numFlancoQueLlega; // Cuento flanco que nos llega
if(flagToggleFlanco == 0)
{ // He recibido Flanco de Subida
if(numFlancoQueLlega == 1)
{
set_timer1(0); // Reinicio TMR1
t1=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
}
if(numFlancoQueLlega == 3)
{ t3=get_timer1();
numFlancoQueLlega = 0; // Guardo en t3 el valor de TMR1 al segundo Flanco de Subida
if(flagHayDatos == 0)
{ // Si los datos anteriores han sido procesados ...
flagHayDatos = 1; // Indico que ya hay nuevos datos de flancos para calcular
}
}
ext_int_edge(0,H_TO_L); // Configuro para capturar siguiente flanco de Bajada
flagToggleFlanco = 1; // Indico que el siguiente flanco será de Bajada
}
else
{ // He recibido Flanco de Bajada
t2=get_timer1(); // Guardo en t2 el valor de TMR1 al Flanco de Bajada
ext_int_edge(0,L_TO_H); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco = 0; // Indico que el siguiente flanco será de Subida
}
}
void main()
{
lcd_init();
lcd_putc("Encendido ");
delay_ms (333);
set_tris_d(0b00000000);
disable_interrupts(global);
disable_interrupts(int_ext);
flagToggleFlanco = 0;
flagHayDatos = 0;
ext_int_edge(0,L_TO_H);
enable_interrupts(int_ext);
enable_interrupts(global);
delay_ms(200);
do {
if(flagHayDatos == 1) // Detecto que ya hay datos de flancos ..
{
if((t3>t2)&&(t2>t1)) // Compruebo que estoy en la misma vuelta de TMR1
{
tth = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
ttl = t3 - t2; // Calculo en Tick's de TMR1 el tiempo en Bajo
tt = tth + ttl; // Calculo en Tick's de TMR1 el Periodo del Pulso
f = 1/tt ; // Calculo la Frecuencia
caudal = f*cte;
}
flagHayDatos=0; // Indico que ya han sido procesados los datos.
}
printf(lcd_putc,"%f m^3/seg",caudal);
delay_ms(100);
lcd_putc(" ");
} while(TRUE);
}
-
Lo que veo es que estás usando el timer1 pero no lo estás configurando en ningún momento por lo tanto siempre te va a dar un mismo valor. Debes usar "setup_timer_1" en el main.
Debes tener en cuenta que el timer1 es de 16bit.
-
Tienes razón pablo, ya lo arreglé pero ahora sigue sin contar el flanco t2 y numflanco sigue sin para de contar en vez de al llegar a 3 volver a ponerse a 0 y las variables th, tl y tt no reciben ningún dato.
Si alguien ve el problema por favor que me lo diga, llevo con este programa dos semanas y aún no consigo que funcione correctamente y estoy bastante desesperado.
#include<16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000)
#define use_portd_lcd TRUE
#byte lcd_d = 8
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA0 PIN_D3
#define LCD_DATA1 PIN_D4
#define LCD_DATA2 PIN_D5
#define LCD_DATA3 PIN_D6
//#define LCD_TYPE 2
#include <lcd.c>
#use standard_io(B)
#use standard_io(D)
const float cte = 21.8;
int numFlancoQueLlega = 0; // Número de Flanco que llega
int flagToggleFlanco=0; // Flag para cambiar de flanco
int t1=0x00,t2=0x00,t3=0x00; // Variables para guardar estados de ...
int tth=0x00,ttl=0x00,tt=0x00; // Timers y pulsos
float f;
int flagHayDatos =0; // Flag para indicar que ya hay datos de ..
float caudal; // dos flancos (de subida y bajada)
#int_ext
void handle_ext_int()
{
++numFlancoQueLlega; // Cuento flanco que nos llega
if(flagToggleFlanco == 0)
{ // He recibido Flanco de Subida
if(numFlancoQueLlega == 1)
{
set_timer1(0);
t1=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
}
if(numFlancoQueLlega == 3)
{
t3=get_timer1();
if(flagHayDatos == 0)
{ // Si los datos anteriores han sido procesados ...
flagHayDatos = 1; // Indico que ya hay nuevos datos de flancos para calcular
}
}
ext_int_edge(H_TO_L); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco = 0; // Indico que el siguiente flanco será de Subida
}
else
{ // He recibido Flanco de Bajada
t2=get_timer1(); // Guardo en t2 el valor de TMR1 al Flanco de Bajada
ext_int_edge(L_TO_H); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco=0; // Indico que el siguiente flanco será de Subida
}
}
void main()
{
delay_ms (333);
lcd_init();
lcd_putc("Encendido ");
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
disable_interrupts(global);
disable_interrupts(int_ext);
set_tris_d(0b00000000);
set_tris_b(0b11111111);
ext_int_edge(L_TO_H);
flagToggleFlanco = 0;
enable_interrupts(int_ext);
enable_interrupts(global);
delay_ms(200);
do {
if(flagHayDatos == 1) // Detecto que ya hay datos de flancos ..
{
if((t3>t2)&&(t2>t1)) // Compruebo que estoy en la misma vuelta de TMR1
{
tth = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
ttl = t3 - t2; // Calculo en Tick's de TMR1 el tiempo en Bajo
tt = tth + ttl; // Calculo en Tick's de TMR1 el Periodo del Pulso
f = 1/tt ; // Calculo la Frecuencia
caudal = f*cte;
}
flagHayDatos=0; // Indico que ya han sido procesados los datos.
}
printf(lcd_putc,"%f m^3/seg",caudal);
delay_ms(100);
lcd_putc(" ");
} while(TRUE);
}
-
puedes probar teniendo en cuenta solo los pulsos de subida, o solo los de bajada ya que en realidad:
tth = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
ttl = t3 - t2; // Calculo en Tick's de TMR1 el tiempo en Bajo
tt = tth + ttl;
con lo anterior haces lo que te comento pero con codigo
-
Bueno Pablo, ya me queda menos. Te hice caso y quité el pulso de bajada y solo cuento los de subida pero me he dado cuenta de que el programa no me salta a la parte del programa principal donde se calcula el caudal, así que la variable flagHaydatos está aumentando continuamente y no me hace ninguna cuenta.
Si alguien es tán amable de ayudarme le estaría muy agradecido.
#include<16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000)
#define use_portd_lcd TRUE
#byte lcd_d = 8
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA0 PIN_D3
#define LCD_DATA1 PIN_D4
#define LCD_DATA2 PIN_D5
#define LCD_DATA3 PIN_D6
//#define LCD_TYPE 2
#include <lcd.c>
#use standard_io(B)
#use standard_io(D)
const float cte = 21.8;
int numFlancoQueLlega = 0; // Número de Flanco que llega
int flagToggleFlanco=0; // Flag para cambiar de flanco
int t1=0x00,t2=0x00; // Variables para guardar estados de ...
int tt=0x00; // Timers y pulsos
float f;
int flagHayDatos =0; // Flag para indicar que ya hay datos de ..
float caudal; // dos flancos (de subida y bajada)
#int_ext
void handle_ext_int()
{
numFlancoQueLlega = numFlancoQueLlega + 1; // Cuento flanco que nos llega
if(flagToggleFlanco == 0)
{
if (numFlancoQueLlega == 1)
{ // He recibido Flanco de Subida
set_timer1(0);
t1=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
flagToggleFlanco = flagToggleFlanco + 1;
}
}
else
{ // He recibido Flanco de Bajada
t2=get_timer1(); // Guardo en t2 el valor de TMR1 al Flanco de Bajada
//ext_int_edge(L_TO_H); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco=0; // Indico que el siguiente flanco será de Subida
numFlancoQueLlega =0;
flagHayDatos=flagHayDatos+1;
}
}
void main()
{
delay_ms (333);
lcd_init();
lcd_putc("Encendido ");
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
disable_interrupts(global);
disable_interrupts(int_ext);
set_tris_d(0b00000000);
set_tris_b(0b11111111);
ext_int_edge(L_TO_H);
flagToggleFlanco = 0;
enable_interrupts(int_ext);
enable_interrupts(global);
delay_ms(200);
do {
if(flagHayDatos == 1) // Detecto que ya hay datos de flancos ..
{
tt = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
f = 1/tt ; // Calculo la Frecuencia
caudal = f*cte;
flagHayDatos=0; // Indico que ya han sido procesados los datos.
}
printf(lcd_putc,"%f m^3/seg",caudal);
delay_ms(100);
lcd_putc(" ");
} while(TRUE);
}
PD: Adjunto un foto del proteus del circuito que estoy realizando, por si le quieren echar un vistazo.
Un saludo y gracias
-
debes tener cuidado con los delay, ya que la interrupción salta en cualquier momento, y si estás dentro de un delay no hay manera de que calcules el caudal. El primer delay de inicio debes colocarlo antes de habilitar las interrupciones.
Con respecto al refresco del display solo lo haría si hay cambios en el valor de la variable caudal, sino lo dejo como está.