TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: tocaja en 14 de Marzo de 2005, 16:01:00
-
Trato de intentar leer con el micro una tensión analógica, y sacarla por un LCD 2x16. Mirandome bien los ejemplos que he encontrado en el foro he conseguido dominar bien el LCD (creo), pero no me pone el valor en el LCD,el resultado es siempre el mismo 255.99. Dejo aqui el código hecho en CCS haber si alguien me puede hechar un cable, muchas gracias.
NOTA: ME DA UN ERROR EN LA INSTRUCCIÓN #DEVICE ADC=8, POR ESO ESTA COMO COMENTARIO
#include <16f876.h>
#use delay(clock=4000000)
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect
//#device adc=8
#define use_portB_lcd TRUE
#include "lcd.c"
#use standard_io(B)
//migsantiago
// As defined in the following structure the pin connection is as follows:
// B0 enable
// B1 rs
// B2 rw
// B4 D4
// B5 D5
// B6 D6
// B7 D7
void main(void)
{
float entrada; // entrada es el valor analogico que entra al A/D
float salida; // salida es el valor que quiero se vea en el LCD
set_tris_A (0xFF); // Puerto A configurado como entrada
set_tris_B(0x00); //Puerto B configurado como salida
port_B_pullups(FALSE); // Desactivamos pull-ups del puerto B
lcd_init(); //Inicia LCD
lcd_putc("MEDIDOR DE CAMPO
"
; //Saca texto
lcd_putc(" MAGNETICO "
; //Saca texto
delay_ms(3000);
lcd_putc("f"
; //Limpia pantalla
lcd_putc(" CAMPO ACTUAL /n"
; //Saca texto
delay_ms(1000);
lcd_gotoxy(9,2); //Acomoda cursor LCD
lcd_putc("OERSTED"
;
while (1)
{
lcd_gotoxy(2,2); //Acomoda cursor LCD
lcd_putc(" "
; //Limpia ese sector de pantalla
lcd_gotoxy(2,2); //Acomoda cursor LCD
setup_adc (adc_clock_div_32);
setup_adc_ports (RA0_ANALOG);
set_adc_channel (0); //Elige canal a medir RA0
delay_us (20);
entrada=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)
setup_adc (adc_off); //Apaga ADC
salida=entrada; //*ganancia;
printf(lcd_putc,"%3.2f",salida); // Mostramos en el lcd el contenido de la variable "salida"
delay_ms(1000);
}
}
-
Prueba a meterle un delay_ms(5000) despues de iniciar la lectura del conversor. De manera que kede mas o menos asi:
entrada=read_adc();
delay_ms(5000);
setup_adc (adc_off);
-
El código está bien, debes tener alguna conexión mal.
Aunque funcione igual, yo pondría los setup en el main, no el el while.
Puedes quitar el setup_adc (adc_off);
Puedes ahorrarte la variable salida y usar solo la de entrada.
Respecto a que te dá error el #DEVICE ADC=8, ponlo detrás de #include <16f876.h> y ya no te dará. Si vas a usar una conversión de 8 bits, no hace falta el #DEVICE ADC=8, lo considera así por omisión. Para 10 bits sí que hace falta.
Un saludo
-
Gracias amigos, entre todos he conseguido hacerlo funcionar, era más un problema de desconocimiento del funcionamiento de un micro.
Mi problema ahora es el siguiente: tengo por ejemplo una entrada analógica de 0.150V, qe pasa por el A/D, y pongo la instrucción para escalar
salida=entrada*5/256;
pues bien,ante esta entrada igual obtengo en el LCD 0.136v
No se si esta inexactitud es normal, podriais aclararmelo??
-
No entiendo bien tu pregunta.
Cuando dices que haces esto: salida=entrada*5/256;
¿Te refieres a que la medida que estás tomando se mueve entre 0 y 5V?
En cualquier caso, si metiéndole una señal de 0,15V te lee 0,136V estaría representando un error del 10%, lo cual es inadmisible, ante lo cual te recomendaría revisar si estás haciendo bien el proceso y por supuesto, asegurarte bien que esos 0,15V son realmente 0,15V.
-
Si eso, perdón por no haberme expresado mejor.El micro tiene un rango de 0 a 5v. Copiaré el codigo que tengo actualmente:
#include <16f876.h>
#use delay(clock=4000000)
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect
#define use_portB_lcd TRUE //Para que las señales vallan al LCD por el puerto B
#include "lcd.c"
#use standard_io(B)
void main(void)
{
float entrada; // entrada es el valor analogico que entra al A/D
float salida; // salida es el valor que quiero se vea en el LCD
set_tris_A (0xFF); // Puerto A configurado como entrada
set_tris_B(0x00); //Puerto B configurado como salida
port_B_pullups(FALSE); // Desactivamos pull-ups del puerto B
lcd_init(); //Inicia LCD
lcd_putc("MEDIDOR DE CAMPO
"
; //Saca texto
lcd_putc(" MAGNETICO "
; //Saca texto
delay_ms(3000);
lcd_putc("f"
; //Limpia pantalla
lcd_putc(" CAMPO ACTUAL /n"
; //Saca texto
delay_ms(1000);
while (1)
{
setup_adc (adc_clock_div_32);
setup_adc_ports (RA0_ANALOG);
set_adc_channel (0); //Elige canal a medir RA0
delay_us (20);
entrada=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)
setup_adc (adc_off); //Apaga ADC
salida=entrada*5/256; //Escalamiento
salida=salida*1000;
if ( salida < 176 )
{
lcd_gotoxy(9,2); //Acomoda cursor LCD
lcd_putc("OERSTED"
;
lcd_gotoxy(2,2); //Acomoda cursor LCD
lcd_putc(" "
; //Limpia ese sector de pantalla
lcd_gotoxy(2,2); //Acomoda cursor LCD
printf(lcd_putc,"%3.2f",salida); // Mostramos en el lcd el contenido de la variable "salida"
delay_ms(1000);
}
else
{
lcd_gotoxy(4,2); //Acomoda cursor LCD
lcd_putc("SATURACION"
;
}
}
}
Todo simulado con proteus, xq todavia no tengo el micro en mis manos, aunque espero que hasta dentro de poco.
El problema es que las medidas que muestra en el LCD no son exactas respecto a lo que meto en la entrada, por ejemplo para 50mv me muestra 39,06 en pantalla.
LA conexión de los pines es
// B0 enable
// B1 rs
// B2 rw
// B4 D4
// B5 D5
// B6 D6
// B7 D7
garcias por la colaboración
-
A ver...
50mv sería 0.05*(256/5)=2.56, osea, tu conversor dará una lectura en decimal de 2 (los decimales tendrás que despreciarlos, logicamente). Por tanto, 2*(5/256)=0.0390625... Te suena??
Lo mismo puedes hacer con el otro ejemplo que pusistes y verás que te da lo que lees en pantalla, según el Proteus.
Qué puedes hacer?? Pues usar de momento los 10bits que tiene el conversor del micro seguramente... Hay pocos modelos con sólo 8bits, que de ser uno de esos...
Ver el rango que vas a tener a la entrada. Si va a ser de pocos milivoltios o ni por asomo llega al rango que tienes, pues no uses un rango de 0 a 5v. Modifica eso... O bien cambiando la tensión de referencia o amplificando la entrada.
Y siempre usa una buena tensión de referencia... que lo que obtienes en Proteus es muy bonito.. pero en la realidad.. ya sabes. Un pequeño ruido o una fuente no lo suficientemente estable te hará variar mucho esa lectura.
Espero te sea de ayuda...
Saludos y suerte!!
-
Vale,entiendo lo que me dices, pero lo que no me aclaro es con la solución, xq no entiendo muxo de micros. Por un lado no se que diferencia hay entre usar 8 o 10 bits. Por otro como se modifica el rango de 0 a 5v?? Por otro, no habia considerado ninguna tensión de referencia....... Como ves estoy algo verde aun,jeje. Tb puede ser que las fallas siempre pasan factura.help please
-
Teóricamente el conversor AD del 16F876 ya trabaja con 10 bits por defecto, por lo que la lectura del mismo la tienes que hacer sobre una variable int16 y los resultados de dicha lectura estarán comprendidos entre 0 y 1023.
No obstante, si quieres asegurarte, puedes añadir esto al principio de tu programa:
#device PIC16F876 ADC=10
-
El CCS por omisión del #device adc=8 o #device adc=10, trabaja con 8bits.
Para mejorar tu lectura para valores de entrada de mV, haz lo que te dice Cuca: usa una conversión de 10 bits, para lo cual tendrás que cambiar el #device adc=8 por #device adc=10 y salida=entrada*5/256 por salida=entrada*5/1024
Si quieres mejorar todavía más la lectura usa una tensión de referencia más pequeña, por ejemplo 2,5V.
Un saludo
-
Vale, muchas gracias, ya lo tengo claro. Ahora lo que intento es en vez de tener 1 entrada analógica, voy a meterle 3, va a ser muy complicado para que salgan las medidas por el LCD???
-
No, es igual, lo único que tienes que hacer es seleccionar el canal analógico con set_adc_channel (x), hacer las operaciones necesarias con él y mostrar el resultado en pantalla. Cuando acabes con el primer canal eliges con set_adc_channel (x) el siguiente y lo mismo.
Un saludo