TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: quirogaareal en 08 de Junio de 2006, 08:43:59
-
Hola gente:
Como he publicado en ocasiones anteriores con respecto a un medidor de presión que estamos haciendo con otros muchachos, lo hago nuevmente.
En esta parte se me encargo el calibrador, este debe consistir en un botón para entrar al menú, otro botón que al presionarlo cuente en forma ascendente y otro en forma descendente. Todo a medida que cuenta debe quedar almacenado en un lugar de memoria (24lc256 en este caso).
Al encender el aparato y entrar en la parte de calibración debe estar el ultimo valor almacenado.
Lo he realizado y la interrupción del timer 0 pero como soy novato MUY NOVATO aun no se muy bien lo que estoy haciendo. Mis preguntas serian las siguientes.
1) si tuviera 2 memorias 24lc256 como hago para direccionarlas por soft, ya se que por hardware se hace cambiando las entradas A0 A1 A2 (gnd gnd gnd en este caso).o (0 0 0)
2) Me gustarían sugerencias como mejorarlos u optimizarlo
3) Aquí esta el programa y mas abajo para descargarlo.
#include <16f628.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
#use rs232(baud=9600, xmit=PIN_A2, rcv=PIN_A3) //manejo del RS232
#define EEPROM_SDA PIN_A1 //pines para...
#define EEPROM_SCL PIN_A0 //...manejo de eeprom 24LC256
#include <24256.c> //libreria eeprom 24LC256
//DECLARACION VARIABLES GLOBALES
int i;//digito para almacenar los valores
BYTE datofijo;
#INT_TIMER0
///LLAMADA FUNCION INTERRUPCION
void interrupcion( )
{
disable_interrupts(global); //apago interrupcion
for(;;)
{
i=read_ext_eeprom(0x00);
if(!input(PIN_A2))// para entrar al menu de calibracion
{
lcd_putc("\f");
lcd_putc("CALIBRACION.....");
delay_ms(250);
lcd_putc("\f");
printf(lcd_putc,"PRESS(UP/DOWN)..\n%3u",i);
delay_ms(250);
}while(!input(PIN_A2));//evito rebotes o que se haga mientras este apretado
if(!input(PIN_A3)) //para ello leemos el estado del pin A1
//del porta para conteo ascendente
{
delay_ms(100);
do
{
i++; //decremento contador para visualizar siguiente digito
if(i>=250) i=250;//¿ya se ha mostrado el digito 250?
//SI -> entonces no avanza mas
datofijo=i;
lcd_gotoxy(1,2);
printf(lcd_putc,"%u",i);
delay_ms(100);
write_ext_eeprom(0x00,datofijo);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en dato fijo
}while(!input(PIN_A3));
}
datofijo=read_ext_eeprom(0x00);//almaceno en dato fijo lo que esta en memoria
if(!input(PIN_A4)) //para ello leemos el estado del pin A1
//del porta para conteo descendente
{
do
{
i--; //decremento contador para visualizar siguiente digito
if(i==-1) i=0;//¿ya se ha mostrado el digito 0?//SI -> vuelve a empezar(digito 9)
datofijo=i;
lcd_gotoxy(1,2);
printf(lcd_putc,"%u",i);//imprimo entero sin signoi para poder pasar de 128
delay_ms(100);
write_ext_eeprom(0x00,datofijo);
}while(!input(PIN_A4));
}
datofijo=read_ext_eeprom(0x00);
}
set_timer0(0 ); //carga TMR0
enable_interrupts(global); //activo interrupcion nuevamente
}
///PROGRAMA
void main()
{
lcd_init( ); //inicializamos lcd
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
enable_interrupts(GLOBAL); //activadas interrupciones
init_ext_eeprom( );
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
while(TRUE);//bucle infinito
}
:-/
-
Me auto respondo :
ENcontre en otra poarte del foro una problematica similar con respecto a memoria , y dice que hay que programarla con instrucciones i2c . Sera cuestion de ponerse y nada mas.
-
Hola quirogaareal, la combinación que uses en los pines A0 A1 A2 del 24LC256 tambien debes intoducirla en el codigo de instruccion que le envias a la memoria para controlarla, de esa manera puedes controlar varias memorias I2C que esten con el mismo lazo de conexión. Si buscas el datasheet de tal memoria tendras explicado todo muy claramente.
Un saludo.
Atte. CARLOS.
-
Gracias Carlos por responder.
Ahora:
He modificado el soft y tengo el inconveniente que cuando presiono el pulsador de conteo descendente para que se almacene el valor en memoria y este pasa de 100 a 99 y mas abajo aun me imprime en el lcd mal la representacion numerica. :(
Alguien podria decirme porque?
Aqui les pongo el codigo :-/
#include <16f628.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
#use rs232(baud=9600, xmit=PIN_A2, rcv=PIN_A3) //manejo del RS232
#define EEPROM_SDA PIN_A1 //pines para...
#define EEPROM_SCL PIN_A0 //...manejo de eeprom 24LC256
#include <24256.c> //libreria eeprom 24LC256
//DECLARACION VARIABLES GLOBALES
int i=0;//digito para almacenar los valores
//BYTE datofijo;
#INT_TIMER0
///LLAMADA FUNCION INTERRUPCION
void interrupcion( )
{
disable_interrupts(global); //apago interrupcion
i=read_ext_eeprom(0x00);
if(!input(PIN_A3)) //para ello leemos el estado del pin A2
//del porta para conteo ascendente
{
do
{
i++; //decremento contador para visualizar siguiente digito
if(i>=250) i=250;//¿ya se ha mostrado el digito 250?
//SI -> entonces no avanza mas
lcd_gotoxy(1,2);
printf(lcd_putc,"%u",i);
delay_ms(50);
write_ext_eeprom(0x00,i);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en i
}while(!input(PIN_A3));
}
i=read_ext_eeprom(0x00);//almaceno en i lo que esta en memoria
if(!input(PIN_A4)) //para ello leemos el estado del pin A1
//del porta para conteo descendente
{
do
{
i--; //decremento contador para visualizar siguiente digito
if(i==-1)
i=0;//¿ya se ha mostrado el digito 0?//SI -> vuelve a empezar(digito 9)
lcd_gotoxy(1,2);
printf(lcd_putc,"%u",i);//imprimo entero sin signoi para poder pasar de 128
delay_ms(50);
write_ext_eeprom(0x00,i);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en i
}while(!input(PIN_A4));
}
i=read_ext_eeprom(0x00);//almaceno en i lo que esta en memoria
enable_interrupts(global); //activo interrupcion nuevamente
}
///PROGRAMA
void main()
{
lcd_init( ); //inicializamos lcd
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
do
{
if(!input(PIN_A2))
{
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
enable_interrupts(GLOBAL); //activadas interrupciones
init_ext_eeprom( );
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
lcd_putc("\f");
lcd_putc("CALIBRACION.....");
delay_ms(500);
lcd_putc("\f");
printf(lcd_putc,"PRESS(UP/DOWN)..\n%u",i);
delay_ms(150);
}
}
while(true);//bucle infinito
}
-
Te esta dejando los digitos ultimos en el LCD. Por ejemplo al pasar de 100 a 99 te deja el ultimo cero. apareciendo: 990. La solucion es sacar los numeros con formato de la siguiente forma:
printf(lcd_putc,"%04u",i);
Esto imprime el numero poniendo los ceros que sean necesarios por delante hasta completar cuatro digitos.
Saludos
-
Gracias jfh900 por responder.
Suponia que era algo de eso pero aun estoy medio verde con el tema.
Ayer con mi amigo ya logramos mostrar presiones a travez del display . pero se nos presento el inconveniente de como mostrar presiones negativas ya que el conversor no responde ante tensiones negativas que te tira el sensor.
Al principiio estabamos usando solo una entrada , pero ahora vamos a usar 2 entradas del pcf 9591 y la 2da entrada es atravez de un inversor de ganancia 1 asi se entra al convesor con tension positiva.
Esta es la otra parte del programa que por ahora muestra el valor de presion positiva. Esto es lo que hemos avanzado hasta ayer, de lo que se avance durante la semana lo publicare y consultare mis dudas y aceptare sus sugerencias.
////////////////////////////////////////////////////////////////////////////////////
//
// 11/junio/06 - Vacuometro(hasta ahora)
//
// Programa: Manejo del dispositivo PCF8591 en modo A/D
// Version: 0.0
//
// Dispositivo: PIC 16F84A Compilador: CCS vs3.245
// Entorno IDE: MPLAB IDE v7.31 Simulador: Proteus 6.7sp3
//
// Notas: Este programa muestra como usar el conversor pfc8591 como adc.
// La Vref es de 2,56v por lo tanto la resolucion del conversor es 10mV.
// Básicamente lo que aquí hacemos es inicializar el conversor con la palabra
// de configuración y luego sólo resta leer (obviamente estamos modificando la
// tención analógica de entrada) sólo nos resta corregir un ligero error que es
// el que apenas pasa el valor de 128 en que se muestra valor negativo.
// Se muestra por pantalla de lcd(LM016L)
//
//
// Conexiones: RA1 -> SDA pcf8591
// RA0 -> SCL pcf8591
//
// lcd(LM016L)
// B0 -> E
// B1 -> RS
// B2 -> RW
// B4 -> D4
// B5 -> D5
// B6 -> D6
// B7 -> D7
// VSS y VEE -> gnd
// VDD ->VCC
//
// pcf8591
// A0,A1,A2.EXT , AGND ->gnd
// AN0,AN1,AN2,AN3 divisor resistivo con potenciometro (2.5v Variables)
// VREF=2.56 (en est6e caso)(pin14) divisor resistivo con potenciometro
//
//
//////////////////////////////////////////////////////////////////////////////////
/******************************************************/
/********** Programa Medidor de Presion con 16f628 ***/
/******************************************************/
#include <16f628.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,noPUT,nolvp//,intrc//ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
#define PCF8591_SCL PIN_A0 //definicion de pines...
#define PCF8591_SDA PIN_A1 //...de manejo del pcf8591
#include <vs_pcf8591.c> //libreria pcf8591
#use rs232(baud=9600, xmit=PIN_A2, rcv=PIN_A3) //manejo del RS232
int dato;
float variable,variable1;
#INT_TIMER0
///LLAMADA FUNCION INTERRUPCION
void interrupcion( )
{
dato=read_adc_value( ); //lee del pcf8591
variable=(float)dato*(-0.004563);
variable1=(float)variable*760;
lcd_gotoxy(1,1);
printf(lcd_putc,"P:%1.2f Bar \nP:%1.2f mmHg ",variable,variable1); //muestra por lcd
/*
if (dato!=V1)
{
printf("\b\b\b\b\b\b\b\b\b\b\bV1=%d.%d BAR",dato/100,(dato-(dato/100)*100));
v1=dato;
} //a una forma de representar con enteros
//con esta parte se imprime en El puerto serial (RS232)
*/
set_timer0(0 ); //carga TMR0
}
///PROGRAMA
void main(void)
{
lcd_init( ); //inicializamos lcd
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
lcd_putc("\f");
puts( " ---------------- " );
puts( " | Medidor |\r | de | \r | Presion. |" );
puts( " ---------------- \r\r\r\r\r\r\r\r\r\r\r\r\r" );
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
enable_interrupts(GLOBAL); //activadas interrupciones
pcf8591_adc_init(0b00000000); //inicializamos pcf8591
while(TRUE);//bucle infinito
}
que es lo que tengo que ver esta semana?
1)bo ver como hacer que si el dispositivo no se usa o no se detecta ninguna actividad mas o menos en 3/4 minutos se apague o entre en modalidad bajo consumo.
2)si mantengo el encendido apretado unos 15 seg(mas o menos , no tiene porque ser execto) entro al modo calibracion , que ya publicada una preliminar del calibrador mas arriba o en dia anteriores.
3)si presiono otra tecla ya vere como lo hago capturo el ultimo valor leido , eso por si tengo magueras cortas o estoy en una posicion incomoda para ver cuanto de presion hay .
Por si alguien tiene dudas de que sensor estamos usando , no lo sabemos porque mi amigo que trabaja en electromedicina lo saco de una maquina que ya no se usaba y no tiene ningun tipo de escritura.
pero este(me refiero al sensor) trabaja com +-1bar de presion , aunque aun seguimos buscando un sesr que mida dicha presion y este trabajando dentro de los 5V en alimentacion y por supuesto valores menores a ese cde tension que tire cuando se aplique presion.
Ya voy a ir aclarando puntos a medida que los vayamos resolviendo o que me vayan preguntando
Saludos desde Cordoba Argentina
-
Hola gente:
Continuando con el proyecto del medidor de presión, no se dado eso hay novato como ya es reconocido en otras ocasiones, si he interpretado bien el uso de interrupciones.
Aquí les adjunto el circuito, y el programa actualizados.
#include <16f628.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
//#use rs232(baud=9600, xmit=PIN_A2, rcv=PIN_A3) //manejo del RS232
#define PCF8591_SCL PIN_A0 //definicion de pines...
#define PCF8591_SDA PIN_A1 //...de manejo del pcf8591
#include <vs_pcf8591.c> //libreria pcf8591
#define EEPROM_SDA PIN_A1 //pines para...
#define EEPROM_SCL PIN_A0 //...manejo de eeprom 24LC256
#include <24256.c> //libreria eeprom 24LC256
//DECLARACION VARIABLES GLOBALES
int i=0,conteo,dato;//digito para almacenar los valores
float variable,variable1;
//BYTE datofijo;
#INT_TIMER0
///LLAMADA FUNCION INTERRUPCION
void interrupcion( )
{
disable_interrupts(global); //apago interrupcion
i=read_ext_eeprom(0x00);
if(!input(PIN_A3)) //para ello leemos el estado del pin A2
//del porta para conteo ascendente
{
do
{
i++; //decremento contador para visualizar siguiente digito
if(i>=250) i=250;//¿ya se ha mostrado el digito 250?
//SI -> entonces no avanza mas
lcd_gotoxy(1,2);
printf(lcd_putc,"%03u",i);
delay_ms(50);
write_ext_eeprom(0x00,i);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en i
conteo=250;
}while(!input(PIN_A3));
}
i=read_ext_eeprom(0x00);//almaceno en i lo que esta en memoria
if(!input(PIN_A4)) //para ello leemos el estado del pin A1
//del porta para conteo descendente
{
do
{
i--; //decremento contador para visualizar siguiente digito
if(i==-1)
i=0;//¿ya se ha mostrado el digito 0?//SI -> se queda ahi
lcd_gotoxy(1,2);
printf(lcd_putc,"%03u",i);//imprimo entero sin signoi para poder pasar de 128
delay_ms(50);
write_ext_eeprom(0x00,i);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en i
conteo=250;
}while(!input(PIN_A4));
}
i=read_ext_eeprom(0x00);//almaceno en i lo que esta en memoria
enable_interrupts(global); //activo interrupcion nuevamente
}
#int_TIMER1
TIMER1_isr()
{
disable_interrupts(global); //apago interrupcion
dato=read_adc_value( ); //lee del pcf8591
variable=(float)dato*(-0.004563);
variable1=(float)variable*760;
lcd_putc("\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"P:%1.2f Bar \nP:%1.2f mmHg ",variable,variable1); //muestra por lcd
delay_ms(1000);
enable_interrupts(global); //activo interrupcion nuevamente
}
///PROGRAMA
void main()
{
enable_interrupts(GLOBAL); //activadas interrupciones
lcd_init( ); //inicializamos lcd
init_ext_eeprom( );
do
{
if(!input(PIN_A2))
{
conteo=250;
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
enable_interrupts(INT_TIMER1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
set_timer1(0);
pcf8591_adc_init(0b00000100); //inicializamos pcf8591 en modo auto incremento
do{
conteo--;
lcd_putc("\f");
printf(lcd_putc,"%02u",conteo);
delay_ms(50);
if(conteo==0) sleep();
}while(!input(PIN_A2));
}
}while(true);//bucle infinito
do
{
if(!input(PIN_A3)&& !input(PIN_A4))
{
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
lcd_putc("\f");
lcd_putc("CALIBRACION.....");
delay_ms(500);
lcd_putc("\f");
printf(lcd_putc,"PRESS(UP/DOWN)..\n%u",i);
delay_ms(150);
do{
conteo--;
lcd_putc("\f");
printf(lcd_putc,"%02u",conteo);
delay_ms(50);
if(conteo==0) sleep();
}while(!input(PIN_A3)&& !input(PIN_A4));
}
}while(true);//bucle infinito
sleep();
}
Uno) quiero lograr que cuando presione la tecla A2 se encienda el aparato, si no se realiza ninguna actividad por unos tantos minutos por ejemplo tres minutos, éste (me refiero al aparato) entre en modo de bajo consumo.
Dos) quiero lograr que cuando presione las teclas A3 y A4 entre en modo calibración (como Explique en anteriores ocasiones esto es para qué cuando uno encienda el aparato y este sin ningún tipo de entrada depresión, me refiero a la presión atmosférica, se tome esta como referencia cero y con el calibrador ponerla a cero).
Tres) 1000 ya hemos logrado una constante que al multiplicar la por el dato del conversor, se muestre aproximadamente correcta en valor en pantalla, pero en este caso solamente estamos usando dos entradas del conversor, así que yo active auto incremento, pero evidentemente cuando mandó imprimir (supongo que será por la forma en la que imprimó) me muestra todo los valores y yo sólo quiero que me muestre los valores del entrada uno y dos del conversor) (usamos una de sus entradas para mostrar la presión positiva y la otra de sus entradas para mostrar la presión negativa, ahí le adjunta de un circuito de cómo se veía implementado en la vida real, aún está en montaje mas adelante le adjuntare el circuito).
Si pueden ayudarme ...
Saludos desde Córdoba Argentina
-
Hola gente :
Aqui esta el progreso logrado hasta el dia 14 de junio.
Por supuesto que falta mucho todavia. :-/
#include <16f628.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
//#use rs232(baud=9600, xmit=PIN_A2, rcv=PIN_A3) //manejo del RS232
#define PCF8591_SCL PIN_A0 //definicion de pines...
#define PCF8591_SDA PIN_A1 //...de manejo del pcf8591
#include <vs_pcf8591.c> //libreria pcf8591
#define EEPROM_SDA PIN_A1 //pines para...
#define EEPROM_SCL PIN_A0 //...manejo de eeprom 24LC256
#include <24256.c> //libreria eeprom 24LC256
#priority timer1 /*le da prioridad a la interrupcion usada
por el medidor de presion*/
/******************************************************************/
//DECLARACION VARIABLES GLOBALES
int i=0,conteo,dato;//digito para almacenar los valores
float variable,variable1;
//BYTE datofijo;
/******************************************************************/
/*interrupcion usada por el calibrador********/
#INT_TIMER0
///LLAMADA FUNCION INTERRUPCION
void interrupcion( )
{
disable_interrupts(global); //apago interrupcion
if(!input(PIN_A3)) //para ello leemos el estado del pin A2
//del porta para conteo ascendente
{
lcd_putc("\f");
printf(lcd_putc,"PRESS(UP/DOWN)..\n%u",i);
do
{
i++; //decremento contador para visualizar siguiente digito
if(i>=250) i=250;//¿ya se ha mostrado el digito 250?
//SI -> entonces no avanza mas
lcd_gotoxy(1,2);
printf(lcd_putc,"%03u",i);
delay_ms(50);
write_ext_eeprom(0x00,i);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en i
conteo=250;
}while(!input(PIN_A3));
}
i=read_ext_eeprom(0x00);//almaceno en i lo que esta en memoria
if(!input(PIN_A4)) //para ello leemos el estado del pin A1
//del porta para conteo descendente
{
lcd_putc("\f");
printf(lcd_putc,"PRESS(UP/DOWN)..\n%u",i);
do
{
i--; //decremento contador para visualizar siguiente digito
if(i==-1)
i=0;//¿ya se ha mostrado el digito 0?//SI -> se queda ahi
lcd_gotoxy(1,2);
printf(lcd_putc,"%03u",i);//imprimo entero sin signoi para poder pasar de 128
delay_ms(50);
write_ext_eeprom(0x00,i);//escribo en la 1era posicion de memoria el
//valor que esta almacenado en i
conteo=250;
}while(!input(PIN_A4));
}
i=read_ext_eeprom(0x00);//almaceno en i lo que esta en memoria
set_timer0(0 );
enable_interrupts(global); //activo interrupcion nuevamente
}
/******************************************************************/
/******************************************************************/
/*interrupcion usada por el medidor de presion********/
//si mantenes apretado este pulsador te va convirtiendo la presion
//si lo suelta queda el valo fijo y puede usar el calibrador
//obviamente despues se canbiara po un interruptor de ser necesario
#int_TIMER1
TIMER1_isr()
{
disable_interrupts(global); //apago interrupcion
do{
pcf8591_adc_init(0b00000100); //inicializamos pcf8591 en modo auto incremento
dato=read_adc_value( ); //lee del pcf8591
variable=(float)dato*(0.004563);
variable1=(float)variable*760;
lcd_gotoxy(1,1);
printf(lcd_putc,"P:%1.2f Bar\nP:%1.2f mmHg ",variable,variable1); //muestra por lcd
delay_ms(600);
}while(!input(PIN_A2));
set_timer1(0);
enable_interrupts(global); //activo interrupcion nuevamente
}
/******************************************************************/
/******************************************************************/
///PROGRAMA PRINCIPAL
void main()
{
enable_interrupts(GLOBAL); //activadas interrupciones
lcd_init( ); //inicializamos lcd
init_ext_eeprom( );
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
enable_interrupts(INT_TIMER1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
set_timer1(0);//carga TMR0
lcd_putc("\f");
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
do
{
//si mantenes apretado este pulsador te va convirtiendo la presion
//si lo suelta queda el valo fijo y puede usar el calibrador
if(!input(PIN_A2))
{
conteo=250;
/*********esta parte a futuro para que si no se lo
usa por un tiempo se apague***********************/
/*do{
conteo--;
//lcd_putc("\f");
//printf(lcd_putc,"%02u",conteo);
delay_ms(50);
if(conteo==0) sleep();
}while(input(PIN_A2));
*/
/***************************************************/
}
/****************este es el calibrador***********/
/*si la presion no es 0 al encender el aparato y
estando a la presion atmosferica , la cual tomamos
como referencia con esto la ponemos a 0**********/
if(!input(PIN_A3)||!input(PIN_A4))
{
lcd_putc("\f");
conteo--;
lcd_putc("\f");
printf(lcd_putc,"%02u",conteo);
delay_ms(50);
if(conteo==0) sleep();
}
}
while(true);//bucle infinito
//sleep();/*****este todavia no se donde ponerlo para
/*si no se lo
usa por un tiempo se apague***********************/
}
//FIN PROGRAMA PRINCIPAL
/******************************************************************/
Ahi les adjunto el circuito en proteus. Masadelante les pondre como obtenemos la constante para visualizar la correcta presion. :shock:
-
Hola gente:
este sabado retrocedimos un poco en cuanto a soft (a una version anterior), y lo hemos hecho funcionar...en parte, vamos a cambiar el metodo de almacenar en eeprom externa y lo haremos en la interna del pic ya que no requeriremos gran cantidad de memoria.
ya publicare el avance un poquito mas adelante , ya que no fue demasiado este sabado.
-
Hola gente :):
Acá estamos de nuevo con el proyecto, no hay publicado en semanas anteriores dado que he estado trabajando, estábamos usando el micro controlador 16F628A, pero nos ha quedado chico así que tuvimos que saltar al 16F876, la placa en la cual probábamos el micro controlador estaba hecha para micro controladores más chicos, así que tuvimos que hacer una pequeña adaptación.
Y yo se que el pic 16F876 tiene un conversor analógico digital interno, pero dado que ya tenemos el Hardware de esa forma lo dejé así.
1) aquí le voy a dejar el programita para descargar, o sea el del lenguaje que C y el del proteus, este último tarda en empezar a simular así que tengan un poquito de paciencia, pero en lo que es hardware funcionar correctamente.
2) hemos usado varias direcciones internas del micro controlador, están especificadas en el mismo programa.
3) para hacer la calibración hacemos combinaciones de teclas, para la calibración positiva mantenemos presionado a A2 y para aumentar o disminuir el valor lo hacemos con A3 y A4.
Para hacer la calibración negativa mantenemos presionado A4 y subimos y bajamos con A2 y A3.
Para convertir el valor de presión ya sea a milímetros de mercurio o a PSI, el cual lo hacemos con el factor KU el cual multiplica en la presión final, para dicha conversión usamos la combinación de teclas A3 y con una instrucción case nos movemos a través de un menú apretando A2.
4) en esta instrucción valorN=dato*kn*ku*0.01; //Calculo el valor de Presion -calculamos el valor de presión negativa.
Es similar a la que usamos para calcular el valor de presión positiva. Dato es el valor que se usa para leer el valor del conversor K. N. es el valor que se usa para el cálculo de la presión negativa (en realidad es para cómo se lo muestra) KU es el valor que multiplicamos pará obtener, en realidad sería para convertir a diferentes valores de presión mmHg o PSI.
5) if (Pobinicial!=PobN) esta instrucción, que se usa al final de ya sea calibración u otras funciones, es debido a que por ejemplo cuando uno calibre y termina el de utilizar la combinación entre A2 A3 y A4, si el valor es distinto al que uno tenía (me refiero al valor de presión por supuesto) cuando unos suelta los botones de calibración lo que uno sigue viendo es el valor de calibración y no el de presión, entonces se hace un condicional, para qué si el valor de presión continúa siendo el que medimos y es igual al valor de calibración, que es el valor que queremos ver entonces sí lo imprime y lo escribe en memoria. Si no sigue mostrando el valor de presión estábamos viendo, evidentemente ya corregido o calibrado.
6) las funciones void cartel(int Pob) , void cartelN(int PobN) son sólo carteles de impresión, para ser un poquito menos enredado el programa o que sea más entendible.
7) la función void presiones(void) es la que se usa para la conversión de presión mmHg o PSI.
8) evidentemente no es la versión definitiva definitiva, pero se le acerca bastante, ya que funciona correctamente el hardware lo estamos estirando, con un manómetro.
9) en caso de que se cambiara el sensor, evidentemente que sea aproximadamente similar al que estamos usando, no habría grandes cambios en el soft.
Aquí va el programa.
////////////////////////////////////////////////////////////////////////////////////
//
// 8/07/06 - Medidor de presion!!! - p+ y p- y ademas posee tabla de conversion.
//
// Programa: Manejo del dispositivo PCF8591 en modo A/D
// Version: 0.0
//
// Dispositivo: PIC 16F628 Compilador: CCS vs3.245
// Entorno IDE: MPLAB IDE v7.31 Simulador: Proteus 6.7sp3
//
// Software con Modificaciones
//
//////////////////////////////////////////////////////////////////////////////////
/******************************************************/
/********** Programa Medidor de Presion con 16f628 ***/
/******************************************************/
#include <16f876.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT//,intrc//ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
#define PCF8591_SCL PIN_A0 //definicion de pines...
#define PCF8591_SDA PIN_A1 //...de manejo del pcf8591
#include <vs_pcf8591.c> //libreria pcf8591
//////////////////////////////////////////////////
//Posiciones de memorias en eeprom del pic usadas
//0x00 Lectura A0 del adc negativo
//0x01 Lectura A1 del adc positivo
//0x02 Kp
//0x03 Kn
//0x04 Pob
//0x05 copia dir 0x01
//0x06 PobN
//0x07 copiaN dir 0x00
//0x08 unidad de presion
////////////////////////////////////////
void calibracionP(void);
void calibracionN(void);
void cartel(int Pob);
void cartelN(int PobN);
void presiones(void);
void CartelU (int unidad);
#INT_TIMER0
interrupcion()
{
int dato;
dato=read_adc_value( ); //lee del pcf8591 pero no lo imprimo,
//esto se hace asi porque he activado el conversor en modo auto incremento
//y no se si es por la libreria o que empieza leyendo el ultimo valor o sea
//Ain3 luego sigue por Ain0, Ain1 y asi sucesivamente , pero en
//este caso uso solo 2 entradas , una para valores positivos y otra para valores
//negativos de presion que son los que imprimo en el display
dato=read_adc_value( ); //lee del pcf8591
write_eeprom(0x00,dato);
dato=read_adc_value( ); //lee del pcf8591
write_eeprom(0x01,dato);
dato=read_adc_value( ); //lee del pcf8591
set_timer0(0 ); //carga TMR0
}
///////////PROGRAMA/////////////////////
void main(void)
{
int dato,Pob,copia,PobN,copiaN,unidad;
float valor,valorN,kp=1,kn=1,Ku=1;
lcd_init( ); //inicializamos lcd
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
lcd_putc("\f");
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
enable_interrupts(GLOBAL); //activadas interrupciones
pcf8591_adc_init(0b00000100); //inicializamos pcf8591
write_eeprom(0x08,1); // inicializo posicion de eeprom dir0x08 => 0x08=1=bar
while(TRUE)
{
if (!input(PIN_A2)) calibracionP();
if (!input(PIN_A4)) calibracionN();
if (!input(PIN_A3)) presiones(); //funcion que selecciona unidad de Presion
unidad=read_eeprom(0x08);
/****** Tabla de Comversion **************/
switch (unidad){
case 1: Ku=1; //Presion en Bar
break;
case 2: Ku=750.2467; //Presion en mmHg
break;
case 3: ku=14.5; //Presion en Psi
break;
default:break;
}
/****** Fin de tabla **************/
PobN=read_eeprom(0x06);
copiaN=read_eeprom(0x07);
kn=(float)PobN/copiaN;
dato=read_eeprom(0x00);
valorN=dato*kn*ku*0.01; //Calculo el valor de Presion -
lcd_gotoxy(1,1);
printf(lcd_putc,"P-:-%1.2f ",valorN); //muestra por lcd
cartelU(unidad);
delay_ms(50);
Pob=read_eeprom(0x04);
copia=read_eeprom(0x05);
kp=(float)Pob/copia;
dato=read_eeprom(0x01);
valor=dato*kp*ku*0.01; //Calculo el valor de Presion +
lcd_gotoxy(1,2);
printf(lcd_putc,"P+: %1.2f ",valor); //muestra por lcd
cartelU(unidad);
delay_ms(50);
}//bucle infinito
}
void calibracionP(void)
{
int Pob=0,copia=0,Pobinicial=0;
if(!input(PIN_A2)) //pin A2=0 --> calibracion
{
lcd_putc("\f");
lcd_putc("Cal+ A3=up A4=Down");
Pob=read_eeprom(0x04); //almaceno en memoria el numerador del calculo de Kp
Pobinicial=Pob;
cartel(Pob);
delay_ms(1000);
while(!input(PIN_A2))
{
if(!input(PIN_A3)) //para ello leemos el estado del pin A3 del porta para conteo ascendente
{
do
{
Pob++; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartel(Pob);
delay_ms(100);
}while(!input(PIN_A3));
}
if(!input(PIN_A4)) //para ello leemos el estado del pin A3 del porta para conteo descendente
{
do
{
Pob--; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartel(Pob);
delay_ms(100);
}while(!input(PIN_A4));
}
}
}
if (Pobinicial!=Pob){//condicion para que cuando salga de calibracion no
//modifique el valor de presion calibrada , si no se varia el valor Pob inicial
write_eeprom(0x04,Pob);
copia=read_eeprom(0x01);
write_eeprom(0x05,copia);
}
lcd_putc("\f");
}
void calibracionN(void)
{
int PobN=0,copiaN=0,Pobinicial=0;
if(!input(PIN_A4)) //pin A2=0 --> calibracion
{
lcd_putc("\f");
lcd_putc("Cal- A3=up A2=Down");
PobN=read_eeprom(0x06);//almaceno en memoria el numerador del calculo de Kn
Pobinicial=PobN;
cartelN(PobN);
delay_ms(1000);
while(!input(PIN_A4))
{
if(!input(PIN_A3)) //para ello leemos el estado del pin A3 del porta para conteo ascendente
{
do
{
PobN++;
delay_ms(100);
cartelN(PobN);
delay_ms(100);
}while(!input(PIN_A3));
}
if(!input(PIN_A2))
{
do
{
PobN--; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartelN(PobN);
delay_ms(100);
}while(!input(PIN_A2));
}
}
}
if (Pobinicial!=PobN){//condicion para que cuando salga de calibracion no
//modifique el valor de presion calibrada , si no se varia el valor PobN inicial
write_eeprom(0x06,PobN);
copiaN=read_eeprom(0x00);
write_eeprom(0x07,copiaN);
}
lcd_putc("\f");
}
void cartel(int Pob)
{
lcd_gotoxy(2,2);
printf(lcd_putc,"P+=%1.2f bar",((float)Pob/100)); //La div por 100 es para que muestre en Bar
}
void cartelN(int PobN)
{
lcd_gotoxy(2,2);
printf(lcd_putc,"P-=%1.2f bar",((float)PobN/100)); //La div por 100 es para que muestre en Bar
}
void presiones(void)
{
int unidad=1;
if(!input(PIN_A3))
{
lcd_putc("\f");
lcd_putc("Unidad de P:");
unidad=read_eeprom(0x08);
lcd_gotoxy(2,2);
cartelU(unidad);
while(!input(PIN_A3))
{
if(!input(PIN_A2))
{
do
{
unidad++;
if (unidad>3) unidad=1;
lcd_gotoxy(2,2);
cartelU(unidad);
delay_ms(1000);
}while(!input(PIN_A2));
}
}
write_eeprom(0x08,unidad);
lcd_putc("\f");
}
}
void CartelU (int unidad){
switch (unidad){
case 1:
lcd_putc("Bar ");
break;
case 2:
lcd_putc("mmHg");
break;
case 3:
lcd_putc("psi ");
break;
default:
break;
}
}
Espero que esto sirva para contribuir, muchas de las cosas que ha aprendido en este foro, un especial agradecimiento VZener, por sus ejemplos en los cuales me he basado. Y también en los de Redpic. :-/
-
Hola Gente aqui esta el mismo programa un poco mas comentado.
Quisierasaber como podria hacer para agregarle una funcion sleep que para cuando se prenda y pase mas o menos 2 minutos ( no tiene que ser preciso solo un cierto tiempo ) , sin usarse o sin detectar entrada de pulsadores o de presion entre en modo SLEEP() o bajo consumo. El circuito de simulacion es el mismo posteado mas arriba.
////////////////////////////////////////////////////////////////////////////////////
//
// 8/07/06 - Medidor de presion!!! - p+ y p- y ademas posee tabla de conversion.
//
// Programa: Manejo del dispositivo PCF8591 en modo A/D
// Version: 0.0
//
// Dispositivo: PIC 16F628 Compilador: CCS vs3.245
// Entorno IDE: MPLAB IDE v7.31 Simulador: Proteus 6.7sp3
//
// Software con Modificaciones
//
//////////////////////////////////////////////////////////////////////////////////
/******************************************************/
/********** Programa Medidor de Presion con 16f628 ***/
/******************************************************/
#include <16f876.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT//,intrc//ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE
#include <lcd.c> //libreria para lcd
#define PCF8591_SCL PIN_A0 //definicion de pines...
#define PCF8591_SDA PIN_A1 //...de manejo del pcf8591
#include <vs_pcf8591.c> //libreria pcf8591
//////////////////////////////////////////////////
//Posiciones de memorias en eeprom del pic usadas
//0x00 Lectura A0 del adc negativo
//0x01 Lectura A1 del adc positivo
//0x02 Kp
//0x03 Kn
//0x04 Pob
//0x05 copia dir 0x01
//0x06 PobN
//0x07 copiaN dir 0x00
//0x08 unidad de presion
////////////////////////////////////////
/********DECLARACION DE FUNCIONES************/
void calibracionP(void);
void calibracionN(void);
void cartel(int Pob);
void cartelN(int PobN);
void presiones(void);
void CartelU (int unidad);
/********************************************/
/********COMIENZO DE INTERRUPCION POR TIMER0************/
#INT_TIMER0
interrupcion()
{
int dato;
dato=read_adc_value( ); //lee del pcf8591 pero no lo imprimo,
//esto se hace asi porque he activado el conversor en modo auto incremento
//y no se si es por la libreria o que empieza leyendo el ultimo valor o sea
//Ain3 luego sigue por Ain0, Ain1 y asi sucesivamente , pero en
//este caso uso solo 2 entradas , una para valores positivos y otra para valores
//negativos de presion que son los que imprimo en el display
dato=read_adc_value( ); //lee del pcf8591
write_eeprom(0x00,dato);//0x00 Lectura A0 del adc presion negativa
dato=read_adc_value( ); //lee del pcf8591
write_eeprom(0x01,dato);//0x01 Lectura A1 del adc presion positivo
dato=read_adc_value( ); //lee del pcf8591
set_timer0(0 ); //carga TMR0 al maximo dado que se resta 0 de 255 quedando al taco
}
///////////PROGRAMA/////////////////////
void main(void)
{
/********************************************/
//Pob: presion observada positiva
//PobN: presion observada negativa
//copia: copia un valor parano modificar el original positivo
//copia: copia un valor parano modificar el original negativo
//unidad:????
//valor:usado para almacenar valores de una operacion positiva
//valorN:usado para almacenar valores de una operacion negativa
//Kp:constante de multiplicacion para visualizacion de la presion positiva
//Kn:constante de multiplicacion para visualizacion de la presion negativa
//Ku:constante de multiplicacion para visualizacion
//de conversion de la presion (PSI , mmHg, Bar)
/********************************************/
int dato,Pob,copia,PobN,copiaN,unidad;//po
float valor,valorN,kp=1,kn=1,Ku=1;
lcd_init( ); //inicializamos lcd
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
lcd_putc("\f");
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
enable_interrupts(GLOBAL); //activadas interrupciones
pcf8591_adc_init(0b00000100); //inicializamos pcf8591 en modo autoincremento
write_eeprom(0x08,1); // inicializo posicion de eeprom dir0x08 => 0x08=1=bar
while(TRUE)
{
if (!input(PIN_A2)) calibracionP();//llama a la funcion calibracion positiva
if (!input(PIN_A4)) calibracionN();//llama a la funcion calibracion negativa
if (!input(PIN_A3)) presiones(); //funcion que selecciona unidad de Presion (PSI , mmHg, Bar)
unidad=read_eeprom(0x08);//inicializo posicion de eeprom dir0x08 => 0x08=1=bar por defecto
/****** Tabla de Comversion **************/
/****** Valores Comversion para otras unidades de presion **************/
/****** por defecto Ku es 1 estaria en Bares **************/
switch (unidad){
case 1: Ku=1; //Presion en Bar
break;
case 2: Ku=750.2467; //Presion en mmHg
break;
case 3: ku=14.5; //Presion en Psi
break;
default:break;
}
/****** Fin de tabla **************/
PobN=read_eeprom(0x06);//calibracion negativa
copiaN=read_eeprom(0x07);//calibracion negativa//copiaN son los escalones del ADC
kn=(float)PobN/copiaN;
dato=read_eeprom(0x00);
valorN=dato*kn*ku*0.01; //Calculo el valor de Presion -
lcd_gotoxy(1,1);
printf(lcd_putc,"P-:-%1.2f ",valorN); //muestra por lcd
cartelU(unidad);
delay_ms(50);
Pob=read_eeprom(0x04);
copia=read_eeprom(0x05);
kp=(float)Pob/copia;
dato=read_eeprom(0x01);
valor=dato*kp*ku*0.01; //Calculo el valor de Presion +
lcd_gotoxy(1,2);
printf(lcd_putc,"P+: %1.2f ",valor); //muestra por lcd
cartelU(unidad);
delay_ms(50);
}//bucle infinito
}
/****** Funcion calibracion positiva**************/
void calibracionP(void)
{
int Pob=0,copia=0,Pobinicial=0;
if(!input(PIN_A2)) //pin A2=0 --> calibracion si lo tenes apretado al pin A2
{
lcd_putc("\f");//borra pantalla
lcd_putc("Cal+ A3=up A4=Down");
Pob=read_eeprom(0x04); //almaceno en memoria el numerador del calculo de Kp
Pobinicial=Pob;
cartel(Pob);// llama a la funcion de impresion en lcd realizando una
//division por 100 ya que POb es un valor entero
delay_ms(1000);
while(!input(PIN_A2))
{
if(!input(PIN_A3)) //para ello leemos el estado del pin A3 del porta para conteo ascendente
{
do
{
Pob++; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartel(Pob);//imprime para ver que avanza la calibracion
delay_ms(100);
}while(!input(PIN_A3));//antirrebote
}
if(!input(PIN_A4)) //para ello leemos el estado del pin A3 del porta para conteo descendente
{
do
{
Pob--; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartel(Pob);
delay_ms(100);
}while(!input(PIN_A4));
}
}
}
/***********esto sirve para que efectivamenete se cargue*************/
/**********el valor calibrado y no el valor original***************/
if (Pobinicial!=Pob)
{//condicion para que cuando salga de calibracion no
//modifique el valor de presion calibrada , si no se varia el valor Pob inicial
write_eeprom(0x04,Pob);
copia=read_eeprom(0x01);//0x01 Lectura A1 del adc presion positivo valor de 0 a 255 del ADC
//copia son los escalones del ADC
write_eeprom(0x05,copia);//0x05copia para no modificar el valor original de lectura del ADC
}
lcd_putc("\f");
}
/****** Funcion calibracion negativa**************/
void calibracionN(void)
{
int PobN=0,copiaN=0,Pobinicial=0;
if(!input(PIN_A4)) //pin A2=0 --> calibracion
{
lcd_putc("\f");
lcd_putc("Cal- A3=up A2=Down");
PobN=read_eeprom(0x06);//almaceno en memoria el numerador del calculo de Kn
Pobinicial=PobN;
cartelN(PobN);
delay_ms(1000);
while(!input(PIN_A4))
{
if(!input(PIN_A3)) //para ello leemos el estado del pin A3 del porta para conteo ascendente
{
do
{
PobN++;
delay_ms(100);
cartelN(PobN);
delay_ms(100);
}while(!input(PIN_A3));
}
if(!input(PIN_A2))
{
do
{
PobN--; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartelN(PobN);
delay_ms(100);
}while(!input(PIN_A2));
}
}
}
/***********esto sirve para que efectivamenete se cargue*************/
/**********el valor calibrado y no el valor original***************/
if (Pobinicial!=PobN){//condicion para que cuando salga de calibracion no
//modifique el valor de presion calibrada , si no se varia el valor PobN inicial
write_eeprom(0x06,PobN);//0x06 Lectura A1 del adc presion negativo valor de 0 a 255 del ADC
copiaN=read_eeprom(0x00);
write_eeprom(0x07,copiaN);//0x07copia para no modificar el valor original de lectura del ADC
}
lcd_putc("\f");
}
/****** Funcion carteles de impresion LCD**************/
void cartel(int Pob)
{
lcd_gotoxy(2,2);
printf(lcd_putc,"P+=%1.2f bar",((float)Pob/100)); //La div por 100 es para que muestre en Bar
}
void cartelN(int PobN)
{
lcd_gotoxy(2,2);
printf(lcd_putc,"P-=%1.2f bar",((float)PobN/100)); //La div por 100 es para que muestre en Bar
}
/**************** Funcion presion (PSI mmHg o Bar)*******************/
void presiones(void)
{
int unidad=1;
if(!input(PIN_A3))
{
lcd_putc("\f");
lcd_putc("Unidad de P:");
unidad=read_eeprom(0x08);
lcd_gotoxy(2,2);
cartelU(unidad);
while(!input(PIN_A3))
{
if(!input(PIN_A2))
{
do
{
unidad++;
if (unidad>3) unidad=1;//reset para no exeder la condicion
lcd_gotoxy(2,2);
cartelU(unidad);
delay_ms(1000);
}while(!input(PIN_A2));
}
}
write_eeprom(0x08,unidad);
lcd_putc("\f");
}
}
/****** Funcion carteles de impresion LCD**************/
void CartelU (int unidad)
{
switch (unidad){
case 1:
lcd_putc("Bar ");
break;
case 2:
lcd_putc("mmHg");
break;
case 3:
lcd_putc("psi ");
break;
default:
break;
}
}
-
Aca esta el circuito con el proteus 6.9 sp4 anda bien esta version de proteus.
-
Muy interesante tu post, quizá me anime para ponerlo en mi 4x4 y ver la presión del turbo ;) ;) ;)
-
Me alegro que te haya gustado.
Pero tene cuidado dado que lo que esta publicado no esta con un sensor comercial. de hecho la empresa aun no nos ha pasado que sensor quiere.
Pero a los efectos de muestra si es de utilidad como programar.
Saludos
Desde cordoba Argentina
-
Me alegro que te haya gustado.
Pero tene cuidado dado que lo que esta publicado no esta con un sensor comercial. de hecho la empresa aun no nos ha pasado que sensor quiere.
Pero a los efectos de muestra si es de utilidad como programar.
Saludos
Desde cordoba Argentina
¿Puedes repetir el tema del sleep que deseas conocer? No me quedó muy en claro tu punto.
-
Hola Maunix:
Mira ya notengo problemas con el sleep, lo resolvi con un contador degresivo y con interrupciones externas tal cual vos me lo habias sugerido en su momento.
El codigo que va hasta ahora ...hasta que esta empresa se decida cual put.....sensor quiere es este.
//Tarea para el sabado :
//comprar baterias , lm1458, ver lo de low batery y hacer una condicion de salto cuando haya presion. o probar con mi modo de pregramacion.
//cortar las pistas y alimentar el operacional con 9V . la programcion con los pulsadores deep switch.
////////////////////////////////////////////////////////////////////////////////////
//
// 1/09/06 - Medidor de presion!!! - p+ y p- y ademas posee tabla de conversion.
//
// Programa: Manejo del dispositivo PCF8591 en modo A/D
// Version: 0.0
//
// Dispositivo: PIC 16F628 Compilador: CCS vs3.245
// Entorno IDE: MPLAB IDE v7.31 Simulador: Proteus 6.7sp3
//
// Software con Modificaciones
// METER OTRO SENSOR PARA HACER PRESION DIFERENCIAL O CONSEGUIR UN SENSOR QUE HAGA AMBAS
//////////////////////////////////////////////////////////////////////////////////
/******************************************************/
/********** Programa Medidor de Presion con 16f628 ***/
/******************************************************/
#include <16f876.h> //pic a utilizar
#device *=16
#device adc=8
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT,NOCPD, NOWRT,NODEBUG //No Debug mode for ICD
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portc_lcd TRUE
#include <flex_lcd1.c> //libreria para lcd
//////////////////////////////////////////////////
//Posiciones de memorias en eeprom del pic usadas
//0x00 Lectura A0 del adc negativo
//0x01 Lectura A1 del adc positivo
//0x02 Kp
//0x03 Kn
//0x04 Pob
//0x05 copia dir 0x01
//0x06 PobN
//0x07 copiaN dir 0x00
//0x08 unidad de presion
//0x09 formato
//0x10 Bateria positiva
//0x11 Bateria negativa
////////////////////////////////////////
/********DECLARACION DE FUNCIONES************/
void calibracionP(void);
void calibracionN(void);
void cartel(int Pob);
void cartelN(int PobN);
void presiones(void);
void CartelU (int unidad);
void bateria(void);
/********************************************/
//Pob: presion observada positiva
//PobN: presion observada negativa
//copia: copia un valor parano modificar el original positivo
//copia: copia un valor parano modificar el original negativo
//unidad:????
//valor:usado para almacenar valores de una operacion positiva
//valorN:usado para almacenar valores de una operacion negativa
//Kp:constante de multiplicacion para visualizacion de la presion positiva
//Kn:constante de multiplicacion para visualizacion de la presion negativa
//Ku:constante de multiplicacion para visualizacion
//de conversion de la presion (PSI , mmHg, Bar)
/********************************************/
///////////PROGRAMA/////////////////////
///LLAMADA FUNCION INTERRUPCION
#INT_TIMER0
void interrupcion( )
{
int dato;
set_adc_channel(0);
delay_ms(10);
dato=read_adc();
write_eeprom(0x00,dato);//0x00 Lectura A0 del adc presion negativa
set_adc_channel(1);
delay_ms(10);
dato=read_adc();
write_eeprom(0x01,dato);//0x01 Lectura A1 del adc presion positiva
set_adc_channel(3);
delay_ms(10);
dato=read_adc();
write_eeprom(0x10,dato);//0x10 Lectura A3 del adc bateria positiva
set_adc_channel(4);
delay_ms(10);
dato=read_adc();
write_eeprom(0x11,dato);//0x11 Lectura A4 del adc bateria negativa
set_timer0(0 ); //carga TMR0
}
void main(void)
{
int Pob,copia,PobN,copiaN,unidad,formato,dato;
long int sleepp=1000;
float valor,valorN,kp=1,kn=1,Ku=1;
lcd_init( ); //inicializamos lcd
lcd_putc(" Medidor de \n Presion...");
delay_ms(1000);
lcd_putc("\f");
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
enable_interrupts(INT_TIMER0); //interrupcion TIMER0 activada
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); //configuracion interrupcion TMR0
set_timer0(0 ); //carga TMR0 -> temporizacion maxima aprox 65.5ms
enable_interrupts(GLOBAL); //activar interrupciones
bateria();
lcd_putc("\f");
while(TRUE)
{
if (!input(PIN_B1))
{
calibracionP();//llama a la funcion calibracion positiva
}
if (!input(PIN_B2))
{
calibracionN();//llama a la funcion calibracion negativa
}
if (!input(PIN_B3))
{
presiones(); //funcion que selecciona unidad de Presion (PSI , mmHg, Bar)
}
unidad=read_eeprom(0x08);//inicializo posicion de eeprom dir0x08 => 0x08=1=bar
formato=read_eeprom(0x09);
/****** Tabla de Comversion **************/
/****** Valores Comversion para otras unidades de presion **************/
/****** por defecto Ku es 1 estaria en Bares **************/
switch (unidad){
case 1: Ku=1; //Presion en Bar
break;
case 2: Ku=750.2467; //Presion en mmHg
break;
case 3: ku=14.5; //Presion en Psi
break;
default:break;
}
/****** Fin de tabla **************/
PobN=read_eeprom(0x06);//calibracion negativa
copiaN=read_eeprom(0x07);//calibracion negativa//copiaN son los escalones del ADC
kn=(float)PobN/copiaN;
dato=read_eeprom(0x00);
valorN=dato*kn*ku*0.01; //Calculo el valor de Presion -
Pob=read_eeprom(0x04);
copia=read_eeprom(0x05);
kp=(float)Pob/copia;
dato=read_eeprom(0x01);
valor=dato*kp*ku*0.01; //Calculo el valor de Presion +
if (formato==2){
/*******************************************/
lcd_gotoxy(1,1);
printf(lcd_putc,"P-:-%1.2f ",valorN); //muestra por lcd
cartelU(unidad);
//delay_ms(500);
lcd_gotoxy(1,2);
printf(lcd_putc,"P+: %1.2f ",valor); //muestra por lcd
cartelU(unidad);
//delay_ms(500);
/*******************************************/
}else
{
lcd_gotoxy(1,1);
printf(lcd_putc,"MANOVACUOMETRO!",valorN); //muestra por lcd
//delay_ms(500);
lcd_gotoxy(1,2);
printf(lcd_putc,"P: %1.2f ",(valor-valorN)); //muestra por lcd
cartelU(unidad);
//delay_ms(500);
}
/******************REVISAR SI SOLO USAMOS EL RESET PARA VOLVER A ENCENDER EL APARATO************/
sleepp--;
if(sleepp==0)
{
lcd_putc("\f");
sleepp=1000;
sleep();
}
}//bucle infinito
}
/****** Funcion calibracion positiva**************/
void calibracionP(void)
{
int Pob=0,copia=0,Pobinicial=0;
if(!input(PIN_B1)) //pin A2=0 --> calibracion si lo tenes apretado al pin A2
{
lcd_putc("\f");//borra pantalla
lcd_putc("Cal+ A5=up A4=Down");
Pob=read_eeprom(0x04); //almaceno en memoria el numerador del calculo de Kp
Pobinicial=Pob;
cartel(Pob);// llama a la funcion de impresion en lcd realizando una
//division por 100 ya que POb es un valor entero
delay_ms(1000);
while(!input(PIN_B1))
{
if(!input(PIN_B3)) //para ello leemos el estado del pin A3 del porta para conteo ascendente
{
do
{
Pob++; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartel(Pob);//imprime para ver que avanza la calibracion
delay_ms(100);
}while(!input(PIN_B3));//antirrebote
}
if(!input(PIN_B2)) //para ello leemos el estado del pin A3 del porta para conteo descendente
{
do
{
Pob--; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartel(Pob);
delay_ms(100);
}while(!input(PIN_B2));
}
}
}
/***********esto sirve para que efectivamenete se cargue*************/
/**********el valor calibrado y no el valor original***************/
if (Pobinicial!=Pob)
{//condicion para que cuando salga de calibracion no
//modifique el valor de presion calibrada , si no se varia el valor Pob inicial
write_eeprom(0x04,Pob);
copia=read_eeprom(0x01);//0x01 Lectura A1 del adc presion positivo valor de 0 a 255 del ADC
//copia son los escalones del ADC
write_eeprom(0x05,copia);//0x05copia para no modificar el valor original de lectura del ADC
}
lcd_putc("\f");
}
/****** Funcion calibracion negativa**************/
void calibracionN(void)
{
int PobN=0,copiaN=0,Pobinicial=0;
if(!input(PIN_B2)) //pin A2=0 --> calibracion
{
lcd_putc("\f");
lcd_putc("Cal- A5=up A2=Down");
PobN=read_eeprom(0x06);//almaceno en memoria el numerador del calculo de Kn
Pobinicial=PobN;
cartelN(PobN);
delay_ms(1000);
while(!input(PIN_B2))
{
if(!input(PIN_B3)) //para ello leemos el estado del pin A3 del porta para conteo ascendente
{
do
{
PobN++;
delay_ms(100);
cartelN(PobN);
delay_ms(100);
}while(!input(PIN_B3));
}
if(!input(PIN_B1))
{
do
{
PobN--; //decremento contador para visualizar siguiente digito
delay_ms(100);
cartelN(PobN);
delay_ms(100);
}while(!input(PIN_B1));
}
}
}
/***********esto sirve para que efectivamenete se cargue*************/
/**********el valor calibrado y no el valor original***************/
if (Pobinicial!=PobN){//condicion para que cuando salga de calibracion no
//modifique el valor de presion calibrada , si no se varia el valor PobN inicial
write_eeprom(0x06,PobN);//0x06 Lectura A1 del adc presion negativo valor de 0 a 255 del ADC
copiaN=read_eeprom(0x00);
write_eeprom(0x07,copiaN);//0x07copia para no modificar el valor original de lectura del ADC
}
lcd_putc("\f");
}
/****** Funcion carteles de impresion LCD**************/
void cartel(int Pob)
{
lcd_gotoxy(2,2);
printf(lcd_putc,"P+=%1.2f bar",((float)Pob/100)); //La div por 100 es para que muestre en Bar
}
void cartelN(int PobN)
{
lcd_gotoxy(2,2);
printf(lcd_putc,"P-=%1.2f bar",((float)PobN/100)); //La div por 100 es para que muestre en Bar
}
/**************** Funcion presion (PSI mmHg o Bar) + presentacion INDIVIDUAL*******************/
void presiones(void)
{
int unidad=1,formato=1;
if(!input(PIN_B3))
{
lcd_putc("\f");
lcd_putc("Unidad de P:");
unidad=read_eeprom(0x08);
lcd_gotoxy(2,2);
cartelU(unidad);
while(!input(PIN_B3))
{
if(!input(PIN_B1))//pin A3 apretado + pin A2 como pulsdor cambio a Bar a mmHg o PSI
{
do
{
unidad++;
if (unidad>3) unidad=1;//reset para no exeder la condicion
lcd_gotoxy(2,2);
cartelU(unidad);
delay_ms(1000);
}while(!input(PIN_B1));
}
if(!input(PIN_B2))//pin A3 apretado + pin A4 como pulsdor cambio a formatos de presentacion presion +,- o diferencial
{
do
{
lcd_gotoxy(2,2);
if (formato==1)
{
lcd_putc("Formato P+ P-");
formato=2;
}else
{
lcd_putc("Formato PSUMA");
formato=1;
}
delay_ms(1000);
}while(!input(PIN_B2));
}
}
write_eeprom(0x08,unidad);
write_eeprom(0x09,formato);
lcd_putc("\f");
}
}
/****** Funcion carteles de impresion LCD**************/
void CartelU (int unidad)
{
switch (unidad){
case 1:
lcd_putc("Bar ");// aca se imprimen espacios vacion por una cuetion de refresco del diplay para que no
//queden impresas letras de mas cuando se corra una presentacion en el display.
break;
case 2:
lcd_putc("mmHg ");
break;
case 3:
lcd_putc("psi ");
break;
default:
break;
}
}
void bateria(void)
{
int bat;
lcd_gotoxy(1,1);
lcd_putc("BATERIA...");
lcd_gotoxy(6,2);
bat=read_eeprom(0x10);
lcd_gotoxy(1,2);
if(bat<180)
{
printf(lcd_putc,"Low Bat %d",bat);
}
else
{
printf(lcd_putc,"%3.1f %% %u",(float)(bat*0.4),bat);
}
delay_ms(1500);
}
LA LIBRERIA MODIFICADA PARA EL LCD EN EL PUERTO C.
// flex_lcd.c
// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.
#define LCD_DB4 PIN_C4
#define LCD_DB5 PIN_C5
#define LCD_DB6 PIN_C6
#define LCD_DB7 PIN_C7
#define LCD_E PIN_C0
#define LCD_RS PIN_C1
#define LCD_RW PIN_C2
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.
#define USE_LCD_RW 1
//========================================
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line
int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};
//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));
delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}
//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.
#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3
retval = 0;
output_high(LCD_E);
delay_cycles(1);
retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
output_low(LCD_E);
return(retval);
}
#endif
//---------------------------------------
// Read a byte from the LCD and return it.
#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high = lcd_read_nibble();
low = lcd_read_nibble();
return( (high<<4) | low);
}
#endif
//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);
#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif
if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);
delay_cycles(1);
#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif
output_low(LCD_E);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------
void lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
//----------------------------
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
if(y != 1)
address = lcd_line_two;
else
address=0;
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;
lcd_gotoxy(x,y);
// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);
return(value);
}
#endif
Saludos desde Cordoba