Inhaltsverzeichnis:

Arduino und PCF8591 ADC DAC IC - Gunook
Arduino und PCF8591 ADC DAC IC - Gunook

Video: Arduino und PCF8591 ADC DAC IC - Gunook

Video: Arduino und PCF8591 ADC DAC IC - Gunook
Video: Electronic Basics #10: Digital to Analog Converter (DAC) 2024, Juli
Anonim
Arduino und PCF8591 ADC DAC IC
Arduino und PCF8591 ADC DAC IC

Wollten Sie schon immer mehr analoge Eingangspins für Ihr Arduino-Projekt, wollten aber nicht für einen Mega ausgeben? Oder möchten Sie analoge Signale generieren? Dann schauen Sie sich das Thema unseres Tutorials an – den NXP PCF8591 IC.

Es löst beide Probleme, da es über einen einzigen DAC (Digital-Analog)-Wandler sowie vier ADCs (Analog-Digital-Wandler) verfügt – alle zugänglich über den I2C-Bus. Der PCF8591 ist in DIP-, SMD- und Modulform erhältlich, was das Experimentieren erleichtert.

Bevor Sie fortfahren, laden Sie das Datenblatt herunter. Der PCF8591 kann sowohl mit 5 V als auch mit 3,3 V betrieben werden. Wenn Sie also ein Arduino Due, Raspberry Pi oder ein anderes 3,3 V-Entwicklungsboard verwenden, sind Sie in Ordnung. Jetzt erklären wir zuerst den DAC, dann die ADCs.

Schritt 1: Verwenden des DAC (Digital-Analog-Wandler)

Verwenden des DAC (Digital-Analog-Wandler)
Verwenden des DAC (Digital-Analog-Wandler)

Der DAC des PCF8591 hat eine Auflösung von 8 Bit – er kann also in 255 Schritten ein theoretisches Signal zwischen null Volt und der Referenzspannung (Vref) erzeugen. Zu Demonstrationszwecken verwenden wir eine Vref von 5 V, und Sie können eine niedrigere Vref wie 3,3 V oder einen beliebigen Maximalwert verwenden, der jedoch unter der Versorgungsspannung liegen muss.

Beachten Sie, dass bei Belastung des Analogausgangs (eine reale Situation) die maximale Ausgangsspannung abfällt – das Datenblatt (das Sie heruntergeladen haben) zeigt einen Abfall von 10 % für eine Last von 10 kΩ. Nun zu unserer Demonstrationsstrecke.

Beachten Sie die Verwendung von 10kΩ Pullup-Widerständen am I2C-Bus und den 10μF Kondensator zwischen 5V und GND. Die I2C-Busadresse wird durch eine Kombination der Pins A0~A2 eingestellt, und mit allen auf GND ist die Adresse 0x90. Der analoge Ausgang kann von Pin 15 genommen werden (und es gibt eine separate analoge GND an Pin 13. Verbinden Sie auch Pin 13 mit GND und die Schaltungs-GND mit Arduino GND.

Um den DAC zu steuern, müssen wir zwei Datenbytes senden. Das erste ist das Kontrollbyte, das einfach den DAC aktiviert und ist 1000000 (oder 0x40) und das nächste Byte ist der Wert zwischen 0 und 255 (der Ausgangspegel). Dies wird in der folgenden Skizze demonstriert:

// Beispiel 52.1 PCF8591 DAC-Demo

#include "Wire.h" #define PCF8591 (0x90 >> 1) // I2C-Busadresse void setup() { Wire.begin(); aufrechtzuerhalten. Void Schleife () { for (int i = 0; i < 256; i ++) { Wire.beginTransmission (PCF8591); // PCF8591 Wire.write (0x40) aufwecken; // Kontrollbyte - DAC einschalten (binär 1000000) Wire.write (i); // Wert, der an DAC gesendet werden soll Wire.endTransmission(); // Übertragung beenden }

für (int i=255; i>=0; --i)

{ Wire.beginTransmission (PCF8591); // PCF8591 Wire.write (0x40) aufwecken; // Kontrollbyte - DAC einschalten (binär 1000000) Wire.write (i); // Wert, der an DAC gesendet werden soll Wire.endTransmission(); // Übertragung beenden } }

Ist Ihnen die Bitverschiebung der Busadresse in der #define-Anweisung aufgefallen? Arduino sendet 7-Bit-Adressen, aber der PCF8591 will 8-Bit, also verschieben wir das Byte um ein Bit.

Schritt 2:

Bild
Bild

Die Ergebnisse der Skizze sind im Bild gezeigt, wir haben den Vref an 5V und den Oszilloskop-Tastkopf und GND an den Analogausgang bzw. GND angeschlossen.

Schritt 3:

Bild
Bild

Wenn Sie Kurven mögen, können Sie mit der folgenden Skizze Sinuswellen erzeugen. Es verwendet eine Lookup-Tabelle in einem Array, die die notwendigen vorberechneten Datenpunkte enthält:

// Beispiel 52.2 PCF8591 DAC Demo - Sinuswelle

#include "Wire.h" #define PCF8591 (0x90 >> 1) // I2C-Busadresse uint8_t sinus_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, 0x 0x, 0xD5, 0x 0x, 0x 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0FEx 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF4, 0xF3, 0x, Fx1, 0xF3, 0x 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xC4, 0xC1, 0xBx, 0x1, 0xBFx, 0x1, 0xBFx 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 0x74,6 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,F, 0x,0x 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, 0x 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64, 0x61, 0x64 0x70, 0x74, 0x77, 0x7A, 0x7D }; Void setup () { Wire.begin (); aufrechtzuerhalten. Void Schleife () { for (int i = 0; i < 256; i ++) { Wire.beginTransmission (PCF8591); // PCF8591 Wire.write (0x40) aufwecken; // Kontrollbyte - DAC einschalten (binär 1000000) Wire.write (sine_wave); // Wert, der an DAC gesendet werden soll Wire.endTransmission(); // Übertragung beenden } }

Schritt 4:

Bild
Bild

Für den folgenden DSO-Image-Dump haben wir Vref auf 3,3 V geändert – beachten Sie die Änderung der Maxima auf der Sinuswelle.

Jetzt können Sie mit dem DAC experimentieren, um Soundeffekte, Signale zu erzeugen oder andere analoge Schaltkreise zu steuern.

Schritt 5: Verwenden der ADCs (Analog-Digital-Wandler)

Wenn Sie die analogRead()-Funktion auf Ihrem Arduino verwendet haben (später in Kapitel Eins), dann sind Sie bereits mit einem ADC vertraut. Ohne PCF8591 können wir eine Spannung zwischen Null und Vref lesen und es wird einen Wert zwischen Null und 255 zurückgegeben, der direkt proportional zu Null und Vref ist.

Zum Beispiel sollte die Messung von 3,3 V 168 zurückgeben. Die Auflösung (8-Bit) des ADC ist niedriger als die des Onboard-Arduino (10-Bit), jedoch kann der PCF8591 etwas tun, was der ADC des Arduino nicht kann. Aber dazu kommen wir gleich. Um einfach die Werte jedes ADC-Pins zu lesen, senden wir zunächst ein Kontrollbyte, um dem PCF8591 mitzuteilen, welchen ADC wir lesen möchten. Für ADCs null bis drei ist das Kontrollbyte 0x00, 0x01, ox02 bzw. 0x03.

Dann fordern wir zwei Byte Daten vom ADC zurück und speichern das zweite Byte zur Verwendung. Warum zwei Byte? Der PCF8591 liefert zuerst den zuvor gemessenen Wert – dann das aktuelle Byte. (Siehe Abbildung 8 im Datenblatt). Wenn Sie nicht alle ADC-Pins verwenden, schließen Sie die unbenutzten an GND an. Die folgende Beispielskizze ruft einfach Werte von jedem ADC-Pin nacheinander ab und zeigt sie dann im seriellen Monitor an:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C-Busadresse #define ADC0 0x00 // Steuerbytes zum Lesen einzelner ADCs #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 Byte Wert0, Wert1, Wert2, Wert3; Void setup () { Wire.begin (); Serial.begin (9600); aufrechtzuerhalten. Void Schleife () { Wire.beginTransmission (PCF8591); // PCF8591 aufwecken Wire.write (ADC0); // Kontrollbyte - ADC0 Wire.endTransmission () lesen; // Übertragung beenden Wire.requestFrom(PCF8591, 2); value0=Wire.read(); value0=Wire.read(); Wire.beginTransmission(PCF8591); // PCF8591 aufwecken Wire.write (ADC1); // Kontrollbyte - ADC1 Wire.endTransmission () lesen; // Übertragung beenden Wire.requestFrom(PCF8591, 2); value1=Wire.read(); value1=Wire.read(); Wire.beginTransmission(PCF8591); // PCF8591 Wire.write (ADC2) aufwecken; // Kontrollbyte - ADC2 Wire.endTransmission () lesen; // Übertragung beenden Wire.requestFrom(PCF8591, 2); value2=Wire.read(); value2=Wire.read(); Wire.beginTransmission(PCF8591); // PCF8591 Wire.write (ADC3) aufwecken; // Kontrollbyte - ADC3 Wire.endTransmission () lesen; // Übertragung beenden Wire.requestFrom(PCF8591, 2); value3=Wire.read(); value3=Wire.read(); Serial.print (Wert0); Serial.print (" "); Serial.print (Wert1); Serial.print (" "); Serial.print (Wert2); Serial.print (" "); Serial.print (Wert3); Serial.print (" "); Serial.println(); }

Beim Ausführen der Skizze werden Ihnen die Werte jedes ADC im seriellen Monitor angezeigt. Obwohl es eine einfache Demonstration war, um Ihnen zu zeigen, wie Sie jeden ADC einzeln lesen, ist es eine umständliche Methode, mehr als ein Byte gleichzeitig von einem bestimmten ADC zu erhalten.

Schritt 6:

Um dies zu tun, ändern Sie das Kontrollbyte, um Auto-Inkrement anzufordern, was durch Setzen von Bit 2 des Kontrollbytes auf 1 erfolgt. Um von ADC0 aus zu beginnen, verwenden wir ein neues Kontrollbyte von binär 00000100 oder hexadezimal 0x04. Fordern Sie dann fünf Datenbytes an (wieder ignorieren wir das erste Byte), was dazu führt, dass der PCF8591 alle Werte in einer Bytekette zurückgibt. Dieser Vorgang wird in der folgenden Skizze demonstriert:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C-Busadresse Byte Wert0, Wert1, Wert2, Wert3; Void setup () { Wire.begin (); Serial.begin (9600); aufrechtzuerhalten. Void Schleife () { Wire.beginTransmission (PCF8591); // PCF8591 Wire.write (0x04) aufwecken; // Kontrollbyte - ADC0 lesen und dann automatisch inkrementieren Wire.endTransmission (); // Übertragung beenden Wire.requestFrom(PCF8591, 5); value0=Wire.read(); value0=Wire.read(); value1=Wire.read(); value2=Wire.read(); value3=Wire.read(); Serial.print (Wert0); Serial.print (" "); Serial.print (Wert1); Serial.print (" "); Serial.print (Wert2); Serial.print (" "); Serial.print (Wert3); Serial.print (" "); Serial.println(); }

Zuvor haben wir erwähnt, dass der PCF8591 etwas kann, was der ADC des Arduino nicht kann, und dies ist ein differentieller ADC. Im Gegensatz zum Single-Ended des Arduino (dh er gibt die Differenz zwischen der positiven Signalspannung und GND zurück, akzeptiert der Differenz-ADC zwei Signale (die nicht unbedingt auf Masse bezogen sein müssen) und gibt die Differenz zwischen den beiden Signalen zurück Dies kann praktisch sein, um kleine Spannungsänderungen für Wägezellen usw. zu messen.

Schritt 7:

Bild
Bild

Das Einrichten des PCF8591 für differentiellen ADC ist eine einfache Sache, das Steuerbyte zu ändern. Wenn Sie auf Seite sieben des Datenblatts blättern, dann betrachten Sie die verschiedenen Arten der Programmierung der Analogeingänge. Bisher haben wir den Modus’00’ für vier Eingänge verwendet, Sie können jedoch die anderen auswählen, die übersichtlich dargestellt sind, zum Beispiel das Bild.

Um also das Steuerbyte für zwei Differenzeingänge einzustellen, verwenden Sie binär 00110000 oder 0x30. Dann ist es eine einfache Sache, die Datenbytes anzufordern und mit ihnen zu arbeiten. Wie Sie sehen, gibt es auch eine Kombination aus Einfach/Differential und einen komplexen Drei-Differential-Eingang. Wir belassen sie jedoch vorerst.

Hoffentlich fanden Sie dies interessant, egal ob Sie Ihren Experimenten einen DAC hinzufügen oder etwas mehr über ADCs erfahren möchten. Bitte erwägen Sie, Ihren PCF8591 bei PMD Way zu bestellen.

Dieser Beitrag von pmdway.com – alles für Macher und Elektronik-Enthusiasten, weltweit versandkostenfrei.

Empfohlen: