Gracias Amigos. Esto es una recopilación de lo voy haciendo sobre la marcha y lo voy exponiendo para que aquel que también quiera y/o necesite incursionar con este PIC, por lo menos tenga alguna guía de lo que debe y no debe hacer.
Esta vez vamos a utilizar un módulo que se utiliza frecuentemente: el módulo del Convertidor Analogico Digital(CAD ó ADC en inglés), yo he realizado uno que otro montaje con este módulo, pero nunca lo he explicado (por allí dijeron que es mas dificil explicar que aplicar lo aprendido), así que intentaré aportar de lo que estoy conociendo.
las fuentes consultadas:
-PICmicro® 18C MCU Family Reference Manual (39500a.pdf pagina 583)
-
configurar el estímulo del ADRESL-
Conceptos-
SALTO EN EL CONVERTIDOR A/D DE UN 16F877-
convertir 10 bits y quedarme con 8 nos vamos directo para la página 261 del 39632c.pdf, que es el datasheet del la familia PIC18F2455/2550/4455/4550 y allí está un capítulo dedicado a este módulo.
-las diferencias que leí respecto al 16F877, le agregaron un adcon2 y hay 13 posibles entradas analogicas multiplexadas.
-la configuración PCFG3:PCFG0 luce mas ordenada.
-Le agregaron unos bits que son muy interesantes ACQT2:ACQT0 para manejar el tiempo de adquisición, ya lo explicaremos.
- desde el punto de vista del 16F87xA(dentro de la familia 16) no ha cambiado las opciones del clock de CAD (hay 7 opciones)
Quisiera hacer un resumen del funcionamiento del CAD para poder explicar las nuevas opciones que trae el 18F4550 y las mejoras respecto al 16F877
La definición del Convertidor Analogico Digital, la podemos conseguir en la
wikipic y se puede desglosar de la siguiente manera:
de acuerdo a la imagen anterior:
-existen unos pines que se pueden configurar como entrada analógica, del cual se toma uno a la vez.
-dado un arreglo R-C,que existe dentro, o a la entrada del módulo CAD se toma un nivel de tensión en un tiempo discreto, ese voltaje se almacenará en el condensador interno (Chold)
-el tiempo que tarde ese condensador en cargarse, lo determinaremos nosotros de 2 maneras:
-mediante un retardo por software (configurando un timer, ó generando ciclos de instrucción).
-mediante un retardo por hardware (configurando los bits ACQT2:ACQT0 en ADCON2)
este tiempo, es el tiempo de adquisición ó Tacq (acquire), y es fundamental para obtener precisión en el resultado digital. Ojo no confundir con Tad, como lo hice alguna vez,(las iniciales en inglés se asemejan a las iniciales en español)
en el caso del 16F877, mediante calculos teoricos era Tacq ~ 20uS
en el caso del 18F4550, el tiempo mínimo que sacan es Tacq ~ 2,45uS
esto aparece en la página 266. Se nota que disminuyó el tiempo y aumentando así la velocidad en el CAD
el retardo por hardware (que así lo quise llamar) ó programmable acquisition time es algo nuevo, es posible configurar el Tacq:
en la figura 21-4 es como siempre lo habiamos visto, antes de activar el GO_DONE había que introducir el Tacq. Ahora usando la configuración por hardware, tenemos la figura 21-5 donde sucede después de haber seteado al GO_DONE (no algodon,
)), haciendolo automático.
-luego viene el proceso de hacer la conversión, es decir, tomar el valor analógico de lo que está cargado en el condensador Chold y llevarlo a un número binario.
-en este proceso de conversión hay otros parametros, uno de ellos es el reloj de conversión, esto quiere decir decir que el módulo CAD, trabaja con un reloj distinto del CPU y que puede depender o no de éste. Eso lo dirá la debida configuración de los bits ADCS2:ADCS0 del registro ADCON2
Cuando digo que puede ser independiente del CPU, es porque puede trabajar con un reloj interno (un oscilador RC) cuya aplicación sería poner a dormir el pic mientras se está haciendo una conversión, ¿y que utilidad puede tener esto?, bueno al estar trabajando solo el módulo CAD, se reduce el ruido de conmutación de los otros perifericos y puede aumentar la precisión del valor digital obtenido.
Desventajas: usando el oscilador interno se tarda mas la conversión (en el orden de los mS, que podría sería mucho tiempo para algunos eventos)
cuando inicia la conversión, lo primero que hace es desconectar el condensador Chold de la entrada analogica, y mediante una aproximación sucesiva, se vá guardando bit a bit de los 10 bits que hay, el resultado digital (ver figura 21-4)
esto también tiene su tiempo y es el tiempo (retardo) de conversión analogico digital por bit, llamado Tad. Según la pagina 267 se requiere de un tiempo de 11Tad para realizar una conversión, el Tad mínimo para el CAD del 18F4550 es 700nS (página 400)
pero haciendo algunos calculos de acuerdo a la tabla 21-1
usando un clock del CPU de 48Mhz se obtiene hasta 64/48Mhz = 1.33uS
Nota: el Tacq sacado por hardware depende de Tad
posteriormente viene todo lo que se venia aplicando anteriormente, esperar a que GO_DONE =0 ó esperar la interrupción del CAD y tomar el valor que está en la pareja de bytes ADRESH:ADRESL (limpiar la bandera ADIF si es es por interrupción) en general, los pasos para un CAD, serian(pag265):
desde luego que todo esto es pura teoría, así que vamos a darle con un ejemplo
para nuestro ejemplo(ejemplo4):
-usaremos un reloj de conversión de 64Tosc = Fosc/64 ya que seguiremos usando un clock de 48Mhz y esto es lo que recomienda la tabla 21-1
-usaremos el Tacq por hardware, así que si nuestro Tad=1.33uS, entonces usando un tacq=2Tad= 2*1.33uS = 2.66uS
-seleccionaremos el canal AN0, el resto como i/o digital
-haremos la conversión AD y después indicaremos el resultado en 10 leds
aunque yo no se para que tanta precisión, si estoy trabajando en C, y no se que como hará eso el compilador.
cálculo preciso + teórico= cálculo preciso + error(práctico)
cálculo preciso + error(teórico)= cálculo preciso + error(práctico) + error(teórico)
// usando el CAD en el 18F4550
// 30-Dic-2006
#include <18f4550.h> //archivo de cabecera
//#DEVICE ADC=8 // cad a 8 bits, justificación a a la derecha
#DEVICE ADC=10 // cad a 10 bits, justificación a a la derecha
//#DEVICE ADC=16 // cad a 10 bits, justificación a a la izquierda
#fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN,NOPBADEN // el fuse que configuramos anteriormente (CORREGIDO)
#use delay(clock=48000000) // el clock que tendremos a la entrada del CPU
#byte LATB=0xF8A
#byte PORTB=0XF81
void main() {
long value;
int parte_alta;
int ADC_ACQT_2TAD=0x1;
output_a(0); // saca un nivel bajo de salida en los puertos
output_b(0);
output_c(0);
output_d(0);
output_e(0);
set_tris_a(0x1); // configura los puertos como salidas
set_tris_b(0x0);
set_tris_c(0x0);
set_tris_d(0x0);
set_tris_e(0x0);
//-----------------------------------
disable_interrupts(global);
disable_interrupts(int_timer1);
disable_interrupts(int_rda);
disable_interrupts(int_ext);
disable_interrupts(int_ext1);
disable_interrupts(int_ext2);
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(FALSE);
setup_adc_ports( AN0 || VSS_VDD );
setup_adc(ADC_CLOCK_DIV_64 || ADC_ACQT_2TAD );
set_adc_channel(0);
while(1){ // bucle infinito
value = read_adc(); // toma el resultado del CAD
output_b((int)value); // envía el byte LSB a portb
parte_alta=(int)((value & 0x300)>>8); // separa los 2 bits MSB de value
output_c(parte_alta); // y los envia al portc
}
}
buscando en el CCS no conseguí alguna constante declarada para los bits ACQTx así que tuve que crearlos y hacer una OR incluyente con las demas constantes dentro de la función setup_adc().
int ADC_ACQT_2TAD=0x1;
para comprobar si esto es correcto, voy a compilar y miraré en la ventana SFR del MPLAB para ver como quedó el registro ADCON2
adcon2cambiandoPero fué en vano, el CCS no me deja cambiar los bits 3,4,5 de ADCON2, así que me voy por ensamblador, sustituyo la linea setup_adc(ADC_CLOCK_DIV_64 || ADC_ACQT_2TAD ); por:
#asm
movlw 0b10001110 ;justificacion_derecha,2Tad,Fosc/64
movwf 0xFC0 ; direccion de ADCON2
#endasm
ahora si aceptó el cambio, entonces se hace la simulación nuevamente, pero antes introduzco el cambio de ADRESx mediante estimulos, en una de las fuentes consultadas(ver arriba) el amigo Maunix explica como hacerlo, ahora si arrancamos con el MPLAB-SIM
video_config_estimuloel estímulo no está funcionando, de verdad que pasé un rato creyendo que estaba mal configurado el Register Injection, pero después me dí cuenta que faltaba la instrucción setup_adc(), si así como lo leen, ¿como se hace entonces si lo había quitado?, bueno, lo coloque de nuevo y le añadí el pedacito en assembler para que aceptara el cambio en ADCON2
setup_adc(ADC_CLOCK_DIV_64 ); //|| ADC_ACQT_2TAD );
#asm
movlw 0b10001110 ;justificacion_derecha,2Tad,Fosc/64
iorwf 0xFC0,1 ; direccion de ADCON2
#endasm
claro, que cambié el movwf por iorwf, para que me aceptara los nuevos bits sin alterar el estado anterior de ADCON2, también es bueno decir que por aquí se puede cambiar la justificación, hay otra cosa interesante, en CCS hay una directiva #DEVICE ADC=xx , sería bueno analizar que pasa si cambio ADC=10 por ADC=16, ¿esto hará la justificación hacia la izquierda?, sería otro estudio.
vamos a simular de nuevo,
nota: el archivito llamado adresito.txt tiene estas lineas guardadas:
1A0
2AA
3FF
esas lineas corresponden al supuesto valor de ADRESH:ADRESL y seran cargadas por el estímulo en un bucle
nueva_simulacionme dió curiosidad y ví el listado en ensamblador, metí un breakpoint en el momento de escoger el canal y hasta que se cargan la pareja ADRESH:ADRESL
calculando el tiempo teorico: Tacq=2*Tad + 11*Tad= 2*(64/48Mhz) +11*(64/48Mhz)=17.33uS
bastante aproximado con los 18.33 uS que dá el MPLAB-SIM.
el siguiente paso es programar el pic y probarlo en el protoboard, hay un detallito que se está olvidando, la resistencia Rs, que es la que vá a la entrada AN0, según los calculos teoricos máximo de 2.5k, yo usaré un potenciometro que le medí 2k que es lo que tengo a mano, ¿habrá algún cambio? eso habrá que verlo en el protoboard.
video_protoboardja ja con tanta cablamenta, me imagino el ruido que debe haber allí.
Lo importante es que hicimos arrancar el módulo CAD y que hicieras las respectivas conversiones.
hice unas mediciones con el tester, y me di cuenta que al insertar la punta en AN0 parece que introduce variaciones, así que conecté un TL082 como seguidor de voltaje, para poder medir sin interferencias. peeeero me topé con un problemita, hay un detalle cuando intentas medir niveles cercano a 0 volts usando el TL082. Buscando por ahí conseguí una
página donde explican el fenomeno(llamado latch-up), a mi me sucede esto porque alimento al operacional con +Vcc=+5 y -Vcc=0.
Solución: alimenté al operacional con +Vcc=+12 y -Vcc= -12 y ¡listo!.
volví hacer mediciones, esta vez arreglando mejor las conexiones:
- una especie de apantallamiento a la entrada AN0
- acerqué mas el C=100nF de alimentación del PIC.
y varios resultados obtenidos:
según estos datos obtenidos, la precisión es mas o menos... uhmmm, será por el montaje en protoboard, si ya se que todo es relativo... voy hacer otra prueba, voy a aumentar el Tacq al máximo permitido por ADCON2, esto es 20Tad = 20 * 1.33uS = 26.6 uS bastante tiempo de sobra que sumandole 11Tad = 11* 1.33uS =14.63uS daría una conversión aproximada de 41.23uS
para Tacq=20Tad -> ADCON2<-0b10111110, entonces el código cambiará:
#asm
movlw 0b10111110 ;justificacion_derecha,20Tad,Fosc/64
iorwf 0xFC0,1 ; direccion de ADCON2
#endasm
repitiendo todo el procedimiento anterior, compilando y simulando y depués grabar el micro, llegamos a revisar el montaje en el protoboard:
videito_proto2y unos datos nuevos que recopilé
Conclusión:
bueno señores, esos resultados como que mejoraron un poco
, uhmmmm... la verdad es que nunca he podido obtener valores calculados en la práctica, quizas un montaje mejor elaborado en baquelita y bien filtrado pueda aumentar la precisión.
espero que les pueda instruir en algo.
nota: en el adjunto está todo el código con su respectivo circuito eléctrico.
Salu2
Pedro
PD: Quise colgar los videos en youtube pero algunos pierden bastante definición