Decidí comenzar a usar MPLAB con XC8 después de que comencé a alcanzar el límite de tamaño de código de 2k en MikroC. El problema es que, dado que todas las bibliotecas de Mikroc son propietarias y no hay bibliotecas disponibles para la serie PIC16F en MPLAB, tuve que escribir mis propias funciones ADC.
Estas son las dos funciones que escribí para configurar mi ADC usando la hoja de datos:
void ADC_Init(){
PIR1bits.ADIF = 0; // Clear interrupt flag
PIE1bits.ADIE = 0; // Disable ADC interrupt
INTCONbits.PEIE = 0; // Disable perriferal interrupts
ADCON2 = 0; // No ADC Trigger
ADCON1bits.ADCS = 0b111; // Select internal RC clock source
ADCON1bits.ADPREF = 0b00; // Select VDD as Vref
ADCON1bits.ADFM = 0; // Left justify, upper 8 MSB in ADRESH
ADCON0bits.ADON = 1; // Turn on ADC Module
}
int ADC_Read(char channel){
ADCON0bits.CHS = channel; // Set channel, must be between 0 and 11
__delay_us(5); // Wait some arbitrary acquisiton time
PIR1bits.ADIF = 0; // Clear interrupt flag
ADCON0bits.GO_nDONE = 1; // Start acquisioin
while(ADCON0bits.GO_nDONE) {} // Wait for the conversion to finish
return (ADRESH << 2) | ADRESL;
}
Para empezar, la señal de entrada que estoy leyendo es bastante ruidosa. En mi programa MikroC con las funciones ADC de la biblioteca, el ruido de fondo en las muestras osciló entre 60 y 100 (ADC de 10 bits). Por piso de ruido, me refiero al rango de valores que el ADC estaba leyendo sin entrada. Ruido del resto del sistema, supongo.
En MPLAB con las funciones anteriores, el ruido de fondo se ha disparado de 200 a 300. En un ADC de 10 bits, tanto ruido es inaceptable. Ejecuto la función ADC_Init() una vez fuera de mi ciclo de programa principal, luego uso la función ADC_Read(..) en mi ciclo de programa.
¿Alguna idea de por qué el ruido es mucho mayor? ¿O alguna idea sobre cómo MikroC obtiene este rendimiento? Sospecho que tiene algo que ver con la forma en que configuré el ADC.
En respuesta a la respuesta de Olin, creo que el "tiempo de adquisición" de 5us podría ser un nombre inapropiado, ese retraso está ahí para permitir que el condensador de retención se cargue después de cambiar los canales ADC. La hoja de datos muestra un ejemplo de una impedancia de señal de 10 kohm que necesita un tiempo de carga de 7,4 us. La impedancia de mi señal es de solo 700 ohmios, así que pensé que 5us debería ser más que suficiente. En cuanto al circuito, no ha cambiado, solo el software. Y la señal que estoy midiendo es una señal digital ligeramente ruidosa que sale de un IC de filtro MSGEQ7.
Esta es una buena ilustración de los problemas con los que se encuentra al usar bibliotecas enlatadas.
Si originalmente tenía un 10% de ruido en la señal, entonces tal vez el problema esté en el circuito. ¿Qué tipo de señal estás midiendo? ¿Cuál es su frecuencia superior? ¿Con qué frecuencia toma muestras? Sería útil mostrar el esquema.
Parece que está permitiendo 5 µs para la adquisición, pero ¿cómo sabe que es suficiente? ¿Qué impedancia es la señal que se alimenta al A/D? Una posible explicación de sus síntomas es que la impedancia de la señal es demasiado alta y el código anterior usaba un tiempo de adquisición más largo, lo que permitió que la muestra y la retención se asentaran más cerca del valor correcto.
Sin embargo, una mejor respuesta probablemente sea repensar toda la estrategia A/D en primer lugar. No lo base en las rutinas de la biblioteca que están disponibles o alguna tontería similar. Lea la sección de la hoja de datos sobre el A/D y piense en la mejor manera de usarlo, posiblemente junto con otro hardware, como temporizadores, para resolver el problema de medición general.
Una estrategia que utilizo con frecuencia es tomar lecturas A/D en una interrupción periódica. Ejecute esto tan rápido como el A/D le permita adquirir y convertir la señal, y dentro de los límites de dejar suficientes ciclos de primer plano para el resto del sistema. Esta interrupción A/D muestrea el A/D mucho más rápido de lo que realmente necesita, luego filtra los resultados con filtros de paso bajo. Cuando el código principal quiere la última lectura, no sale y toma una sola lectura A/D. Solo usa el valor actual de la salida del filtro de paso bajo. He hecho este tipo de cosas muchas veces. De hecho, es mi forma normal de tomar lecturas A/D a menos que haya una razón específica para hacerlo de manera diferente.
En un microcontrolador pequeño, no hay sustituto para comprender realmente el hardware y ser consciente de cómo se usa exactamente, ya sea a través de su propio código o de rutinas de "biblioteca".
Ahora dice que está utilizando interrupciones periódicas para leer el A/D, pero entonces su código tiene aún menos sentido que antes. Si solo está leyendo un solo canal, entonces dejaría el A/D configurado en ese canal y no lo cambiaría durante la operación normal. Si está leyendo varios canales, la interrupción los recorrerá. En ese caso, la interrupción de la conversión A/D realizada cambiaría el hardware al nuevo canal justo después de obtener los resultados de la conversión. De esa manera, la mayor parte del tiempo que no es conversión se usa para adquirir la siguiente señal. Incluso si tuviera que ejecutar el A/D bastante rápido, como 100 kHz por ejemplo, eso aún deja la mayoría de 10 µs para la adquisición.
Por lo general, no llamaría a una rutina de conversión A/D desde una interrupción de todos modos, e incluso si lo hiciera, no estaría cambiando el canal y luego esperando la adquisición y la conversión mientras el código de primer plano está bloqueado fuera del procesador. . Eso no tiene sentido y es innecesario.
Luego está el problema de devolver el valor de 10 bits sin signo justificado a la izquierda en un entero con signo. No tiene sentido que los valores de 512 y superiores se interpreten como negativos.
Una vez más, ¿cuál es el contenido de frecuencia superior de la señal? ¿Con qué frecuencia el firmware necesita su valor? Hago estas preguntas por buenas razones, y espero que las responda ya sea que crea que son relevantes o que entienda las razones o no. Después de todo, este es tu problema. Somos voluntarios tratando de ayudar, pero si se niega a cooperar, encontraremos otros lugares para pasar nuestro tiempo limitado aquí.
No hay nada inherente a ninguna de las bibliotecas que deba afectar el ruido de fondo. El estado predeterminado para muchos PIC ADC es de 8 bits, y debe configurar las cosas para obtener los 10 bits completos (no sé cómo se hace eso en MPLAB). Esto puede haber sido manejado por usted en MikroC. Además, debe asegurarse de que sus datos estén justificados correctamente en el entero de 16 bits. Si lo tiene justificado a la izquierda, y solía estar justificado a la derecha, su piso de ruido se vería grande
Shubham
olin lathrop