Tabla de contenido:

Arduino y PCF8591 ADC DAC IC: 7 pasos
Arduino y PCF8591 ADC DAC IC: 7 pasos

Video: Arduino y PCF8591 ADC DAC IC: 7 pasos

Video: Arduino y PCF8591 ADC DAC IC: 7 pasos
Video: PCF8591 AD-DA Converter Demo with AT89S52 2024, Noviembre
Anonim
Arduino y PCF8591 ADC DAC IC
Arduino y PCF8591 ADC DAC IC

¿Alguna vez ha querido más pines de entrada analógica en su proyecto Arduino, pero no ha querido desembolsar un Mega? ¿O le gustaría generar señales analógicas? Luego, consulte el tema de nuestro tutorial: el NXP PCF8591 IC.

Resuelve ambos problemas, ya que tiene un solo convertidor DAC (digital a analógico) y cuatro ADC (convertidores de analógico a digital), todos accesibles a través del bus I2C. El PCF8591 está disponible en formato DIP, montaje en superficie y módulo, lo que facilita la experimentación.

Antes de continuar, descargue la hoja de datos. La PCF8591 puede funcionar tanto con 5 V como con 3,3 V, por lo que si está utilizando una placa de desarrollo Arduino Due, Raspberry Pi u otra placa de desarrollo de 3,3 V, está bien. Ahora, primero explicaremos el DAC, luego los ADC.

Paso 1: uso del DAC (convertidor de digital a analógico)

Uso del DAC (convertidor de digital a analógico)
Uso del DAC (convertidor de digital a analógico)

El DAC en el PCF8591 tiene una resolución de 8 bits, por lo que puede generar una señal teórica de entre cero voltios y el voltaje de referencia (Vref) en 255 pasos. Para fines de demostración, usaremos un Vref de 5V, y puede usar un Vref más bajo, como 3.3V o lo que desee que sea el valor máximo … sin embargo, debe ser menor que el voltaje de suministro.

Tenga en cuenta que cuando hay una carga en la salida analógica (una situación del mundo real), el voltaje de salida máximo caerá: la hoja de datos (que descargó) muestra una caída del 10% para una carga de 10 kΩ. Ahora para nuestro circuito de demostración.

Tenga en cuenta el uso de resistencias pull-up de 10kΩ en el bus I2C y el capacitor de 10μF entre 5V y GND. La dirección del bus I2C se establece mediante una combinación de pines A0 ~ A2, y con todos ellos a GND, la dirección es 0x90. La salida analógica se puede tomar del pin 15 (y hay un GND analógico separado en el pin 13. Además, conecte el pin 13 a GND y el circuito GND a Arduino GND.

Para controlar el DAC necesitamos enviar dos bytes de datos. El primero es el byte de control, que simplemente activa el DAC y es 1000000 (o 0x40) y el siguiente byte es el valor entre 0 y 255 (el nivel de salida). Esto se demuestra en el siguiente esquema:

// Ejemplo 52.1 Demostración de PCF8591 DAC

#incluya "Wire.h" #define PCF8591 (0x90 >> 1) // I2C dirección de bus void setup () {Wire.begin (); } bucle vacío () {for (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (0x40); // byte de control - activa DAC (binario 1000000) Wire.write (i); // valor para enviar a DAC Wire.endTransmission (); // finalizar la transmisión}

para (int i = 255; i> = 0; --i)

{Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (0x40); // byte de control - activa DAC (binario 1000000) Wire.write (i); // valor para enviar a DAC Wire.endTransmission (); // finalizar la transmisión}}

¿Notó el cambio de bits de la dirección del bus en la declaración #define? Arduino envía direcciones de 7 bits, pero el PCF8591 quiere una de 8 bits, por lo que cambiamos el byte un bit.

Paso 2:

Imagen
Imagen

Los resultados del boceto se muestran en la imagen, hemos conectado el Vref a 5V y la sonda del osciloscopio y GND a la salida analógica y GND respectivamente.

Paso 3:

Imagen
Imagen

Si le gustan las curvas, puede generar ondas sinusoidales con el siguiente boceto. Utiliza una tabla de búsqueda en una matriz que contiene los puntos de datos precalculados necesarios:

// Ejemplo 52.2 Demostración de PCF8591 DAC - onda sinusoidal

#include "Wire.h" #define PCF8591 (0x90 >> 1) // Dirección de bus I2C uint8_t sine_wave [256] = {0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96, 0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE, 0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4, 0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD8x, 0xD1, 0xD3, 0xD8xD5, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFED, 0xFED, 0xFED 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xEF4, 0xF1, 0xF5, 0xEF4, 0xF3, 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xC4, 0xBxB 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x7, 0x7 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52, 0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x 3C, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18, 0x16, 0x15, 0x13, 0x11, 0x10, 0x0x0, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, 0x03, 0x02, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x128, 0x22, 0x20, 0x1Ex, 0x20, 0x20 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64x, 0x67, 0x61, 0x64x, 0x67 0x70, 0x74, 0x77, 0x7A, 0x7D}; configuración vacía () {Wire.begin (); } bucle vacío () {for (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (0x40); // byte de control - activa DAC (binario 1000000) Wire.write (sine_wave ); // valor para enviar a DAC Wire.endTransmission (); // finalizar la transmisión}}

Paso 4:

Imagen
Imagen

Para el siguiente volcado de imagen DSO, cambiamos el Vref a 3.3V; observe el cambio en los máximos en la onda sinusoidal.

Ahora puede experimentar con el DAC para crear efectos de sonido, señales o controlar otros circuitos analógicos.

Paso 5: uso de los ADC (convertidores de analógico a digital)

Si ha utilizado la función analogRead () en su Arduino (en el Capítulo Uno), entonces ya está familiarizado con un ADC. Sin PCF8591 podemos leer un voltaje entre cero y Vref y devolverá un valor entre cero y 255 que es directamente proporcional a cero y Vref.

Por ejemplo, medir 3.3V debería devolver 168. La resolución (8 bits) del ADC es menor que la del Arduino integrado (10 bits), sin embargo, el PCF8591 puede hacer algo que el ADC de Arduino no puede hacer. Pero llegaremos a eso en un momento. Primero, para simplemente leer los valores de cada pin de ADC, enviamos un byte de control para decirle al PCF8591 qué ADC queremos leer. Para los ADC de cero a tres, el byte de control es 0x00, 0x01, ox02 y 0x03 respectivamente.

Luego pedimos dos bytes de datos del ADC y almacenamos el segundo byte para su uso. ¿Por qué dos bytes? El PCF8591 devuelve primero el valor medido anteriormente y luego el byte actual. (Consulte la Figura 8 en la hoja de datos). Finalmente, si no está utilizando todos los pines ADC, conecte los que no utilice a GND. El siguiente boceto de ejemplo simplemente recupera los valores de cada pin de ADC uno a la vez, luego los muestra en el monitor serial:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // Dirección del bus I2C #define ADC0 0x00 // bytes de control para leer ADC individuales #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 byte value0, value1, value2, value3; configuración vacía () {Wire.begin (); Serial.begin (9600); } bucle vacío () {Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (ADC0); // byte de control - leer ADC0 Wire.endTransmission (); // finaliza la transmisión Wire.requestFrom (PCF8591, 2); value0 = Wire.read (); value0 = Wire.read (); Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (ADC1); // byte de control - leer ADC1 Wire.endTransmission (); // fin de la transmisión Wire.requestFrom (PCF8591, 2); valor1 = Wire.read (); valor1 = Wire.read (); Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (ADC2); // byte de control - leer ADC2 Wire.endTransmission (); // fin de la transmisión Wire.requestFrom (PCF8591, 2); valor2 = Wire.read (); valor2 = Wire.read (); Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (ADC3); // byte de control - leer ADC3 Wire.endTransmission (); // fin de la transmisión Wire.requestFrom (PCF8591, 2); valor3 = Wire.read (); valor3 = Wire.read (); Serial.print (valor0); Serial.print (""); Serial.print (valor1); Serial.print (""); Serial.print (valor2); Serial.print (""); Serial.print (valor3); Serial.print (""); Serial.println (); }

Al ejecutar el boceto, se le presentarán los valores de cada ADC en el monitor en serie. Aunque fue una demostración simple para mostrarle cómo leer individualmente cada ADC, es un método engorroso para obtener más de un byte a la vez de un ADC en particular.

Paso 6:

Para hacer esto, cambie el byte de control para solicitar auto-incremento, lo cual se hace configurando el bit 2 del byte de control a 1. Entonces, para comenzar desde ADC0 usamos un nuevo byte de control binario 00000100 o hexadecimal 0x04. Luego solicite cinco bytes de datos (una vez más ignoramos el primer byte) lo que hará que el PCF8591 devuelva todos los valores en una cadena de bytes. Este proceso se demuestra en el siguiente esquema:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // Byte de dirección de bus I2C valor0, valor1, valor2, valor3; configuración vacía () {Wire.begin (); Serial.begin (9600); } bucle vacío () {Wire.beginTransmission (PCF8591); // despierta PCF8591 Wire.write (0x04); // byte de control - leer ADC0 y luego auto-incrementar Wire.endTransmission (); // finaliza la transmisión Wire.requestFrom (PCF8591, 5); value0 = Wire.read (); value0 = Wire.read (); valor1 = Wire.read (); valor2 = Wire.read (); valor3 = Wire.read (); Serial.print (valor0); Serial.print (""); Serial.print (valor1); Serial.print (""); Serial.print (valor2); Serial.print (""); Serial.print (valor3); Serial.print (""); Serial.println (); }

Anteriormente mencionamos que el PCF8591 puede hacer algo que el ADC de Arduino no puede, y esto es ofrecer un ADC diferencial. A diferencia del terminal único de Arduino (es decir, devuelve la diferencia entre el voltaje de la señal positiva y GND, el ADC diferencial acepta dos señales (que no necesariamente tienen que estar referenciadas a tierra) y devuelve la diferencia entre las dos señales Esto puede resultar conveniente para medir pequeños cambios en los voltajes de las celdas de carga, etc.

Paso 7:

Imagen
Imagen

Configurar el PCF8591 para ADC diferencial es una simple cuestión de cambiar el byte de control. Si pasa a la página siete de la hoja de datos, considere los diferentes tipos de programación de entrada analógica. Anteriormente usamos el modo '00' para cuatro entradas, sin embargo, puede seleccionar las otras que están claramente ilustradas, por ejemplo, la imagen.

Entonces, para configurar el byte de control para dos entradas diferenciales, use el binario 00110000 o 0x30. Entonces es una simple cuestión de solicitar los bytes de datos y trabajar con ellos. Como puede ver, también hay una combinación de entrada simple / diferencial y una entrada compleja de tres diferenciales. Sin embargo, los dejaremos por el momento.

Esperamos que haya encontrado esto de interés, ya sea agregando un DAC a sus experimentos o aprendiendo un poco más sobre los ADC. Considere pedir su PCF8591 a PMD Way.

Esta publicación presentada por pmdway.com: todo para fabricantes y entusiastas de la electrónica, con envío gratuito en todo el mundo.

Recomendado: