TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: alraid en 21 de Enero de 2013, 08:45:33
-
hola foreros,
estoy haciendo mi proyecto final de carrera que consiste en disenyar e implementar un medidor de campo magnético con un sensor para despues tratar la señal en un PIC 16F876 y mostrar el resultado por una pantalla LCD. El programa ya lo tengo hecho y siulado por Proteus funciona perfectamente pero a la hora de montarlo es donde surgio el problema.
El rango de la señal que entro al PIC para la conversión A/D por la entrada analógica es de 0 a 5 Voltios, que es el voltage con el que alimento el PIC. El caso es que a la hora de representar el resultado por la pantalla LCD no me calcula valores más altos de 4 Voltios ni más pequeños de 1 Voltio, como si el rango del PIC fuera de 1 a 4 Voltios en vez de 0 a 5. A partir del valor equivalente a 4 Voltios ya no me da más resultado aunque le introduzca al PIC en la entrada analógica un valor de 4,5.
Como en la silución por proteus sale perfecta y como en la entrada analógica realmente entran valores de 0 a 5 Voltios creo que es un problema del propio PIC y me tiene bastante desconcertado.
Muchas gracias
-
Alraid!
Eso pudiera pasar si la impedancia del elemento que estas conectando a la entrada del adc es muy alta, creo que el fabricante del pic recomienda que esta sea menor de 10Kohm.
Prueba utilizando un potenciometro de 5 o 10Kohm, como divisor de tension y nos comentas :mrgreen:
Saludos
-
Usas un amplificador operacional como etapa amplificadora?
-
Sí ppyote. Utilizo un amplificador operacional para adaptar mi señal al rango del PIC. Concretramente una etapa amplificadora restadora de ganancia 1.
Ralf2 viendo tu comentario he calculado con un tester la resistència que provoca esa etapa i es de 5,5kohms. Luego he quitado un condensador cerámico de 100nF que tenia en paralelo entre la salida del operacional y la entrada del PIC que tenía colocado para acabar de filtrar la señal pero aún así el problema persiste.
-
Mide la salida de la etapa amplificadora puesto que podía ser problema de esta. Podría ser que estas teniendo problemas con el offset del amplificador operacional, a mi me pasó lo mismo ya que del amplificador sólo me cubría el rango de 1v y 4v
-
Alraid si conectas directamente los 5V de la alimentacion del pic a la entrada del adc no te aparecen los 5V en la lcd?
Haz probado con otro pic?
En caso tal que hallas hechos todas esas pruebas y verificado los voltajes con un tester, entonces podrias colocar el hardware y el software que hiciste para verlo?
Saludos
-
la salida de voltage del operacional es la correcta de 0 a 5V. Mañana probarén conectar directamente 5 Voltios por la entrada analògica sin pasar por la etapa amplificadora haber que pasa. Si persiste el problema mañana os cuelgo el codigo de programa.
Gràcias por vuestro interés.
-
Me parece que el término que quiso utilizar ppyote es "Swing" y es el rango de tensión que puede cubrir la salida del operacional de acuerdo a la alimentación. Generalmente un operacional alimentado con 5V no llega a esta tensión a la salida debido a cuestiones de los transistores de salida, hay sin embargo un tipo de operacional que se denomina "Rail to rail" el cual puede llevar la tensión de salida a valores muy próximos a los de alimentación. Yo generalmente utilizo los LM358 (Dual AO) que es una especie de semi rail to rail, ya que su valor mínimo llega muy próximo a los 0V, pero no así a la tensión superior. También tiene estas características el LM324 (quad AO).
Lo que me extraña es que el rango sea tan corto, en una de esas todo sea cuestion de programación o de algún error de diseño.
-
Verifica en el seteo del micro y los pines de voltaje de referencia.
por alli podria estar el problema.
saludos.
-
anda por parte, saca la etapa de acondicionamiento de señal y reemplazala por un divisor de tension para obtener todo el rango de tensiones de 0 a 5v y verifica que funcione la rutina de conversion.
-
Me parece que el término que quiso utilizar ppyote es "Swing" y es el rango de tensión que puede cubrir la salida del operacional de acuerdo a la alimentación. Generalmente un operacional alimentado con 5V no llega a esta tensión a la salida debido a cuestiones de los transistores de salida, hay sin embargo un tipo de operacional que se denomina "Rail to rail" el cual puede llevar la tensión de salida a valores muy próximos a los de alimentación. Yo generalmente utilizo los LM358 (Dual AO) que es una especie de semi rail to rail, ya que su valor mínimo llega muy próximo a los 0V, pero no así a la tensión superior. También tiene estas características el LM324 (quad AO).
Lo que me extraña es que el rango sea tan corto, en una de esas todo sea cuestion de programación o de algún error de diseño.
a eso precisamente me refería, pero por no enrollarme escribiendo y editando con el móvil lo he dejado así
gracias por una mejor explicación flacoclau
-
alraid
Lo que indican los amigos sobre las limitaciones del op amp son correctas el operacional tiene unos voltajes de saturacion que limitan el maximo voltaje de salida y el minimo de estos, como sabes, por eso no tendras los 5V a la salida si los almentas con 5V, ni 0V, a menos que sean del tipo rail to rail, creo :mrgreen:
Aqui (http://www.swarthmore.edu/NatSci/echeeve1/Ref/SingleSupply/SingleSupply.html), puedes ver un ejemplo :mrgreen:
No obstante como te indique arriba y como los compañeros señalan, elimina la etapa acondicionadora y metele 5V directo o por un divisor de tension al pic debes leer 5V en la lcd, sino saca por la lcd tambien el valor del adc que deberia ser 1023 si operas a 10bits o 255 si operas a 8 bits.
Haber si el problema esta en otra parte y si tienes un pic de sobra prueba tambien con el.
Saludos
-
Gràcias a todos por las respuestas pero acabo de probar de alimenar directamente la entrada analógica con 5V sin la etapa amplificadora y el problema persiste, aunque le entre 5V el PIC ve 4V. Además el problema de swing ja lo tuve en su momento y por eso alimento el operacional com -8V y 8V.
Despues de la prueba de hoy de conectar directamente 5V y que no funcione veo que el problema es del PIC o de la programación. Os dejo el codigo del programa.
#include <16f876.h>
#device adc=10
#FUSES XT,NOWDT
#use delay (clock=2000000)
#include <lcd420.c>
float b;
float valor;
float G=1.0;
int8 unitat=1;
short n=0;
////////////////////////////////////////////////////////////////////////////////
// Funciones del programa //
////////////////////////////////////////////////////////////////////////////////
void menu2()
{
printf(lcd_putc, "1-GAUSS 2-TESLA\n");
printf(lcd_putc, "3-VOLT 4-ANT\n");
}
void menu1()
{
printf(lcd_putc, "1-MESURA\n");
printf(lcd_putc, "2-UNITATS 3-SEG\n");
}
void menu3()
{
printf(lcd_putc, "1-GUANY 3-ANT\n");
printf(lcd_putc, "\n");
}
void ant4()
{
printf(lcd_putc, "\n 4-ANT");
}
void menys()
{
printf(lcd_putc, "\fG=%01.2f 4-ANT" , G);
printf(lcd_putc, "\n1:- 2:0.1 3:0.01");
delay_ms(250);
}
void mes()
{
printf(lcd_putc, "\fG=%01.2f 4-ANT\n" , G);
printf(lcd_putc, "1:+ 2:0.1 3:0.01\n");
delay_ms(250);
}
////////////////////////////////////////////////////////////////////////////////
// Función principal del programa //
////////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////////
// Inicialización del programa //
////////////////////////////////////////////////////////////////////////////////
void main() {
setup_adc_ports(all_analog);
setup_adc(ADC_CLOCK_INTERNAL);
lcd_init();
printf(lcd_putc, " BENVINGUTS\n");
delay_ms(2000);
printf(lcd_putc, "\f");
printf(lcd_putc, " GAUSSIMETRE\n");
printf(lcd_putc, " DIGITAL");
delay_ms(2000);
inici:
printf(lcd_putc, "\f");
for (;;)
{
menu1();
///////////////////////////////////////////////////////////////////////////////
// Programa para la medida //
////////////////////////////////////////////////////////////////////////////////
if(input(pin_c0)==0)
{
while (input(pin_c0)==0)
{
menu1();
}
while (input(pin_c3)==1)
{
set_adc_channel(0);
valor=read_adc();
delay_ms(20);
set_adc_channel(1);
b=read_adc();
delay_ms(20);
b=2.0*b/1024.0;
valor=(5.0*valor/1024.0);
if (input(pin_c4)==1)
{
if (unitat==1)
{
valor=((G*200.0*valor)-(b*500));
printf(lcd_putc, "\f %04.2f Gauss", valor);
ant4();
delay_ms(250);
}
else if (unitat==3)
{
printf(lcd_putc, "\f %01.2f Volts", valor);
ant4();
delay_ms(250);
}
else if (unitat==2)
{
valor=((G*200.0*valor)-(b*500));
valor=valor*0.1;
printf(lcd_putc, "\f %04.2f mTeslas", valor);
ant4();
delay_ms(250);
}
}
else if (input(pin_c4)==0)
{
if(unitat==1)
{
valor=((G*1000.0*valor)-(b*2500.0));
printf(lcd_putc, "\f %04.2f Gauss", valor);
ant4();
delay_ms(250);
}
else if (unitat==3)
{
printf(lcd_putc, "\f %01.2f Volts", valor);
ant4();
delay_ms(250);
}
else if (unitat==2)
{
valor=((G*1000.0*valor)-(b*2500.0));
valor=valor*0.1;
printf(lcd_putc, "\f %04.2f mTeslas", valor);
ant4();
delay_ms(250);
}
}
}
goto inici;
}
///////////////////////////////////////////////////////////////////////////////
// Programa para el cambio de unidades //
////////////////////////////////////////////////////////////////////////////////
if(input(pin_c1)==0)
{
while (input(pin_c1)==0)
{
menu1();
}
printf(lcd_putc, "\f");
for(;;)
{
menu2();
if(input(pin_c0)==0)
{
while (input(pin_c0)==0)
{
menu2();
}
printf(lcd_putc, "\f");
unitat=1;
printf(lcd_putc, " MESURA GAUSS\n");
delay_ms(1000);
goto inici;
}
if(input(pin_c1)==0)
{
while (input(pin_c1)==0)
{
menu2();
}
printf(lcd_putc, "\f");
unitat=2;
printf(lcd_putc, " MESURA TESLAS\n");
delay_ms(1000);
goto inici;
}
if(input(pin_c2)==0)
{
while (input(pin_c2)==0)
{
menu2();
}
printf(lcd_putc, "\f");
unitat=3;
printf(lcd_putc, " MESURA VOLTS\n");
delay_ms(1000);
goto inici;
}
if(input(pin_c3)==0)
{
goto inici;
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Programa para la variación de la ganancia //
////////////////////////////////////////////////////////////////////////////////
if(input(pin_c2)==0)
{
while (input(pin_c2)==0)
{
menu1();
}
printf(lcd_putc, "\f");
for(;;)
{
menu3();
if(input(pin_c0)==0)
{
while (input(pin_c0)==0)
{
menu3();
}
tornar:
printf(lcd_putc, "\f");
if(n==0)
{
for(;;)
{
mes();
if (input(pin_c0)==0)
{
while (input(pin_c0)==0)
{
mes();
}
n=1;
goto tornar;
}
else if (input(pin_c1)==0)
{
while (input(pin_c1)==0)
{
mes();
}
G=G+0.1;
goto tornar;
}
else if (input(pin_c2)==0)
{
while (input(pin_c2)==0)
{
mes();
}
G=G+0.01;
goto tornar;
}
else if (input(pin_c3)==0)
{
while (input(pin_c3)==0)
{
mes();
}
goto inici; &n
-
Me parece (confirmarlo antes) que All_Analogs () habilita las dos Referencias también, es decir, que en ref+ deberías conectarle 5V y en ref- deberías conectarle gnd.
Ese puede ser tu problema...
-
Yo creo que All_ANALOG dejaba todos como entradas analógicas pero utilizaba las referencias internas. He visto que cuando hace la selección de canal no espera el tiempo prudencial para hacer la lectura. Tal vez sea ese el error.
En su código veo esto....
set_adc_channel(0);
valor=read_adc();
delay_ms(20);
set_adc_channel(1);
b=read_adc();
Y la espera debería estar entre la selección del canal "set_adc_channel(xxxx)" y la lecutra "x=read_adc()"
-
MGLSOFT, probaré en vez de activar todas las entradas analógicas con All_analog() probaré sólo activar la entrada analógica de RA0 y RA1 que son las únicas que necesito. También aumentaré el tiempo que te refieres AngelGris, pondré delay_ms(100);
Lo pruebo y os cuento
-
No pasa por aumentar el tiempo que ya tienes puesto, sino por cambiarlo de lugar. La idea es que sea assí...
set_adc_channel(0);
delay_ms(2);
variable = read_adc();
set_adc_channel(1);
delay_ms(2);
variable = read_adc();
-
Es para darle tiempo de estabilización al canal analógico elegido...
-
Ves alraid un pequeño problema de tiempos por eso era necesario que colocoaras el programa.
Haz como dice AngelGris y de seguro resuelves el 1er problema, te queda luego el del op amp :D
Saludos
-
Señores, problema solucionado. cambiando la configuración analógica de All_analogs() por la configuración setup_adc(AN0_AN1_VREF_VREF) o setup_adc(AN0_AN1_AN3) (lo he probado con las dos configuraciones) ya me abarca todo el rango que tiene que abarcar el PIC. Por lo que supongo que era problema de la configuración analógica o de las referencias que cogía con esta configuración.
Muchas gracias a todos, quizas no me habéis ayudado directamente con el problema pero con vuestros comentarios me habéis ayudado a "rodear" el problema y localizarlo. Finalmente el problema no era la etapa amplificadora sino problema de programa. Gracias a todos.
Cuando lo tenga definitivamente acabado preguntaré al tutor si puedo colgarlo en el foro de proyectos para enseñarlo. Lo tengo que preguntar porque como es un proyecto para la universidad en que he tenido que firmar un papel que no haya problemas de confidencialidad.
Gracias de nuevo soys unos cracs
-
Me alegro que pudieras solucionarlo.
Deberías ponerle al tema (Solucionado) en el nombre del POST, así saben que ya hubo solución...
-
Verifica en el seteo del micro y los pines de voltaje de referencia.
por alli podria estar el problema.
saludos.
Hay que leer todas los aportes ;-), que bueno que encontraras la solución.