Hola, parto mi posteo agradeciendo por toda la ayuda que me han dado los temas de este foro para conocer más a fondo el mundo de los microcontroladores PIC.

Ahora estoy haciendo mi Proyecto de Título (un afinador de guitarra eléctrica basado en un PIC18F2550) y tengo un gran dilema que me ha complicado bastante la cosa. Para explicarlo de manera sencilla, el funcionamiento del afinador se basa en la lectura de una señal de guitarra (preamplificada, obviamente) y el sampleo por parte del conversor A/D del microcontrolador. Una vez sampleada, el programa contaría los períodos de la señal digitalizada mediante una rutina if y luego compararía el resultado con un registro en memoria para comprobar que la cuerda está en el tono correcto o no.
Todo esto ocupa filtraje digital y el procedimiento anteriormente descrito, sin embargo, para probar que las etapas de conversión y cuenta de períodos funcionaba correctamente, ocupé el siguiente código de prueba (como se puede deducir del mismo, ocupo como salida un display LCD y como interfaces de entrada un par de pulsadores):
#include <18F2550.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#define adc=8
#use delay(clock=4000000)
#include "lcd.c"
#byte port_a = 0xF80
#byte port_b = 0xF81
#byte port_c = 0xF82
#reserve 0x20:0x232 // Reserva los siguientes bytes de memoria RAM
long sample;
/* Subrutinas del display LCD------------------------------------------------------------------------------------------------------------------------------*/
void menu1() {
printf(lcd_putc, "Seleccione cda:\n");
}
void menu(int valor){
if (valor==1) {
menu1();
printf(lcd_putc, "1era Mi");
}
if (valor==2) {
menu1();
printf(lcd_putc, "2da Si");
}
if (valor==3) {
menu1();
printf(lcd_putc, "3era Sol");
}
if (valor==4) {
menu1();
printf(lcd_putc, "4a Re");
}
if (valor==5) {
menu1();
printf(lcd_putc, "5a La");
}
if (valor==6) {
menu1();
printf(lcd_putc, "6ta Mi");
}
}
/* Subrutina de prueba de la cuenta de período (sin filtrado - borrar una vez comprobada)------------------------------------------------------------------*/
void muestra() {
printf(lcd_putc, "\fN. samples\n= %ld", sample);
}
void cuenta1() {
int per, *p;
long buc;
p = 0x20;
for(per=0;per<=10;) {
if ((*(p+buc)!=0)&&(*(p+buc-1)==0)) {
++per;
};
++buc;
if (per>=1) {
++sample;
}
};
muestra(); // Llama a subrutina 'muestra'
}
/* Subrutina del Conversor---------------------------------------------------------------------------------------------------------------------------------*/
void conversor() {
int i, value, *p;
long buc;
p = 0x20; // Graba la dirección 0x20 en el puntero 'p'
setup_adc_ports(AN0|VSS_VDD); // Vref+ = Vdd, Vref- = Vss
setup_adc(ADC_CLOCK_DIV_2); // Frecuencia de clk es de Fosc / 4
set_adc_channel(0); // RA0 como entrada analógica
printf(lcd_putc, "\fToque nota");
for(i=1;i<=30;++i) { // Espera 3 segs. (Tiempo de espera para tocar la nota)
delay_ms(100);
}
printf(lcd_putc, "\fConvirtiendo..");
for(buc=0;buc<=522;++buc) { // Se harán 522 conversiones
value = read_adc(); // Lee el valor
*(p+buc) = value; // Guarda el valor en la dirección de RAM correspondiente
// incrementa en uno la dirección de memoria
delay_us(209); // Retraso de 209 microsegundos (de manera de hacer que frecuencia sampling = 4300 Hz. Ver archivo .lst
};
printf(lcd_putc, "\fConversion lista");
for(i=1;i<=10;++i) { // Espera 1 seg.
delay_ms(100);
}
cuenta1(); // Llama a subrutina 'cuenta1' (de prueba)
} // Fin de subrutina 'conversor'
/* Parte principal del programa----------------------------------------------------------------------------------------------------------------------------*/
void main() {
int i, val;
set_tris_a(00000001); // Fija RA0 como entrada y el resto de los pines del puerto A como salidas
set_tris_b(00000000); // Fija puerto B como salida
set_tris_c(10100000); // Puerto C como entrada para los pulsadores (RC5, RC6) y el resto de los pines como salidas
port_a = 0xFF; // Fija el valor '1' en todos los pines que no se ocuparán
port_b = 0XFF;
port_c = 0XFF;
/* Carga los valores (en número de samples por diez períodos) de las fundamentales en registros. (Frecuencia de sampling = 4300 Hz)----------------*/
/*Bienvenida y menú selección----------------------------------------------------------------------------------------------------------------------*/
lcd_init(); // Inicia el display LCD
lcd_putc("\f");
printf(lcd_putc, "\fBienvenido");
for(i=1;i<=30;++i) { // Espera 3 segs.
delay_ms(100);
}
lcd_putc("\f"); // borra el display
val=1; // Rutina de selección. Si RC5 pasa a estado bajo, cambia la pantalla (subrutinas 'menu1' y 'menu'). Si RC6 pasa a estado bajo, se dirige a la subrutina de conversión.
menu(val);
while(true) {
if (!input(pin_c7)) {
delay_ms(500);
++val;
if (val==7) {
val=1;
}
lcd_putc("\f");
menu(val);
}
if (!input(pin_c6)) {
lcd_putc("\f");
conversor();
}
}
} // Final de programa principal
La finalidad de este programa es efectuar la conversión y la cuenta de períodos y mostrar en el display LCD el número de samples contados (que es proporcional a la frecuencia). La frecuencia de sampling es de 4300 Hz y la simulación en Proteus corre bastante bien, salvo algún par de correcciones que deberé hacer ya que le cuenta de samples no es siempre muy precisa. La susodicha simulación vendrá adjunta a este posteo.
El punto es que, al comprobar el mismo programa en el protoboard, el mismo me lee cualquier cosa, no me lee, resetea el programa, en fin, problemas que yo asocio con la presencia de ruido tanto en el PIC como en el conversor A/D mismo. He tratado de poner condensadores en la alimentación del PIC y de filtrar la señal análoga de entrada al conversor, sin éxito. Mi problema no creo que sea de impedancia del conversor, ya que la hoja de datos del PIC dice que la fuente de la señal análoga no debe tener más de 2.5 KOhms de entrada, y el generador de funciones que ocupo para la prueba es de 50 Ohms.
Para comprobar si el conversor A / D tenía problemas de resolución por ruido, escribí un programa simple que medía el valor de una señal DC y escribía el resultado de la conversion en el display LCD. No tuve problema alguno.
Sospecho que mi problema debe ser con la lectura de una señal AC. Las que yo ocupo están entre los 80 y 330 Hz.
Perdón por lo largo y latoso de mi posteo, pero quise darles todos los detalles que podía. Ahora estoy un poco apurado así que algo se me puede haber escapado, cualquier cosa, no duden en preguntar. ¡Muchas gracias!