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.
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.