TODOPIC

FORO TÉCNICO => Foro Técnico => Mensaje iniciado por: DarkVect en 01 de Febrero de 2008, 08:48:29

Título: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 01 de Febrero de 2008, 08:48:29
Hola amigos,

Tengo que diseñar un transmisor de 4-20mA con dos canales. Mi idea es utilizar un PIC16F para capturar las medidas de los sensores y luego un conversor a 4-20mA para enviar la inforamción.

He visto algunos conversores como el AD420 que funcionan con SPI y con una resolución de 16bits para el rango de 4 a 20mA. El problema es que necesitaría 2 SPI, uno por canal, o un multiplexor que pueda trabajar a la velocidad del SPI y que no sea muy armatoste.

Por otro lado también he visto algunos conversores analógicos que funcionan bien con un PWM a su entrada. El problema con éstos es que el rango de entrada es de 0 a 2V típicamente y el PWM me va de 0 a 5V y no quiero añadir más componentes externos para reducirlo. Por otro lado he visto el XTR115 (http://focus.ti.com/lit/ds/symlink/xtr115.pdf) que me funcionaría muy bien ya que la entarda es escalable con una simple resistencia pero de nuevo aparece el PWM que con 256 valores no me da mucha resolución para lo que quiero medir ya que necesito mínimo 360 puntos.

Se os ocurre alguna otra forma de hacerlo o alguna pista?

Gracias!!
Título: Re: 4-20mA Current Loop
Publicado por: Nocturno en 01 de Febrero de 2008, 09:04:52
¿Y no te sirve el que has visto si implementas el SPI por software?, realmente consume muy poquitos ciclos.
Título: Re: 4-20mA Current Loop
Publicado por: MGLSOFT en 01 de Febrero de 2008, 09:13:08
Igual que dice Manolo, yo me inclinaria por hacer el SPI por software y usar el AD420.
Si usas C es mas facil aun... :mrgreen:
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 01 de Febrero de 2008, 09:30:01
Por lo que veo al AD420 se le puede igresar una entrada "tipo serie" siguiendo las especificaciones del datasheet por lo que con un par de AD420 ya lo tendría resuelto con buena precisión.

Cómo hago el protocolo por software? Sería algo del estilo crear una función: enviar_dato()  a la que le paso el valor a enviar con 16bits y dentro de la función ir activando el pin de datos y el del reloj hasta enviar el dato completo?

Tenéis algún ejemplo de cómo se implementa una comunciación sin utlizar las funciones predefinidas? Es que siempre he utilizado RS-232 con todo predefinido.

Muchas gracias!!
Título: Re: 4-20mA Current Loop
Publicado por: Nocturno en 01 de Febrero de 2008, 09:32:46
Recientemente he utilizado SPI por software. Te pongo el equivalente a la función spi_write() del CCS pero hecho a mano:
void EscribeSPI(int8 Dato) {
   int8 j=8;
   while (j--) {
      SPI_SOUT = (Dato >> j) & 1;
      SPI_CLK=0;
      SPI_CLK=1;
   }
}
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 01 de Febrero de 2008, 09:37:49
Gracias Nocturno.

La función que me has dejado no lleva ningún delay, no habrá problemas con los tiempo de hold y setup de los datos?
Para enviar los 16 bits puedo encadenar dos veces la función o podría tener un problema de temporización?  El AD420 tiene también una entrada Latch que es la que carga el valor del registro de entrada al CDA. Con activarla justo después de enviar dato ya es suficiente, no?
Título: Re: 4-20mA Current Loop
Publicado por: Nocturno en 01 de Febrero de 2008, 09:42:39
Es que no he usado nunca ese ADC que indicas; yo la he usado con un expansor de puertos MPC23S17 y va de lujo a esta velocidad y sin retardos.
Es verdad que antes y después de la comunicación hay que activar y desactivar el ChipSelect de tu AD420, pero no lo integré en el envío del dato, porque esto me permite encadenar varios datos seguidos.
Digamos que hay una rutina superior que hace lo siguiente:
Código: [Seleccionar]
Activa ChipSelect;
EscribeSPI(Dato1);
EscribeSPI(Dato2);
...
EscribeSPI(DatoN);
Desactiva ChipSelect;
También tienes que ver si tu AD420 recibe el dato en Clock positivo o en clock negativo. Esta rutina está preparada para el segundo caso, por eso pongo SPI_CLK=0 cuando el dato está cargado.
Si tu cacharro lo espera al contrario, sólo tendrás que poner primero el 1 y luego el 0.
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 01 de Febrero de 2008, 09:48:32
OK! En principio creo que lo tengo claro. La semana que viene me llega todo y probaré a ver qué tal sale.

Muchas gracias!!
Título: Re: 4-20mA Current Loop
Publicado por: MGLSOFT en 01 de Febrero de 2008, 09:49:40
Para establecer el protocolo SPI por software, necesitas cumplir los timings que dice la hoja de datos, con la ayuda de Manolo, podras hacer tu rutina.

(http://img341.imageshack.us/img341/6269/ad420gc6.jpg)
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 01 de Febrero de 2008, 12:11:18
Eso mismo preguntaba. Supongo que tengo que calcular la velocidad a la que el PIC me va a ir escribiendo cada dato según el reloj que le ponga y de ahí mirar si cumplo el timing.
Título: Re: 4-20mA Current Loop
Publicado por: MGLSOFT en 01 de Febrero de 2008, 13:10:29
Es muy importante saber en que lenguaje programas, para ayudarte a hacer el driver... :mrgreen:
Título: Re: 4-20mA Current Loop
Publicado por: MGLSOFT en 01 de Febrero de 2008, 13:17:43
Aqui un ejemplo puesto por un forista de CCS C.

Código: C
  1. #include <18F452.h>
  2. #use delay(clock=16000000)
  3. #fuses HS,NOWDT,NOLVP,PUT,NOPROTECT,BROWNOUT
  4.  
  5. #define AD420_LATCH  PIN_D1
  6. int16 val = 0x7fff;           // Half scale
  7.  
  8. void main(void)
  9. {
  10.    setup_spi(spi_master | spi_l_to_h |spi_clk_div_16);
  11.  
  12.    output_low(AD420_LATCH);
  13.    
  14.    spi_write(val >> 8);    // Send msb
  15.    spi_write(val & 0xff);  // Send lsb
  16.    
  17.    output_high(AD420_LATCH);
  18.    
  19.    while(1);               // Dac output should be half full scale    
  20. }    
  21.  

Por supuesto que falta, pero es una punta... :mrgreen:
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 01 de Febrero de 2008, 13:27:17
Utilizo CCS. Gracias!!
Título: Re: 4-20mA Current Loop
Publicado por: Nocturno en 01 de Febrero de 2008, 14:37:01
¡Ojo!, ese ejemplo sirve pero usando el hardware del PIC. Si tienes los pines ocupados por otra cosa, no podrás usarlo tal y cual está ahí.
Título: Re: 4-20mA Current Loop
Publicado por: MGLSOFT en 01 de Febrero de 2008, 15:56:03
Tiene razon Manolo.
Pero si tienes un PIC con SPI en hardware, los dos AD420 los conectas en cascada y puedes tirarles el datos con un solo bus SPI... :mrgreen:

En caso de hacerlo por software, deberias hacer que tu funcion maneje 16 bits, quedaria algo asi (con permiso de Manolo):

Código: C
  1. void EscribeSPI(int16 Dato) {
  2.    int8 j=16;
  3.    while (j--) {
  4.       SPI_SOUT = (Dato >> j) & 1;
  5.       SPI_CLK=0;
  6.       SPI_CLK=1;
  7.    }
  8. }

Espero te sirva, ahora tienes las dos opciones, avisa si anda, porque mas adelante debo escribir un AD420 y ya me queda, je..je.. :mrgreen: :mrgreen:
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 04 de Febrero de 2008, 12:04:27
Todavía no he recibido los AD420 pero tranquilos que os manetndré inforamdos de todo.

Un par de preguntas más. Cómoconecto dos AD420 a un mismo SPI? Puedo compartir reloj y datos y sólo utilziar el LACTH para validar los datos en uno u otro AD420?

Por otro lado tengo un "problemilla" de resoluciones. La entrada la capturo con el ADC del PIC a 8bits. Y al AD420 le tengo que enviar un valor en 16bits por lo que mis saltos en valores del AD420 serán de 256 en 256, es decir, si el valor del ADC es 50 el que le mando al AD420 es de 50*256 cosa que me da un salto en corriente de salida de 0,062464mA -> 0,0624mA/(20mA-4mA)=0,4% de error, es correcto?
Título: Re: 4-20mA Current Loop
Publicado por: MGLSOFT en 04 de Febrero de 2008, 13:06:05
Porque no utilizas el conversor a 10 bits, si usas un 16F eso es posible y tienes 4 veces mas resolucion!!
Por lo demas, debes enviar los valores al AD420 usando una regla de conversion del dato, escalandolo de 10 a 16 bits...

Respecto a como conectar varios DAC AD420, en la hoja de datos dicen que es asi:   :mrgreen: :mrgreen:

(http://img171.imageshack.us/img171/1331/multiplesad420yb9.jpg)
Título: Re: 4-20mA Current Loop
Publicado por: DarkVect en 04 de Febrero de 2008, 15:25:14
OK!! Gracias!! Lo tenía delante!! Para mandar los 32 bits que dice que hay que mandar puedo seguir utilizando la misma rutina incluyendo en lugar de (int16 dato) -> (int16 Dato1, int 16 Dato2) y enviando uno después del otro, no?

Nunca he usado los 10 bits del ADC por la facilidad de tratarlo todo como int8 pero supongo que la mejor forma es aprovecharlo. Ya os contaré!!
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 19 de Febrero de 2008, 15:48:00
Bueno, pues ya me han llegado los AD420 y he podido trastear un poquito con ellos.

El código que os adjunto va incrementando la variable 'val' de 500 en 500 y la va enviando por SPI al AD420. A la salida del loop del AD420 tengo una resistencia de 200 ohmios en la que se ve la caída de tensión producida por la corriente.

Al empezar el téster marca 0,80V clavados y va aumentando poco a poco. No lo he mirado mucho pero al llegar a medio rango (2,4V) se me reinicia y vuelve a 0,80... seguiré investigando.

Código: [Seleccionar]
#include <16F818.h>                                //PIC a utilizar

#fuses XT                                          //configuracion de fusibles
#fuses NOWDT
#fuses PROTECT
#fuses PUT
#fuses NOBROWNOUT
#fuses MCLR
#fuses NOLVP
#fuses CPD
#fuses NOWRT
#fuses NODEBUG

#use delay (clock=4000000)
#use fast_io(a)

#define LED          PIN_A1                        //LED de funcionamiento
#define AD420_LATCH  PIN_B3


void main(void)
{
   int16 val=0;

   disable_interrupts(GLOBAL);                     //deshabilitar interrupciones
   disable_interrupts(INT_EEPROM);                 //deshabilitar interrupcion EEPROM
   disable_interrupts(INT_RB);                     //deshabilitar interrupcion portb
   disable_interrupts(INT_TIMER0);                 //deshabilitar interrupcion del timer0
   disable_interrupts(INT_TIMER1);                 //deshabilitar interrupcion timer1
   disable_interrupts(INT_TIMER2);                 //deshabilitar interrupcion timer2
   disable_interrupts(INT_CCP1);                   //deshabilitar interrupcion CCP1
   disable_interrupts(INT_SSP);                    //deshabilitar interrupcion I2C / SPI
   disable_interrupts(INT_AD);                     //deshabilitar interrupcion ADC
   disable_interrupts(INT_EXT);                    //deshabilitar interrupcion RB0

   setup_TIMER_0(RTCC_INTERNAL | RTCC_DIV_1);      //preescaler=1
   setup_TIMER_1(T1_DISABLED);                     //desactivar timer1
   setup_TIMER_2(T2_DIV_BY_1,255,16);              //preescaler=16
   setup_CCP1(CCP_OFF);                            //desactivar modulo captura
   setup_SPI(spi_master | SPI_L_TO_H | SPI_CLK_DIV_16);
   setup_ADC_PORTS(AN0);                           //entradas analogicas
   setup_ADC(ADC_CLOCK_INTERNAL);                  //activar modulo ADC

   set_tris_a(0b00000000);                         //porta todo como salida
   set_tris_b(0b00000010);

   ext_int_edge(H_TO_L);                           //interrupcion externa en flanco de bajada

   port_b_pullups(TRUE);                           //pullups portb activadas

   enable_interrupts(GLOBAL);                      //interrupciones activadas

   delay_ms(1000);

   do
   {
      output_toggle(LED);

      output_low(AD420_LATCH);

      spi_write(val >> 8);                         // Send msb
      spi_write(val & 0xFF);                       // Send lsb

      output_high(AD420_LATCH);

      delay_ms(1000);
      val=val+500;

   }while(TRUE);
}
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: MGLSOFT en 19 de Febrero de 2008, 15:56:56
Podras poner aqui el esquema del circuito que usas, al menos una imagen de un esquema a mano sirve...
Asi podremos ser de mas ayuda... :mrgreen:
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 19 de Febrero de 2008, 16:04:31
Me marcho ya del despacho, pero mañana la pongo. Básicamente es la configuración del Datasheet con los condensadores que pide. Luego tengo el Data_In del AD420 a la salida SPI del PIC, el reloj igual y luego utilizo el pin B3 para hacer de Latch del AD420.

Lo raro es que si directamente le digo al PIC que envíe el valor 0xFFFF el AD420 se pone de inmediato a 4,0V de salida.

Debe de haber algún error tonto en el código.
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: MGLSOFT en 19 de Febrero de 2008, 16:10:20
Estas seguro que hay que enviar primero el MSB ?? :mrgreen:

Verificalo en la hoja de datos...
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 20 de Febrero de 2008, 06:24:14
Según veo en el Datasheet va primero el MSB:

(http://img403.imageshack.us/img403/9283/dibujolb0.png)
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 20 de Febrero de 2008, 07:03:14
Más o menos voy viendo por dónde van los tiros. Con el código siguiente primero le mando 0x0000 para que la salida de ponga a 0,80V (4mA) y luego le mando 0xFFFF para que se ponga a 4,0V (20mA). Lo que físicamente observo es que la salida empieza a 0,80V, luego mando el 0xFFFF y la salida pasa a la mitad del rango (2,4V) y la siguiente vez si que se pone a los 4,0V.

Parece como si entre medio hubiese algo que no lo entiende.

Código: [Seleccionar]
#include <16F818.h>                                //PIC a utilizar

#fuses XT                                          //configuracion de fusibles
#fuses NOWDT
#fuses PROTECT
#fuses PUT
#fuses NOBROWNOUT
#fuses MCLR
#fuses NOLVP
#fuses CPD
#fuses NOWRT
#fuses NODEBUG

#use delay (clock=4000000)
#use fast_io(a)

#define LED          PIN_A1                        //LED de funcionamiento
#define AD420_LATCH  PIN_B3


void main(void)
{
   int16 val=0;

   disable_interrupts(GLOBAL);                     //deshabilitar interrupciones
   disable_interrupts(INT_EEPROM);                 //deshabilitar interrupcion EEPROM
   disable_interrupts(INT_RB);                     //deshabilitar interrupcion portb
   disable_interrupts(INT_TIMER0);                 //deshabilitar interrupcion del timer0
   disable_interrupts(INT_TIMER1);                 //deshabilitar interrupcion timer1
   disable_interrupts(INT_TIMER2);                 //deshabilitar interrupcion timer2
   disable_interrupts(INT_CCP1);                   //deshabilitar interrupcion CCP1
   disable_interrupts(INT_SSP);                    //deshabilitar interrupcion I2C / SPI
   disable_interrupts(INT_AD);                     //deshabilitar interrupcion ADC
   disable_interrupts(INT_EXT);                    //deshabilitar interrupcion RB0

   setup_TIMER_0(RTCC_INTERNAL | RTCC_DIV_1);      //preescaler=1
   setup_TIMER_1(T1_DISABLED);                     //desactivar timer1
   setup_TIMER_2(T2_DIV_BY_1,255,16);              //preescaler=16
   setup_CCP1(CCP_OFF);                            //desactivar modulo captura
   setup_SPI(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
   setup_ADC_PORTS(AN0);                           //entradas analogicas
   setup_ADC(ADC_CLOCK_INTERNAL);                  //activar modulo ADC

   set_tris_a(0b00000000);                         //porta todo como salida
   set_tris_b(0b00000010);

   ext_int_edge(H_TO_L);                           //interrupcion externa en flanco de bajada

   port_b_pullups(TRUE);                           //pullups portb activadas

   enable_interrupts(GLOBAL);                      //interrupciones activadas

   delay_ms(1000);
   output_low(LED);

   do
   {
      output_toggle(LED);

      output_low(AD420_LATCH);

      spi_write(val >> 8);                         // Send msb
      spi_write(val & 0xFF);                       // Send lsb

      output_high(AD420_LATCH);

      val=65535;
      delay_ms(8000);

   }while(TRUE);
}
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 20 de Febrero de 2008, 07:28:37
Subo el esquema para quien quiera utilizarlo:

(http://img403.imageshack.us/img403/916/dibujolp1.png)

Una pregunta más, alguien sabe cómo puedo saber si el SPI debe ir SPI_L_TO_H o SPI_H_TO_L??

Gracias!!
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 20 de Febrero de 2008, 07:36:43
SOLUCIONADO Y FUNCIONANDO!!

Me respondo a mi mismo. El AD420 requiere que el SPI se configure con el SPI en SPI_H_TO_L.

Ahora el programa ese que va incrementando val de 500 en 500 funciona perfectamente y con una precisión extraordinaria.

Espero que os pueda servir para vuestros proyectos.

Un saludo!!
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: MGLSOFT en 20 de Febrero de 2008, 08:16:36
Felicitaciones!!
Ahora si que me animo a usarlo yo!! :D :D
Me alegro que hayas llegado a buen termino. :mrgreen:
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 20 de Febrero de 2008, 08:28:18
La verdad es que temía bastante que el tema del SPI me amargara pero por suerte en la primera prueba que hice conseguí que el AD420 respondiera, mal pero respondiera. A partir de ahí ha sido ir depurando el fallo.

Me ha sorprendido la facilidad de uso del SPI. Con 4 líneas lo tienes enviando lo que quieras. Ahora sólo me falta hacer la prueba de enlazar los dos AD420 en serie a ver si consigo que ambos respondan correctamente.

Un saludo!!
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: DarkVect en 21 de Febrero de 2008, 08:58:50
Comentar que ya tengo los 2 AD420 en serie y todo va de maravilla. El proceso sigue el mismo esquema que con uno, simplemente hay que transmitir 32 bits en lugar de los 16 y ya está.

Un saludo!!
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: MGLSOFT en 21 de Febrero de 2008, 09:05:44
Bravo !!! :-/ :-/
Título: Re: 4-20mA Current Loop (SOLUCIÓN AD420)
Publicado por: stk500 en 21 de Febrero de 2008, 16:38:01
en hora buena amigo  :-/ :-/ :-/ yo estoy con un ADC8800 ya contare  :lol: