Hace ya un rato realice un proyecto para una clase en mi universidad, crear un sensor de presion
aqui comparto mi diagrama, por si alguien necesita ayuda para elaborar uno.
LISTA DE MATERIALES:
* Amplificador Operacional LM741
* PIC16f877a (Con el mismo codigo sirve igual el PIC16f887)
*4 Resistencias de 1 Mega ohm
*1 Resistencia de 1 Kohm
*1 Potenciomentro de 5kohm
*2 capacitor de 22 pico Faradios
*Cristal de 4Mhz oscilador para el Pic
*1 Push Button
*1 Led
* 1 Resistencia de 330 ohm
* Pantalla LCD 16x2 (De la que tiene el driver Hitachi HD 44780 "que es ahora de las mas comunes"
*Galga de presion Flexiforce (http://www.tekscan.com/flexible-force-sensors)
->Si pueden alimentar al Opamp con una fuente de 8v en lugar de la de 5v da mejor resultado
->LA LCD y el PIC se alimentan con 5v, no alimentar con mas voltaje o las quemas
La galga, aqui en Monterrey Mexico yo la compre en: http://www.5hz-electronica.com/sensordepresinflexiforce-100lbs.aspx
El diagrama lo muestro a continuación:
Diagrama Esquemático de conexiones |
Atencion, el diagrama el Potenciometro RV2 (5M) es la galga, sus tres terminales de la galga van conectadas como si fueran el potenciometro, debido a que proteus no posee la galga entre sus dispositivos tuve que colocarla asi.
La galga posee tres terminales (pines o patitas), la primera (lado izquierdo) va conectada a la entrada No Inversora del opamp y la 3ra (lado derecho) va directo al PIC, la terminal del centro no va conectada.
Diagrama en Proteus (.DSN):
DSN
CODIGO_CSS
Explicación:
*La galga cambia su resistencia al momento de aplicarle una fuerza, esta tiene una resistencia por arriba de 5Mega ohms cuando no hay fuerza aplicada, al momento de aplicar fuerza su resistencia disminuye.
*Por medio de un arreglo en el Opamp (LM741) a manera de Convertidor Voltaje Corriente, colocamos la Galga a manera de Resistencia de carga, gracias al arreglo del opamp, por ella va a cirular una corriente continua asi que al vairar su resistencia, variara directamente proporcional el voltaje en la misma
*El voltaje en la galga se lleva al convertidor analogico/digital del pic y voila, obtienes una variacion de voltaje traducida en bits.
*Solo falta calibrar el peso en la galga de tal manera que al colocar una fuerza nos de la medida en Kf
El codigo del PIC lo coloco a continuacion:
#include "16f877.h" // Pic a utilizar #device adc=10 // Usa resolución de 10 bits #use delay(clock=4000000) // Cristal a utilizar #fuses xt,nowdt,noput,nobrownout,nolvp,noprotect // Fusibles #include "lcd.c" // Libreria para utilizar LCD por el puerto D #use standard_io (D) #include <math.h> #include <string.h> void mostrar_en_lcd(float peso);//prototipo de metodo para mostrar en la lcd el peso actual int checa_numero_o_punto(char caracter); float obtiene_lectura(); float valor_absoluto(float num); float calcula_peso(float bits); //**********************--------------COMIENZA EL MAIN void main() { int i=0; float numdec1=0; float numdec2=0; lcd_init(); lcd_putc("\f"); lcd_putc("Comenzando...\n"); delay_ms(500); numdec1=obtiene_lectura(); //*******************************-*-*-*-*BUCLE INFINITO while (TRUE) { delay_ms(10);//esperamos un cuarto de segundo numdec2=obtiene_lectura(); delay_ms(10); if(valor_absoluto((numdec2-numdec1))>5) { numdec1=numdec2; mostrar_en_lcd(calcula_peso(numdec1)); } } //*******************************/*/**/*/TERMINA BUCLE INFINITO } //**********************--------------TERMINA EL MAIN ///******************************************************************************************** //COMIENZAN LOS METODOS PRIVADOS float calcula_peso(float bits) { float peso_real=0; return peso_real=-0.013135593*bits+11.76949153; } float valor_absoluto(float num) { //calculamos valor absoluto if (num<0) { //rango=rango*(-1); num*=(-1); } return num; } //Metodo que muestra en la lcd el peso actual registrado void mostrar_en_lcd(float peso) { int i=0; int mayor=9; int verifica=0; char pesochar[9];//array que contendra el string del peso //inicializamos el array for(i=0;i<=(mayor-1);i++) { pesochar[i]=0; } //sprintf redondea todo a 3 decimales //sprintf(array char para a guardar,"string de estructura y tipo",variable a convertir) sprintf(pesochar,"%5.4f",peso);//convertimos a char //checamos que todos los caracteres sean numeros o punto //si no lo son, metemos un "0" for(i=0;i<=(mayor-1);i++) { verifica=checa_numero_o_punto(pesochar[i]);//verificamos si es un numero o punto if(verifica==0) { pesochar[i]='0';//si no es numero o punto entonces metemos un "0" } } //borramos la pantalla lcd_putc("\f"); //mostramos el letrero de "El peso es:" y damos un salto de linea lcd_putc("La Fuerza es:\n"); //mostramos en la lcd el peso for(i=0;i<=(mayor-1);i++) { lcd_putc(pesochar[i]); } //agregamos la palabra kilos al final lcd_putc(" Kgf"); } //Metodo que checa si el caracter char pasado como parametro //es un numero u un punto, si no lo es regresa un cero //si lo es, regresa un uno int checa_numero_o_punto(char caracter) { int verificador=0; switch(caracter) { case '0': { verificador=1; } break; case '1': { verificador=1; } break; case '2': { verificador=1; } break; case '3': { verificador=1; } break; case '4': { verificador=1; } break; case '5': { verificador=1; } break; case '6': { verificador=1; } break; case '7': { verificador=1; } break; case '8': { verificador=1; } break; case '9': { verificador=1; } break; case '.': { verificador=1; } break; default: verificador=0; break; } return verificador; } //metodo usado para obtener el numero binario directo del convertidor A/D //en el puerto B //considerando el bit de mayor peso en el pin RB7 y el de menor peso en el pin RB0 //metodo usado para obtener el numero binario directo del convertidor A/D //en el puerto B //considerando el bit de mayor peso en el pin RB7 y el de menor peso en el pin RB0 float obtiene_lectura() { float medicion=0; //variable entera que contendra la medicion del convertidor AD delay_ms(10); setup_adc (adc_clock_internal); setup_adc_ports (all_analog); set_adc_channel (0); // Elige canal a medir RA0 delay_ms(10); medicion=read_adc (); // Hace conversión AD setup_adc (adc_off); //detenemos al convertidor delay_ms(10); return medicion; }
Grande! terminalo porfa!
ResponderEliminarEl programa esta en C?
Esta en Pic C de CCS, deja me doy un tiempo para actualizar todo
ResponderEliminarHola, Excelente trabajo!
ResponderEliminarTienes la parte de la calibración del sensor?
Eit, que onda Anónimo.
EliminarLo siento, este proyecto quedó hasta allí pero te puedo dar una explicación sencilla:
la calibración se realiza modificando la variable peso_real en la función calcula_peso(float bits).
Si observas "peso_real=-0.013135593*bits+11.76949153;" se esta usando una relación de línea recta que no pasa por cero (si graficas esa función te dara una linea recta que no pasará por cero, ya que estamos suponiendo que para cierto intervalo de valores la galga es lineal).
Y = aX + B
donde:
Y es el peso real (lo que deseas obtener)
a es la pendiente de la recta
B es la ordenada del origen
X es el valor del ADC leído
Puedes encontrar tus propios valores para tus necesidades encontrando a y B.
1.- Encuentra un objeto el cual sepas su peso exacto (obtendras "P1")
2.- Pesalo con el circuito arriba mencionado y observa cuantos bits te da el ADC, obviamente tendrás que modificar algo el codigo para que puedas ver los bits del ADC (obtendras "bits1").
Quizá te dirva de algo esto: http://hzsquare.blogspot.fr/2011/10/convertidor-ad-con-pic16f887-y-lcd-jhd.html
3.- Repite los pasos 1 y 2 con un segundo objeto (obtendras "P2" y "bits2")
a = (P2 - P1) / (bits2 - bits1) <--- pendiente de la recta
B = P2 - (a)(bits2) ó
B = P1 - (a)(bits1)
Lo bueno es que es una explicación sencilla, si no, imaginate!!!
Saludos y Suerte
Muchas gracias por tu respuesta, me quedo claro lo de la calibración, pero tengo otra duda...
EliminarEn el esquemático conectas la salida del operacional a RA0 y el pin3 de la galga a RA1... Cuando realizas la conversión A/D, lo haces del pin RA0.... con RA1 no haces nada... es como si lo conectaras a tierra? o cual es la finalidad de esa conexión?
Por otro lado, no manejo CCS... me gustaría realizar el programa en lenguaje basic, pero veo que realizas varias acciones como esta :
if(valor_absoluto((numdec2-numdec1))>5)
{
numdec1=numdec2;
mostrar_en_lcd(calcula_peso(numdec1));
Pero no logro comprender por que o para que...
Otra forma mas sencilla de hacerlo seria realizar la conversión A/D, realizar el ajuste de la calibración y listo? Es posible? Se obtendría el mismo resultado?
Muchas gracias por tu aporte!
Podrías responder al anterior comentario.
EliminarGracias