Sommario:

Arduino e PCF8591 ADC DAC IC: 7 passaggi
Arduino e PCF8591 ADC DAC IC: 7 passaggi

Video: Arduino e PCF8591 ADC DAC IC: 7 passaggi

Video: Arduino e PCF8591 ADC DAC IC: 7 passaggi
Video: Electronic Basics #10: Digital to Analog Converter (DAC) 2024, Novembre
Anonim
Arduino e PCF8591 ADC DAC IC
Arduino e PCF8591 ADC DAC IC

Hai mai desiderato più pin di ingresso analogico sul tuo progetto Arduino, ma non hai voluto sborsare per un Mega? Oppure desideri generare segnali analogici? Quindi dai un'occhiata all'argomento del nostro tutorial: NXP PCF8591 IC.

Risolve entrambi questi problemi in quanto dispone di un singolo convertitore DAC (da digitale ad analogico) e di quattro ADC (convertitori da analogico a digitale), tutti accessibili tramite il bus I2C. Il PCF8591 è disponibile in DIP, montaggio superficiale e modulo, che lo rende facile da sperimentare.

Prima di proseguire, scarica la scheda tecnica. Il PCF8591 può funzionare sia a 5 V che a 3,3 V, quindi se stai utilizzando un Arduino Due, un Raspberry Pi o un'altra scheda di sviluppo da 3,3 V sei a posto. Ora spiegheremo prima il DAC, poi gli ADC.

Passaggio 1: utilizzo del DAC (convertitore digitale-analogico)

Utilizzo del DAC (convertitore digitale-analogico)
Utilizzo del DAC (convertitore digitale-analogico)

Il DAC sul PCF8591 ha una risoluzione di 8 bit, quindi può generare un segnale teorico compreso tra zero volt e la tensione di riferimento (Vref) in 255 passi. A scopo dimostrativo useremo un Vref di 5V, e puoi usare un Vref più basso come 3,3V o qualunque cosa tu voglia che il valore massimo sia … tuttavia deve essere inferiore alla tensione di alimentazione.

Nota che quando c'è un carico sull'uscita analogica (una situazione del mondo reale), la tensione di uscita massima diminuirà: il foglio dati (che hai scaricato) mostra un calo del 10% per un carico di 10 kΩ. Ora per il nostro circuito dimostrativo.

Notare l'uso di resistori pull-up da 10kΩ sul bus I2C e il condensatore da 10μF tra 5V e GND. L'indirizzo del bus I2C è impostato da una combinazione di pin A0~A2, e con tutti loro a GND l'indirizzo è 0x90. L'uscita analogica può essere presa dal pin 15 (e c'è un GND analogico separato sul pin 13. Inoltre, collegare il pin 13 a GND e il circuito GND a Arduino GND.

Per controllare il DAC dobbiamo inviare due byte di dati. Il primo è il byte di controllo, che attiva semplicemente il DAC ed è 1000000 (o 0x40) e il byte successivo è il valore compreso tra 0 e 255 (il livello di uscita). Ciò è dimostrato nel seguente schizzo:

// Esempio 52.1 PCF8591 DAC demo

#include "Wire.h" #define PCF8591 (0x90 >> 1) // Indirizzo bus I2C void setup() { Wire.begin(); } void loop() { for (int i=0; i<256; i++) { Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(0x40); // byte di controllo - attiva DAC (binario 1000000) Wire.write(i); // valore da inviare al DAC Wire.endTransmission(); // fine trasmissione }

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

{ Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(0x40); // byte di controllo - attiva DAC (binario 1000000) Wire.write(i); // valore da inviare al DAC Wire.endTransmission(); // fine trasmissione } }

Hai notato lo spostamento di bit dell'indirizzo del bus nell'istruzione #define? Arduino invia indirizzi a 7 bit ma il PCF8591 vuole un 8 bit, quindi spostiamo il byte di un bit.

Passo 2:

Immagine
Immagine

I risultati dello sketch sono mostrati nell'immagine, abbiamo collegato il Vref a 5V e la sonda dell'oscilloscopio e GND rispettivamente all'uscita analogica e GND.

Passaggio 3:

Immagine
Immagine

Se ti piacciono le curve puoi generare onde sinusoidali con lo schizzo qui sotto. Utilizza una tabella di ricerca in un array che contiene i punti dati precalcolati necessari:

// Esempio 52.2 PCF8591 DAC demo - onda sinusoidale

#include "Wire.h" #define PCF8591 (0x90 >> 1) // Indirizzo 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, 0xD5, 0xD3, 0xD5, 0xD8, 0xD5, 0xD8, 0x 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF4, 0xF3, 0xF 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xC4, 0xB6, 0xBC, 0xBF 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 0x74, 0x7, 0x74, 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, 0x,0F 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x20, 0x22, 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64 0x70, 0x74, 0x77, 0x7A, 0x7D }; void setup() { Wire.begin(); } void loop() { for (int i=0; i<256; i++) { Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(0x40); // byte di controllo - attiva DAC (binario 1000000) Wire.write(sine_wave); // valore da inviare al DAC Wire.endTransmission(); // fine trasmissione } }

Passaggio 4:

Immagine
Immagine

Per il seguente dump dell'immagine DSO, abbiamo cambiato il Vref a 3,3 V – nota il cambiamento nei massimi sull'onda sinusoidale.

Ora puoi sperimentare con il DAC per creare effetti sonori, segnali o controllare altri circuiti analogici.

Passaggio 5: utilizzo degli ADC (convertitori da analogico a digitale)

Se hai usato la funzione analogRead() sul tuo Arduino (molto indietro nel capitolo uno), allora hai già familiarità con un ADC. Senza PCF8591 possiamo leggere una tensione tra zero e Vref e restituirà un valore compreso tra zero e 255 che è direttamente proporzionale a zero e Vref.

Ad esempio, la misurazione di 3,3 V dovrebbe restituire 168. La risoluzione (8 bit) dell'ADC è inferiore a quella dell'Arduino integrato (10 bit), tuttavia il PCF8591 può fare qualcosa che l'ADC di Arduino non può. Ma ci arriveremo tra un momento. Innanzitutto, per leggere semplicemente i valori di ciascun pin ADC inviamo un byte di controllo per dire al PCF8591 quale ADC vogliamo leggere. Per gli ADC da zero a tre il byte di controllo è rispettivamente 0x00, 0x01, ox02 e 0x03.

Quindi chiediamo due byte di dati indietro dall'ADC e memorizziamo il secondo byte per l'uso. Perché due byte? Il PCF8591 restituisce prima il valore misurato in precedenza, quindi il byte corrente. (Vedi Figura 8 nella scheda tecnica). Infine, se non stai utilizzando tutti i pin ADC, collega quelli inutilizzati a GND. Il seguente schizzo di esempio recupera semplicemente i valori da ciascun pin ADC uno alla volta, quindi li visualizza nel monitor seriale:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // Indirizzo bus I2C #define ADC0 0x00 // byte di controllo per la lettura dei singoli ADC #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 byte valore0, valore1, valore2, valore3; void setup() { Wire.begin(); Serial.begin(9600); } void loop() { Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(ADC0); // byte di controllo - legge ADC0 Wire.endTransmission(); // termina la trasmissione Wire.requestFrom(PCF8591, 2); valore0=Filo.read(); valore0=Filo.read(); Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(ADC1); // byte di controllo - legge ADC1 Wire.endTransmission(); // termina la trasmissione Wire.requestFrom(PCF8591, 2); valore1=Filo.leggi(); valore1=Filo.leggi(); Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(ADC2); // byte di controllo - legge ADC2 Wire.endTransmission(); // termina la trasmissione Wire.requestFrom(PCF8591, 2); valore2=Filo.leggi(); valore2=Filo.leggi(); Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(ADC3); // byte di controllo - legge ADC3 Wire.endTransmission(); // termina la trasmissione Wire.requestFrom(PCF8591, 2); valore3=Filo.leggi(); valore3=Filo.leggi(); Serial.print(value0); Serial.print(" "); Serial.print(value1); Serial.print(" "); Serial.print(value2); Serial.print(" "); Serial.print(value3); Serial.print(" "); Serial.println(); }

Dopo aver eseguito lo schizzo, ti verranno presentati i valori di ciascun ADC nel monitor seriale. Sebbene fosse una semplice dimostrazione per mostrare come leggere singolarmente ogni ADC, è un metodo scomodo per ottenere più di un byte alla volta da un particolare ADC.

Passaggio 6:

Per fare ciò, cambia il byte di controllo per richiedere l'auto-incremento, che viene fatto impostando il bit 2 del byte di controllo su 1. Quindi per iniziare da ADC0 usiamo un nuovo byte di controllo di 00000100 binario o esadecimale 0x04. Quindi richiedere cinque byte di dati (ancora una volta ignoriamo il primo byte) che farà sì che il PCF8591 restituisca tutti i valori in una catena di byte. Questo processo è dimostrato nel seguente schizzo:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // Byte indirizzo bus I2C valore0, valore1, valore2, valore3; void setup() { Wire.begin(); Serial.begin(9600); } void loop() { Wire.beginTransmission(PCF8591); // riattiva PCF8591 Wire.write(0x04); // byte di controllo - legge ADC0 quindi incrementa automaticamente Wire.endTransmission(); // termina la trasmissione Wire.requestFrom(PCF8591, 5); valore0=Filo.read(); valore0=Filo.leggi(); valore1=Filo.leggi(); valore2=Filo.leggi(); valore3=Filo.read(); Serial.print(value0); Serial.print(" "); Serial.print(valore1); Serial.print(" "); Serial.print(value2); Serial.print(" "); Serial.print(value3); Serial.print(" "); Serial.println(); }

In precedenza abbiamo detto che il PCF8591 può fare qualcosa che l'ADC di Arduino non può, e questo è offrire un ADC differenziale. A differenza del single-ended di Arduino (cioè restituisce la differenza tra la tensione del segnale positivo e GND, l'ADC differenziale accetta due segnali (che non devono necessariamente essere riferiti a massa), e restituisce la differenza tra i due segnali Questo può essere utile per misurare piccole variazioni di tensione per celle di carico e così via.

Passaggio 7:

Immagine
Immagine

L'impostazione del PCF8591 per l'ADC differenziale è una semplice questione di modifica del byte di controllo. Se vai alla pagina sette della scheda tecnica, considera i diversi tipi di programmazione degli ingressi analogici. In precedenza abbiamo utilizzato la modalità '00' per quattro ingressi, tuttavia è possibile selezionare gli altri che sono chiaramente illustrati, ad esempio l'immagine.

Quindi per impostare il byte di controllo per due ingressi differenziali, utilizzare il binario 00110000 o 0x30. Quindi si tratta semplicemente di richiedere i byte di dati e lavorare con essi. Come puoi vedere c'è anche la combinazione singolo/differenziale e un complesso ingresso a tre differenziali. Comunque li lasceremo per il momento.

Spero che tu abbia trovato questo interessante, sia che tu aggiunga un DAC ai tuoi esperimenti o che impari qualcosa in più sugli ADC. Si prega di considerare di ordinare il PCF8591 da PMD Way.

Questo post ti è stato presentato da pmdway.com: tutto per produttori e appassionati di elettronica, con consegna gratuita in tutto il mondo.

Consigliato: