Interfaz AD7811 ADC con Arduino sobre SPI

TL; DR: no obtengo los valores correctos del AD7811 ADC. Le doy al ADC una entrada desde mi fuente de alimentación de sobremesa (Tenma 72-2540) a la entrada analógica 1, y obtengo varios resultados (y siempre tremendamente incorrectos) (aunque hay cierta coherencia, ¡sigue leyendo!). Tengo preguntas adicionales sobre la parte que podría ser más adecuada para una publicación separada.

Más detalles sobre el problema.

Quería probar rápidamente el ADC AD7811 con mi Arduino Mega 2560 ya que planeo usar el AD7811 para un proyecto de pasatiempo, y es ligeramente diferente al único ADC SPI que he usado antes (no hay una "selección de esclavo" dedicada per se en el AD7811, tiene una combinación de inicio de conversión, inicio de trama de recepción e inicio de trama de transmisión). Al vincular CONVST, RFS y TFS, parece que debería funcionar de manera similar a la forma en que Slave Select funciona normalmente para dispositivos SPI. No usaré el Mega en mi proyecto final, simplemente fue más rápido ponerlo en marcha.

Circuito Aquí hay un diagrama de mi circuito, está implementando el "Diagrama de conexión típico" que se encuentra en la página 10 de la hoja de datos. (También he incluido una captura de pantalla de esto debajo de mi circuito)

Esquema de Arduino conectado a AD7811

Diagrama de conexión típico de la hoja de datos

fotografías de conexiones

Aquí hay algunas fotos que muestran cómo tengo todo conectado.

Vista de arriba hacia abajo de la placa de prueba

Primer plano de las conexiones ADC

Vista de macros

Código

    #include <SPI.h>

const int convst = 42;  // CONVST pin on AD7811 connected to Pin 42 on Arduino
uint16_t return_val = 0;

// value to transfer to the control register (see page 7 of the datasheet)
uint16_t control = 0B1011000011; 

void setup() {
  // start the SPI library:
  SPI.begin();
  SPI.beginTransaction(SPISettings(2000, MSBFIRST, SPI_MODE0));
  pinMode(convst, OUTPUT);
  digitalWrite(convst, HIGH);
  Serial.begin(9600);
}

void loop() {
  digitalWrite(convst, LOW); // Initiate the conversion process. Since TFS is also brought low, MOSI data is latched into the ADC (page 16)
  SPI.transfer(control>>2); // Transfer first 8 MSB of control settings (page 7 datasheet) i.e. 0B10110000 
  SPI.transfer(control<<6); // Transfer last 2 bits of control settings i.e. 0B11000000

  delayMicroseconds(3);      // Conversion process takes at most 2.3us 
  digitalWrite(convst, HIGH);// Bring CONVST, RFS and TFS high. First sentence of page 16 indicates that this would cause the result to be put on the SPI bus
  delayMicroseconds(1);
  return_val = SPI.transfer16(0); //read the 10 bit result
  return_val = return_val >> 6;   //SPI.transfer16 stores our result as a 16 bit number, but ADC only has 10bit resolution. Rightshift by 6 to correct this error. 

  Serial.println("Return");
  Serial.println(return_val); //print the value that we got back
  delay(1000);
}

Valores devueltos

Como dije en TL;DR, los valores que obtengo siempre son "incorrectos" (quizás "no es lo que esperaba" es mejor), pero no son necesariamente los mismos valores cada vez. Por ejemplo, al alimentar 1 V CC a la Entrada 1 del ADC, obtengo los valores 617, 616, 105 y 104 como mis valores de retorno que estoy imprimiendo en la salida en serie (esto es después de cambiar 6 bits a la derecha). No hay un patrón discernible real, sin embargo, siempre es uno de estos 4 valores. Para una entrada de 1 VCC y con Vref a 5 VCC, esperaría alrededor de 204 o 205 como valor de retorno (1/5 * 1024). Si cambio a una entrada de 2 V CC, obtengo 722, 721, 210, 209.

Capturas de alcance

  1. Prueba de que se está escribiendo en el registro de control (línea MOSI)

La configuración de control parece estar dejando el Arduino en la línea MOSI. Hay un "fallo" (¿terminología?) que ocurre cuando se transfiere 0 desde SPI.transfer16(): mira la imagen a continuación, hay un pico corto de ~300 ns de duración alrededor del borde descendente del octavo ciclo de reloj. No estoy seguro de por qué ocurre esto, le digo a Arduino que escriba un 0 para esta transacción. El azul es SLCK, el rojo es MOSI (pin 51 Arduino)

Escribir en el registro de control, así como escribir 0 como parte del proceso de lectura

Error en el proceso de escritura

  1. línea MISO

Naturalmente, quería comprobar la respuesta del ADC. El azul es SCLK, el rojo es MISO (pin 50 en Arduino)

línea MISO

He notado que, ocasionalmente, hay una caída exponencial en los últimos 7 ciclos de reloj (y algo más). No estoy seguro de qué hacer con esto, pero no se ve bien.

MISO con decaimiento exponencial

  1. Selección de fichas

El rojo es CONVST, RFS y TFS (unidos). Una vez que baja, el reloj en serie comienza a funcionar y los datos se transfieren (de la manera que se muestra en las capturas de alcance anteriores). El azul es SLCK, el rojo es CONVST/RFS/TFS (pin 42)

Tiempo de selección de fichas

  1. Comprobación de la entrada analógica 1

La entrada al ADC parece estar limpia, la pasé por alto con un capacitor de 10nF para ayudar a limpiar la entrada.

Captura de entrada ADC

Todavía soy bastante nuevo en hacer mis propios diseños digitales, la segunda vez que uso SPI, ¡así que realmente agradecería cualquier sugerencia o consejo! Si falta alguna información que necesites, te la conseguiré. Estoy dispuesto a mejorar en todo lo que pueda, ¡incluidas mis habilidades para solucionar problemas!

Respuestas (1)

Por ejemplo, al alimentar 1 V CC a la Entrada 1 del ADC, obtengo los valores 617, 616, 105 y 104 como mis valores de retorno que estoy imprimiendo en la salida en serie (esto es después de cambiar 6 bits a la derecha). No hay un patrón discernible real, sin embargo, siempre es uno de estos 4 valores. Si cambio a una entrada de 2 V CC, obtengo 722, 721, 210, 209.

Tenga en cuenta las diferencias entre los valores:

  • 617 - 105 = 512
  • 616 - 104 = 512
  • 722 - 210 = 512
  • 721 - 209 = 512

Está claro que tiene problemas para leer correctamente el noveno bit del valor: 2 9 = 512. A veces obtiene "1" y otras veces obtiene "0".

La variación de un conteo (617 frente a 616, etc.) es simplemente un error de cuantificación normal.


He notado que, ocasionalmente, hay una caída exponencial en los últimos 7 ciclos de reloj (y algo más). No estoy seguro de qué hacer con esto, pero no se ve bien.

En realidad, eso es perfectamente normal. Durante un ciclo de lectura, el AD7811 solo maneja datos durante los primeros diez ciclos de reloj, luego procesa su salida. Si el último bit de datos (el LSB de la lectura) es 1, el voltaje de la señal decae lentamente cuando se apaga el controlador. Estás ignorando esos últimos 6 bits de todos modos.


En general, diría que lo más sospechoso que veo es el tiempo en su línea MOSI. El AD7811 espera que los datos sean estables durante el flanco descendente del reloj, pero en sus trazas, ahí es cuando parece estar cambiando. Es posible que deba cambiar los modos en su maestro SPI entre escritura y lectura para hacerlo bien.

Esa es una de las peores cosas del "estándar" SPI: hay cuatro formas diferentes de configurar cómo se controla el reloj en relación con los datos (tanto lectura como escritura), y a veces es difícil inferir la configuración requerida de la hoja de datos de un dispositivo. .

Aprecio que mires esto. Aparte del noveno bit, ninguno de esos valores está cerca de lo que esperaría. Actualicé la publicación con el valor esperado, pero para 1VDC esperaría alrededor de 204 o 205 (1/5 * 2 ^ 10). De todos modos, ¿tiene alguna idea de qué podría estar causando que lea el noveno bit incorrectamente?
Ver editar arriba.