AD9833 Problemas con Arduino y SPI [No puedo pensar en un buen título]

3

Bien, estoy a punto de terminar, estoy jugando con un AD9833 para sintetizar una onda de pecado. He peinado todas las formas de foros con respecto al AD9833 en vano. Este es el circuito que estoy corriendo.

EDITAR: aunque el circuito dice que Fsync está controlado por PB0 (pin 53) está realmente conectado al pin 36 según el código

Otro EDITAR: Estoy haciendo esto en una placa de pruebas, lo que, como he leído, es un gran no, no, podría dañar la pieza o solo introducir interferencias locas. .EstoycontrolandoelAD9833conunArduinoMega2560ycomunicándomeconelprotocoloSPI,peroenlugardeusarelpinSSenelArduino,estoycontrolandomanualmenteelpinFsync,yaquenecesitotransferir16bits.

//thesensorcommunicatesusingSPI,soincludethelibrary:#include<SPI.h>//pinsusedfortheconnectionwiththesensor//theotheryouneedarecontrolledbytheSPIlibrary):constintfSync=36;voidsetup(){Serial.begin(9600);//starttheSPIlibrary:SPI.begin();SPI.beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE3));//initalizethedatareadyandchipselectpins:delay(10);pinMode(fSync,OUTPUT);digitalWrite(fSync,HIGH);delay(10);digitalWrite(fSync,LOW);SPI.transfer(0x20);//turnsB28-write28bitstoFREQregisterSPI.transfer(0x00);digitalWrite(fSync,HIGH);delayMicroseconds(1);digitalWrite(fSync,LOW);SPI.transfer(0x4C);//write0x0C0Fto14LSBSPI.transfer(0x0F);digitalWrite(fSync,HIGH);delayMicroseconds(1);digitalWrite(fSync,LOW);SPI.transfer(0x70);//write0x30FFto14MSBSPI.transfer(0xFF);digitalWrite(fSync,HIGH);delayMicroseconds(1);digitalWrite(fSync,LOW);SPI.transfer(0x00);//OutputsinewaveSPI.transfer(0x00);digitalWrite(fSync,HIGH);delayMicroseconds(1);SPI.end();}voidloop(){}

Losdatosseestánsincronizandoenelflancodescendenteyelrelojestáinactivo.

Estaesunaseñalde1MHzqueestoyusandocomomirelojmaestroyprovienedeungeneradordefunciones.

Estamonstruosidadesloqueobtengoparaunasalida.Segúnmiscálculos,elregistroFREQdebetener0x30FFC0F=51.379E6.Estosignificaquelafrecuenciadesalidadeberíaserdeaproximadamente191kHz,loqueesunacasualidad,creoquelaondatieneunafrecuenciadeaproximadamente200kHz.

EstoysegurodequelosregistrosdedatosseestánactualizandocomosepuedeveraquícuandoingreselossiguientesdatosSPI

0x20000x4C000x7F0F0x0000

He comprobado mis voltajes y todo parece estar dentro del rango

  • CAP / 2.5V es ~ 2.49V
  • AGND a DGND 0V
  • VDD 4.95V del arduino

Mi único pensamiento es que frito el chip cuando lo soldé a la tabla de ruptura, ya he intentado 2 y tengo dudas de poner el 3ro puesto que estos chicos malos no son baratos.

¿Hay algún problema evidente que alguien pueda ver? Solicite cualquier otro dato si es necesario.

    
pregunta Lpaulson

1 respuesta

3

Resumen

Parece que funciona bien según lo diseñado.

Si desea que sigamos solucionando este problema, debe decir explícitamente (1) lo que esperaba ver, (2) lo que realmente vio y (3) lo que parece ser la diferencia.

Algunos de los problemas más difíciles para mi depuración son cuando estoy convencido de que hay un problema con algo, pero resulta que todo funciona realmente bien. Estoy malinterpretando lo que veo en mi o 'el alcance como un problema, cuando en realidad mi o'scope me está mostrando que las cosas están funcionando bien.

También: buen trabajo reduciendo su código a un SSCCE relativamente corto. Eso hizo mucho más fácil averiguar qué estaba pasando. Gracias.

detalles

Esta imagen es exactamente lo que espero ver en el alcance cuando el DAC en un DDS está programado para generar una onda sinusoidal cercana (pero no exactamente igual a) 1/5 de la frecuencia de muestreo de salida.

NoimportacuántosbitsderesolucióntengaelDAC,sisolotienetiempoparagenerar5valoresdemuestraporciclodelaondasinusoidal,verá5pasosporciclodelaformadeondadesalida,yaqueveraquí.

Estoesperfectamentenormalyesperado.TodoslosllamadosgeneradoresDTMFde"onda sinusoidal" que he usado tienen salidas de aspecto muy similar.

Con algunas aplicaciones (como los generadores DTMF que he usado), mientras que tales formas de onda pueden verse bastante feas en el o'scope y ni siquiera son reconocibles como ondas sinusoidales, funcionan perfectamente bien en la práctica.

Con muchas aplicaciones, un poco de filtrado redondea los bordes afilados de la escalera para que se vea como una onda sinusoidal en el o-scope. (Un circuito de filtro RC de la serie es a menudo adecuado).

Algunas aplicaciones son muy sensibles a la distorsión armónica y no armónica causada por este tipo de escalones. Con tales aplicaciones, usted debe: (a) filtre fuertemente la salida para eliminar la frecuencia de frecuencia de muestreo y todos sus armónicos, o (b) aumentar la frecuencia de muestreo para salir de la zona sensible. En su caso, puede aumentar su reloj maestro hasta 12.5 MHz con bastante facilidad, pero por encima de eso se requieren modificaciones de hardware más serias. (Las personas que hacen RF a menudo no pueden (b) y, por lo tanto, se ven obligadas a usar la opción (a) y pasan mucho tiempo ajustando los complejos filtros de escalera RLC y preocupándose por la desviación del valor de los componentes. Las personas que hacen electrónica de audio a menudo encuentran la opción (b) mucho más simple. )

Si entiendo su código correctamente, está escribiendo 0x30FF en los 14 MSB del registro FREQ0 de 28 bits. Mientras que normalmente aumenta el valor binario en el registro FREQ aumenta la frecuencia de salida, alias de frecuencia / debajo del muestreo / efectos de tasa Nyquist causar valores a lo largo de la mitad del período (en este caso, valores por encima de 0x2000 en los 14 MSB) a alias y parecen generar una frecuencia más baja. (Tales valores siguen siendo útiles cuando se generan ondas triangulares ...) Así que espero la misma frecuencia que 0x4000 - 0x30FF = 0x0F01.

output_frequency = Phase * f_MCLK /( 2^28 )  # (from p. 12 of datasheet)

En este caso, Phase es efectivamente (0x0F01 < < 14), dando una frecuencia de salida con solo aproximadamente 2 (2 ^ 28 / (0x0F01 < < 14)) == 4.2 muestras por ciclo de salida. En f_MCLK == 1 MHz, espero una frecuencia de salida de aproximadamente 230 KHz, que es lo que veo en su alcance.

Si realmente necesita para generar una frecuencia de más de la mitad de 1 MHz, necesita cambiar su hardware.

EDITAR:

  

Según mis cálculos, el registro FREQ debe tener 0x30FFC0F = 51.379E6.

Ojalá este chip estuviera diseñado de tal manera que fuera cierto. Pero debido a que este chip utiliza cargas de registro funky de 14 bits,

SPI.transfer(0x4C);     //write 0x0C0F to 14LSB
...
SPI.transfer(0x70);     //write 0x30FF to 14MSB

termina colocando (0x30FF) < < 14 + 0x0C0F == (0x30FF) * 2 ^ 14 + 0x0C0F == 0x0C3F_CC0F == 206e6 (decimal) en el registro FREQ0. Debido a que es más de la mitad de 2 ^ 28, vemos un repliegue de aliasing, por lo que la frecuencia de salida es la misma que cargar 0x1000_000 - 0x0C3F_CC0F = 0x03C033F1 en el registro FREQ0. Como 2 ^ 28 / 0x03C033F1 es aproximadamente 4.3, verá 4 o 5 pasos por "onda sinusoidal" completa. Y con una frecuencia de paso de 1 MHz, eso da una frecuencia de salida de aproximadamente 0x03C033F1 * 1 MHz / 2 ^ 28 que es aproximadamente 230 kHz.

Creo que quieres algo más como

// FIXME: do this without float, only integers,
// without overflowing the 32-bit Arduino "long int" ?
void set_frequency( long int desired_frequency ){
    const long int f_MCLK = 1e6; // change to 10e6 when we put the 10 MHz crystal in.
    ASSERT( (desired_frequency * 2) < f_MCLK );
    const int phase0command = 0x4000;
    const float steps_per_Hz = (1.0 * ((long int)1)<<28) / f_MCLK;
    // phase =  (desired_frequency * 2^28) / f_MCLK
    unsigned long int steps_per_clk = desired_frequency * steps_per_Hz;
    unsigned int high14 = steps_per_clk >> 14;
    unsigned int low14 = steps_per_clk & (0x3FFF);
    digitalWrite(fSync, LOW);
    SPI.transfer16(phase0command | low14);
    digitalWrite(fSync, HIGH);
    delayMicroseconds(1);
    digitalWrite(fSync, LOW);
    SPI.transfer16(phase0command | high14);
    digitalWrite(fSync, HIGH);
}
    
respondido por el davidcary

Lea otras preguntas en las etiquetas