Problema con la comunicación SPI cuando se usa el aislador digital Silabs Si86xx

1

Estoy tratando de establecer una comunicación entre Atmel Atmega32U4 (utilizado en Arduino Leonardo) en MCU PCB y TI DAC8552 en PSU PCB a través de enlace SPI aislado. Para el aislamiento, estoy usando Silicon Labs Si86xx aislador digital que puede funcionar Hasta 150MHz. Si bien todo funciona como se esperaba SIN el aislador, obtuve resultados bastante extraños cuando el aislador se colocó entre el dispositivo MCU y el dispositivo DAC. Para las pruebas se utiliza un boceto de Arduino muy simple que envía en bucle infinito dos valores al DAC cada uno de los últimos 20 ms:

#include "SPI.h"
int DAC2_SELECT=5; // uncomment this line if Arduino board is used instead of PSU MCU board
int IO_EXPANDER2=6; // uncomment this line if Arduino board is used instead of PSU MCU board
int ADC2_SELECT=13; // uncomment this line if Arduino board is used instead of PSU MCU board

int var=0;

void setup()
{  
  // Deselect devices that share same SPI bus on the PSU post-regulator board
  pinMode(ADC2_SELECT, OUTPUT);
  digitalWrite(ADC2_SELECT, HIGH); // Deselect ADS1120
  pinMode(IO_EXPANDER2, OUTPUT);
  digitalWrite(IO_EXPANDER2, HIGH); // Deselect MCP23S08  

  // Initialize DAC8552
  pinMode(DAC2_SELECT, OUTPUT);
  SPI.begin(); // wake up the SPI bus.
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(0);  //CPOL=0, CPHA=0
  // SPI.setClockDivider(SPI_CLOCK_DIV16); // Slow down SPI clock speed to 1MHz for testing purpose

  digitalWrite(DAC2_SELECT, LOW);
  SPI.transfer(B00100100); // Write to Data Buffer B
  SPI.transfer(0x99); // send first byte
  SPI.transfer(0x99);  // send second byte  
  digitalWrite(DAC2_SELECT, HIGH); // Deselect DAC
}

void loop()
{
  digitalWrite(DAC2_SELECT, LOW);
  SPI.transfer(B00010000); // Write to Data Buffer A
  SPI.transfer(0x20); // send first byte
  SPI.transfer(0x00);  // send second byte  
  digitalWrite(DAC2_SELECT, HIGH); // Deselect DAC
  delay(20);

  digitalWrite(DAC2_SELECT, LOW);
  SPI.transfer(B00010000); // Write to Data Buffer A and activate channel A
  SPI.transfer(0x80); // send first byte
  SPI.transfer(0x00);  // send second byte  
  digitalWrite(DAC2_SELECT, HIGH); // Deselect DAC 
  delay(20);
}

El esquema derivado de uno muy complejo se muestra a continuación:

ResultadosSINaislador:

Conexión entre MCU y PSB PCB:

EstoesloqueobtuvecuandoseagregóaisladorentreMCUyDAC:

Lo probé utilizando el aislador en MCU PCB ...

perotambiénparaasegurarsedeusarelaisladorconectadoeneltableroparaasegurarsedequealgoestáconectadoincorrectamentealaPCBMCU:

Tenga en cuenta que la PCB de MCU tiene dos conectores IDC de 10 pines: el negro es un SPI no aislado y el gris está aislado SPI donde la parte "remota" del dispositivo aislador se suministra desde una fuente externa (PSU PCB). Intencionalmente, utilicé el mismo cable plano, y la longitud del cable no parece ser un problema, ya que todo funciona correctamente sin aislador. Para estar completamente seguro, traté de reducir la velocidad del reloj SPI tanto como sea posible, incluso a 125 kHz (se divide por 128 de 4 MHz por defecto o se divide por 4). Nada ayuda en caso de aislador: recibo continuamente valores aleatorios en la salida en lugar de dos fijos. También probé la siguiente conexión "híbrida" en la que MOSI y el chip select (ADC2_SELECT) pasan por el aislador y SCLK está conectado directamente, mientras que la conexión a tierra MCU NO ESTÁ conectada a la conexión a tierra remota "PSU". Para mi sorpresa, esa combinación funciona, pero no puedo explicar por qué. La verificación de la señal desde ambos lados del aislador no muestra nada sospechoso: la duración de la señal en el lado "remoto" es ligeramente más corta ya que el aislador tiene la lógica de activación Schmitt incorporada.

Se me acabaron las ideas sobre qué probar a continuación, así que si alguien tiene alguna sugerencia, hágamelo saber.

EDITAR 2015-06-08: Estoy agregando a continuación dos capturas de pantalla una al lado de la otra, donde a la izquierda se encuentra el DAC cuando SPI está conectado directamente. Parece que la configuración del nuevo valor está sincronizada pero, por alguna razón, el valor se "desplaza" hacia arriba o hacia abajo en caso de un valor más bajo (0x20).

Cuandoelcambioesde0x70a0x80,obtuvelosiguiente:

EDICIÓN 2015-06-09: A continuación, encontrará más medidas sugeridas por Tom L. Todo se realiza en el tablero, se usan los mismos cables y el cable plano que en los resultados presentados inicialmente. Las conexiones a ambos lados del aislador están unidas, el "remoto" (o lado B) se suministra desde la PCB de la PSU, el host (o el lado A) desde Arduino Leonardo. Primero me cansé de usar el cableado mencionado de la conexión directa SPI y funciona como se esperaba. En el primer paso, SCLK y MOSI permanecen directamente conectados. CS (ADC2_SELECT) pasa el aislador. Todos los pines del aislador no utilizados están conectados a tierra. DAC funciona como se puede ver en las siguientes dos capturas de pantalla (S1 es el lado del host, S2 es el lado remoto en el dispositivo aislador, la señal DAC es una salida analógica en el pin 4 de DAC8552 (VOUTA):

Lo mismo cuando MOSI pasa por el aislador y SCLK y CS se mantuvieron directamente conectados:

Y ahora tenemos un problema que persiste y no puedo entender qué está pasando: cuando SCLK pasa por el aislador, la comunicación se detiene, independientemente del hecho de que la señal se ve bien en ambos lados del aislador. Tenga en cuenta que en el rastreo DAC no hay más cambios. Ese es uno de los dos escenarios posibles. Ya se describió otro (los valores aleatorios se presentan en la salida DAC).

Estoy agregando un escenario adicional cuando SCLK está conectado al lado del host a través de un condensador. En ese caso, el DAC comienza a comportarse con regularidad incluso cuando los terrenos no están unidos. Por favor encuentre abajo el esquema y el resultado:

    
pregunta prasimix

2 respuestas

0

Toda la miseria es generada por el modo de reloj SPI declarado erróneamente. Incluso puse en el boceto el siguiente comentario: CPOL = 0, CPHA = 0 que es SPI_MODE 1 y para eso en Arduino IDE existe una constante SPI_MODE1 que es no igual a 0.

Por lo tanto, para el correcto funcionamiento se debe utilizar el siguiente comando:

SPI.setDataMode(SPI_MODE1);

EDITAR: Mi comprensión de CPHA estaba equivocada. CPHA 0 no es flanco descendente, lo que requiere DAC8552, sino flanco ascendente. El CPHA correcto tiene que ser 1 y no 0.

    
respondido por el prasimix
0

Esa señal de salida parece que conectaste dos salidas entre sí (¿SDO?) o un reloj a alguna otra salida. Apague su dispositivo y mida si sus conexiones son correctas.

También, qué parte está utilizando exactamente, ya que hay algunas variantes con diferentes configuraciones de entrada / salida.

Editar 2015-06-08:

Bien, tendremos que hacerlo paso a paso.

  1. Conecte las conexiones a tierra (lado primario y secundario del aislador). Esto asegurará que sean realmente el mismo potencial.
  2. Verifique que haya configurado los pines en su microcontrolador correctamente (deshabilite las funciones internas, por lo que debería ver que realmente los está utilizando como salidas y no como configuración de Alta Z / Baja)
  3. Verifique que su conexión funcione sin el aislador.
  4. Conecte CS a través del aislador, mida el nivel antes y después del aislador y verifique si su conexión funciona. Deja todas las demás conexiones conectadas directamente.
  5. Ahora haga lo mismo para MOSI (use el mismo pin en su aislador como lo hizo antes con CS)
  6. Haga lo mismo con SCLK (nuevamente, use solo el pin en el aislador que probó antes)

¿Qué elementos funcionan y cuáles no?

    
respondido por el Tom L.

Lea otras preguntas en las etiquetas