ADC Simultaneo en 2 canales con dsPIC33 [CCS Compiler]

Qué tal compañeros del foro, buenas noches.

Antes que nada describo las herramientas que estoy usando:

* Microcontrolador: dsPIC33FJ12MC202
* Compilador: CCS Compiller 4.104
* Simulador: Proteus 7.7 SP2

El objetivo al que quiero llegar es a poder realizar un muestreo simultaneo en los canales AN0 y AN1, y poder convertir los valores en un valor de voltaje, para finalmente enviar los valores por el puerto serie.

Hasta dónde he leído en el datasheet, sé que tengo que configurar el bit SIMSAM del AD1CON1 para poder efectuar el muestreo.

De momento el programa que tengo es el siguiente:

Código:
#INCLUDE <33FJ12MC202.H>
#DEVICE adc=10             // Se incluyó esta directiva
#USE DELAY(CLOCK=80M)      // En base a esta Fosc el compilador maneja las instrucciones
                           // que usan recursos de tiempo, como la comunicación serial RS232
#USE RS232(BAUD=9600,XMIT=PIN_B6,RCV=PIN_B7) // Terminales RP6 y RP7
#FUSES HS, PR_PLL, NOWDT   // El PLL se programa en base a un cristal principal 
                           // externo

//********************************** REGISTROS *********************************
#WORD M        = 0x0746       // Factor M para la configuración del PLL
#WORD IFS0     = 0x0084       // Registro que contiene AD1IF
#WORD AD1CON1  = 0x0320       // Registro que contiene la bandera de fin 
                              // conversion del ADC
#WORD AD1CON2  = 0x0322       // Registro para configurar muestreo simultaneo 
#WORD CLKDIV   = 0x0744       // Registro para configurar divisor de reloj
//********************* CONFIGURACIÓN DE BITS DE REGISTROS *********************
// Bits de factor M
#BIT PLLFBD_0  = M.0
#BIT PLLFBD_1  = M.1
#BIT PLLFBD_2  = M.2
#BIT PLLFBD_3  = M.3
#BIT PLLFBD_4  = M.4
#BIT PLLFBD_5  = M.5
#BIT PLLFBD_6  = M.6
#BIT PLLFBD_7  = M.7
#BIT PLLFBD_8  = M.8
// Registro CLKDIV
#BIT DOZE_14  = CLKDIV.14
#BIT DOZE_13  = CLKDIV.13
#BIT DOZE_12  = CLKDIV.12
// Registro IFS0
#BIT AD1IF = IFS0.13  
// Registro AD1CON1
#BIT DONE = AD1CON1.13     // Bit para fin de conversión
// Registro AD1CON2
#BIT CPHS_8 = AD1CON2.8    // Se configuran CH0 y CH1 para muestra simultanea
#BIT CPHS_9 = AD1CON2.9    // Se configuran CH0 y CH1 para muestra simultanea
//#BIT ASAM   = AD1CON2.2  // Muestreo se hace inmediatamente despues de la 
                           // última conversión
#BIT SIMSAM = AD1CON1.3

//************************** DECLARACIÓN DE VARIABLES **************************
char  c=0;
int16 valor;
float V1=0.0, V2=0.0;
//***************************** PROGRAMA PRINCIPAL *****************************
MAIN(){
//*************************** CONFIGURACIÓN DEL dsPIC **************************

   // Fcy=(1/2)*((Fin*M)/(N1*N2))=(1/2)*((20MHz*32)/(2*4))= 40 MIPS
   // M = 32 --> Se configura
   // N1 = 2 --> Valor por defecto
   // N2 = 4 --> Valor por defecto
   // Fin= 20 MHz --> Se selecciona este valor, por ser comercial
   // Valor binario   000011110 --> Valor decimal 32 cargado
   PLLFBD_8 = 0;//----|||||||||     al registro PLLDIV<8:0> 
   PLLFBD_7 = 0;//-----||||||||
   PLLFBD_6 = 0;//------|||||||
   PLLFBD_5 = 0;//-------||||||
   PLLFBD_4 = 1;//--------|||||
   PLLFBD_3 = 1;//---------||||
   PLLFBD_2 = 1;//----------|||
   PLLFBD_1 = 1;//-----------||
   PLLFBD_0 = 0;//------------|
   
   // Se configuran los canales AN0 y AN1 con los bits CHPS<1:0> para un 
   // muestreo simultaneo
   
   CPHS_9=0;
   CPHS_8=1;
   
   // Se activca el muestreo simultaneo
   
   SIMSAM=1;

   set_tris_a(0b11111);                // RA0 a RA4 como entradas
   setup_adc_ports(VSS_VDD|sAN0|sAN1); // Se configuran los puertos análogos
   setup_adc(ADC_CLOCK_DIV_8);         // TAD = 100 ns

//*****************************************************************************

while(1){
      set_adc_channel(0);
      delay_us(1);        // TSAMP >= 2TAD, 2TAD = 200 ns
      valor=read_adc();
      V1=(3.6/1024.0)*valor;
      set_adc_channel(1);
      delay_us(1);
      valor=read_adc();
      V2=(3.6/1024.0)*valor;
      printf("V1 = %f V", V1);
      printf("V2 = %f V", V2);
      
      delay_ms(500); // Para que se puedan visualiar detenidamente los valores
                     // el la terminal virtual mientras manipulas los potenciómetros.
   }


}

La verdad estoy un poco perdido en como efectuar el muestreo simultaneo, y de dónde y como se leen los valores una vez obtenidos. Lo poco que tengo ha sido leer y leer :rolleyes: ya que en la red no hay muchos ejemplos y los pocos que hay nadie responde con una respuesta muy concreta.

Anexo simulación.

Sin más de momento espero alguien me pueda echar una mano GRACIAS!!.
 

Adjuntos

  • Registrador.rar
    16.8 KB · Visitas: 16
Creo que estás configurando registros que el compilador hace por defecto.
Este compilador hace mucho por uno en cuanto a configuración de registros básicos se refiere.

Aunque sea un dsPIC, lo puedes programar como si se tratara de otro PIC.
Así que puedes escribir tu programa normalmente sin preocuparte por configurar registros especiales.
El uso de las funciones especiales lo puedes encontrar en el archivo 33FJ12MC202.h
Y lo puedes abrir desde el mismo entorno seleccionándolo en el árbol de archivos.

Con PIC Compiler en algunos casos si es necesario definir algunos registros o sus bits, pero es raro el caso.

Yo he usado el ADC en un dsPIC30F4013 y no tuve problemas.

No tengo el dsPIC33FJ12MC202 para hacer pruebas en físico, pero mira el ejemplo adjunto para que lo tomes como referencia.

Por los mensajes de advertencia del simulador sobre SIMSAM y ASAM no te preocupes, porque cuando yo probé el circuito en físico, funcionó bien.
 

Adjuntos

  • dsPIC33FJ12MC202 2 ADC.rar
    28.7 KB · Visitas: 32
Última edición:
Muchas gracias por tu respuesta D@rkbytes.

En cuanto al ejemplo que amablemente compartiste, tengo algunos comentarios. El muestreo que efectúas en el programa no es simultaneo, veo que hay retardos, lo que lo hace consecutivo, una muestra después de la otra. Lo que quiero hacer es calcular la potencia instantánea de un circuito de 120 VCA (debo implementar el dsPIC en físico), por medio de un transformador reductor y un sensor de efecto hall, ambas señales de voltaje las llevaré a un acondicionador de voltaje (AdV1 y AdV2), tal como se muestra en la siguiente imagen:

interface de medición.png

En cuanto al programa que compartiste, veo que tienes:

Código:
#use     delay(crystal = 20MHz)
setup_adc(ADC_CLOCK_DIV_2|VSS_VDD);

y yo tengo:

Código:
#USE DELAY(CLOCK=80M)
setup_adc(ADC_CLOCK_DIV_8);

Aquí mi explicación del por qué lo tengo configurado así, la siguiente imagen sirve de apoyo:
Ecuacion y Diagrama - Datasheet.png

Si vemos la ecuación 7-3 y nos apoyamos en la nota de la página 95 del datasheet, con un cristal de 20MHz tenemos una Fosc=80MHz, Tosc=12.5 ns.

Tosc sigue siendo pequeño en comparación con Tad=65 ns (pág 266 del datasheet), para lograr que el reloj de conversión del ADC sea mayor, requerimos un ADC_CLOCK de 8.
12.5 ns * 8 = 100 ns lo que nos lleva a un Tad=100 ns (setup_adc(ADC_CLOCK_DIV_8)).

Como ya lo mencionaba el muestreo simultáneo se habilita activando el bit SIMSAM, pero una vez que lo habilito, como hago para acceder a la lectura del valor de los canales AN0 y AN1, es decir como obtengo sus valores individuales, esto último sé que no es al mismo tiempo pero sus valores se tomaron al mismo tiempo.

Sin más de momento muchas gracias por estar interesado D@rkbytes.
 
Antes que nada una disculpa por no aclarar mi objetivo desde el principio.

Muchas gracias por la información D@rkbytes, estuve leyendo el manual que me proporcionaste en conjunto con el datasheet del dsPIC33FJ12MC202 y al parecer este dsPIC no tiene DMA (creo que significa Direct Memory Access), por lo tanto el manual que menciona el datasheet es Section 28. Analog-to-Digital Converter (ADC) without DMA para la familia dsPIC33F. Hasta ahorita lo que he leído y entendido, tengo que configurar el formato de salida del ADC con los bits FORM<1:0> del registro AD1CON1. de la siguiente manera:

Formato de Salida de ADC.png

Creo que el formato de salida que más me conviene es el de FORM<1:0>: 0b00 (el de hasta abajo) de la imagen anterior.

Para después acceder a las lecturas de los canales AN0 (ADC1BUF1) y AN1 (ADC1BUF2).

Voy a intentar obtener las lecturas de esta manera y comento haber como me fue.

Duda D@rkbytes, en la simulación que me pasaste, no envía los valores decimales al puerto serie verdad? me aparece lo siguiente:

Simulación D@rkbytes.png

Estoy usando la versión 7.7 de Proteus.
 
Duda, D@rkbytes ¿En la simulación que me pasaste, no envía los valores decimales al puerto serie, verdad?

Estoy usando la versión 7.7 de Proteus.
Si envía la cadena con decimales, pero tal vez algo cambiaste, porque se debe ver de la siguiente forma:

Captura 2 ADC.jpg

La simulación la realicé con Proteus v7.10 SP 0
 
Que tal muy buenos días.

Después de quebrarme la cabeza intentando efectuar el muestreo simultaneo, un profesor del Instituto Tecnológico de Morelia, el profesor Gustavo Velázquez Gaytán fue quién hizo el código de programa y me lo compartió ya que él es mi asesor de proyecto de titulación. El código no se ha probado físicamente pero estoy seguro de que funciona sin problemas.

Adjunto el código y la simulación
 

Adjuntos

  • Muestreo Simultaneo Gustavo Velázquez.rar
    16.4 KB · Visitas: 60
Atrás
Arriba