Tabla de contenido:

Cómo crear y probar un mejor DAC con ESP32: 5 pasos
Cómo crear y probar un mejor DAC con ESP32: 5 pasos

Video: Cómo crear y probar un mejor DAC con ESP32: 5 pasos

Video: Cómo crear y probar un mejor DAC con ESP32: 5 pasos
Video: ✅ Música Digital Dentro del ESP32 esta genial para hacer proyectos 2024, Noviembre
Anonim
Cómo hacer y probar un mejor DAC con ESP32
Cómo hacer y probar un mejor DAC con ESP32
Cómo hacer y probar un mejor DAC con ESP32
Cómo hacer y probar un mejor DAC con ESP32

El ESP32 tiene 2 convertidores de digital a analógico (DAC) de 8 bits. Estos DAC nos permiten producir voltajes arbitrarios dentro de un cierto rango (0-3,3 V) con 8 bits de resolución. En este Instructable, le mostraré cómo construir un DAC y caracterizar su rendimiento, así como compararlo con el ESP32 DAC. Los índices de rendimiento que analizaré incluyen

  • Nivel de ruido
  • Banda ancha
  • No linealidad integral
  • No linealidad diferencial

Para probar estos índices usaré el ADS1115.

Es importante tener en cuenta que su evaluación de todos estos índices solo será tan precisa como su dispositivo de referencia (en este caso, el ADS115). Por ejemplo, el ADS115 no tiene precisión de 16 bits cuando se trata de su compensación y ganancia de voltaje. Estos errores pueden llegar hasta el 0,1%. Para muchos sistemas, estos errores se pueden ignorar cuando la precisión absoluta es una preocupación limitada.

Suministros

  • ADS1115
  • Tablero ESP32
  • tablero de circuitos
  • cables de puente
  • Resistencia de 5 kOhmios
  • 1 condensador cerámico micro-Faradio

Paso 1: Colocación de la placa de pruebas

Colocación de la placa de pruebas
Colocación de la placa de pruebas

Conecte los siguientes pines

Entre el ESP32 y el ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

En el ADS1115

DIRECCIÓN TIERRA (ADS115)

Haciendo el DAC

Hay muchas formas de hacer un DAC. La más simple es filtrar en paso bajo una señal PWM con una resistencia y un condensador. Podría haber agregado un amplificador operacional aquí como un búfer, pero quería mantener las cosas simples. Este diseño es simple y económico de implementar con cualquier microcontrolador que admita PWM. No voy a repasar la teoría del diseño aquí (google PWM DAC).

Simplemente conecte la resistencia GPIO255 KOhm 1 microFarad Capacitor gnd

Ahora conecte un cable de puente desde el punto donde la resistencia se encuentra con el capacitor a A0 en el ADS115.

Paso 2: evaluar la señal al nivel de ruido

Evaluar la señal al nivel de ruido
Evaluar la señal al nivel de ruido

Para evaluar el nivel de ruido, simplemente ejecute el siguiente script. Para evaluar esto, simplemente dejamos el DAC en un valor fijo y medimos cómo oscila el voltaje con el tiempo.

Debido al diseño del DAC, el ruido será mayor cuando la señal PWM tenga un ciclo de trabajo del 50%. Por tanto, aquí es donde lo evaluaremos. También evaluaremos el ESP32 a este mismo nivel de señal. También filtraremos el ESP32 DAC con el mismo filtro de paso bajo para que la medición sea comparable.

Para mí el resultado fue claro. El diseño PWM tenía> 6dB mejor SNR (eso es 2 veces mejor). Una clara victoria para el nuevo DAC. Una pequeña confusión es que hay filtros integrados en el ADC que definitivamente mejoran la SNR. Por tanto, los valores absolutos pueden resultar difíciles de interpretar. Si hubiera utilizado un filtro de segundo orden, este no sería el caso.

De todos modos, el código está debajo

#incluir

# incluir anuncios de Adafruit_ADS1115; // biblioteca adafruit para adc int16_t adc0; // configuración nula (nula) {Serial.begin (115200); // Inicie la serie ads.setGain (GAIN_TWO); // 2x ganancia +/- 2.048V 1 bit = 0.0625mV ads.begin (); // comenzar adc float M = 0; // flotador medio inicial Mp = 0; // previouos mean float S = 0; // Variación inicial float Sp = 0; // varianza anterior const int reps = 500; // número de repeticiones int n = 256; // número de muestras ledcSetup (0, 25000, 8); // establece la frecuencia pwm = 25000 Hz a una resolución de 8 bits ledcAttachPin (25, 0); // establece pwm en el pin 25 ledcWrite (0, 128); // configúrelo en la mitad del ciclo de trabajo (mayor ruido) delay (3000); // esperar el tiempo de estabilización float snrPWM [reps]; // matriz de snrs para PWM float snrDAC [reps]; // matriz de snrs para DAC for (int i = 0; i <reps; i ++) {// loope over repititions for (int k = 1; k <(n + 1); k ++) {// loope over samples adc0 = ads.readADC_SingleEnded (0); // obtener la lectura M = Mp + (adc0 - Mp) / k; // calcular la media móvil Mp = M; // establece la media anterior S = Sp + (adc0 - Mp) * (adc0 - M); // calcular la varianza progresiva Sp = S; // establece la varianza anterior} // snr en dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); // restablecer valores M = 0; Mp = 0; S = 0; Sp = 0; } ledcDetachPin (25); // desconectar PWM del pin 25 dacWrite (25, 128); // escribir en DAC delay (3000); // esperar para conformarse con (int i = 0; i <reps; i ++) {// igual que el bucle PWM para (int k = 1; k <(n + 1); k ++) {adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Pf = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; } snrDAC = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); M = 0; Mp = 0; S = 0; Sp = 0; } // trazar las SNR en un gráfico para (int i = 1; i <repeticiones; i ++) {Serial.print ("PWM_SNR (dB):"); Serial.print (snrPWM ); Serial.print (","); Serial.print ("ESP32_SNR (dB):"); Serial.println (snrDAC ); }} bucle vacío (vacío) {}

Paso 3: No linealidad integral y no linealidad diferencial

No linealidad integral y no linealidad diferencial
No linealidad integral y no linealidad diferencial

La no linealidad integral es una medida de aproximadamente cuánta desviación hay entre el voltaje de salida de su DAC y una línea recta. Cuanto más grande es, peor es …

La no linealidad diferencial es una medida de aproximadamente cuánto se desvía el cambio observado en el voltaje (de un código al siguiente) de lo que se esperaría de una línea recta.

Los resultados aquí fueron realmente interesantes. En primer lugar, ambos tienen un error de menos de 0.5lsb (a una resolución de 8 bits), lo cual es bueno, pero el PWM tiene una linealidad integral mucho mejor. Ambos tienen una no linealidad diferencial comparable, pero el ESP32 DAC tiene algunos picos muy extraños. Además, el método PWM tiene cierta estructura para los errores. Básicamente, sobrepasa y no alcanza el voltaje correcto de forma alterna.

Mi sospecha es que se trata de un extraño error de redondeo en la forma en que se produce una señal PWM de 8 bits en el ESP32.

Una forma de corregir esto es alternar rápidamente entre dos códigos adyacentes (por ejemplo, 128, 129) con el PWM. Con un filtro de paso bajo analógico, los errores resultantes promediarán cero. Simulé esto en el software y, de hecho, todos los errores desaparecieron. ¡Ahora el método PWM tiene una linealidad con una precisión de 16 bits!

Cualquiera que sea, el código para generar los datos está a continuación. La salida estará en el monitor serial en formato.csv. Simplemente cópielo en un archivo de texto para su posterior procesamiento.

#incluir

# incluir anuncios de Adafruit_ADS1115; / * Use esto para la versión de 16 bits * / int16_t adc0; configuración nula (nula) {Serial.begin (115200); ads.setGain (GAIN_ONE); // 2x ganancia +/- 2.048V 1 bit = 1mV 0.0625mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); Serial.println ("esperado, observado"); ledcWrite (0, 2); retraso (3000); para (int i = 2; i <255; i ++) {ledcWrite (0, i); retraso (100); adc0 = ads.readADC_SingleEnded (0); flotante esperado = (i / 256.0 * 3.3) / 4.096 * 32767; Serial.print (esperado); Serial.print (","); Serial.println (adc0); }} bucle vacío (vacío) {}

Paso 4: ancho de banda

Banda ancha
Banda ancha

Voy a definir el ancho de banda aquí como la frecuencia a la que la salida del DAC cae en 3dB. Esta es una convención y, hasta cierto punto, arbitraria. Por ejemplo, en el punto de 6dB, el DAC seguirá emitiendo una señal que tendrá una amplitud de ~ 50%.

Para medir esto, simplemente pasamos ondas sinusoidales a una frecuencia creciente desde el DAC al ADC y medimos su desviación estándar. Como era de esperar, el punto 3dB está a 30Hz (1 / (2 * pi * 5000 * 1e-6)).

El ESP32 puede hacer 1 megamuestra por segundo. Esta es una victoria indiscutible para el ESP32. Su amplitud no decae en absoluto en la región de prueba de ancho de banda de 100 Hz.

El siguiente código puede probar el ancho de banda de PWM DAC.

#incluir

# incluir anuncios de Adafruit_ADS1115; / * Use esto para la versión de 16 bits * / int16_t adc0; int16_t adc1; configuración vacía (void) {float M; Flotante Mp = 0; flotador S = 0; flotador Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x ganancia +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); retraso (5000); Serial.println ("Frecuencia, Amplitud"); for (int i = 1; i <100; i ++) {inicio largo sin signo = milis (); unsigned long T = milis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma de flotación; while ((T - inicio) <1000) {int out = 24 * sin (2 * PI * i * (T - inicio) / 1000.0) + 128; ledcWrite (0, fuera); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Pf = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = milis (); k ++; } si (i == 1) {norma = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norma, 3); k = 0; }} bucle vacío (vacío) {}

Y este código probará el ancho de banda de ESP32. Asegúrese de quitar el condensador o los resultados serán los mismos para ambos métodos.

#incluir

# incluir anuncios de Adafruit_ADS1115; / * Use esto para la versión de 16 bits * / int16_t adc0; int16_t adc1; configuración vacía (void) {float M; Flotante Mp = 0; flotador S = 0; flotar Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x ganancia +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); retraso (5000); Serial.println ("Frecuencia, Amplitud"); for (int i = 1; i <100; i ++) {inicio largo sin signo = milis (); unsigned long T = milis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma de flotación; while ((T - inicio) <1000) {int out = 24 * sin (2 * PI * i * (T - inicio) / 1000.0) + 128; dacWrite (25, fuera); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Pf = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = milis (); k ++; } si (i == 1) {norma = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norma, 3); k = 0; }} bucle vacío (vacío) {}

Paso 5: pensamientos finales

El nuevo diseño de DAC gana en linealidad y ruido, pero pierde en ancho de banda. Dependiendo de su aplicación, uno de estos índices puede ser más importante que el otro. Con estos procedimientos de prueba, ¡debería poder tomar esa decisión objetivamente!

Además, creo que vale la pena señalar aquí que debido a que la salida PWM es de bajo ruido, con una linealidad excepcional debería ser posible construir un DAC de resolución mucho más alta con la salida PWM (tal vez incluso con una precisión de 16 bits). Eso va a requerir algo de trabajo. Hasta entonces, ¡te digo adiós!

Recomendado: