Innehållsförteckning:

Arduino och PCF8591 ADC DAC IC: 7 steg
Arduino och PCF8591 ADC DAC IC: 7 steg

Video: Arduino och PCF8591 ADC DAC IC: 7 steg

Video: Arduino och PCF8591 ADC DAC IC: 7 steg
Video: IoT Introduction 2019 Session 10 - Fixing the Internet of Broken Things, Lighting 2024, Juli
Anonim
Arduino och PCF8591 ADC DAC IC
Arduino och PCF8591 ADC DAC IC

Har du någonsin velat ha fler analoga ingångar på ditt Arduino -projekt, men inte velat gaffla ut en Mega? Eller vill du generera analoga signaler? Kolla sedan in ämnet för vår handledning - NXP PCF8591 IC.

Den löser båda dessa problem eftersom den har en enda DAC (digital till analog) omvandlare samt fyra ADC (analog till digital omvandlare) - alla tillgängliga via I2C -bussen. PCF8591 finns i DIP, ytmontering och modulform, vilket gör det enkelt att experimentera med.

Ladda ner databladet innan du går vidare. PCF8591 kan fungera på både 5V och 3.3V, så om du använder en Arduino Due, Raspberry Pi eller en annan 3.3 V utvecklingskort går det bra. Nu ska vi först förklara DAC, sedan ADC: erna.

Steg 1: Använda DAC (digital-till-analog-omvandlare)

Använda DAC (digital-till-analog-omvandlare)
Använda DAC (digital-till-analog-omvandlare)

DAC på PCF8591 har en upplösning på 8 bitar-så den kan generera en teoretisk signal mellan noll volt och referensspänningen (Vref) i 255 steg. För demonstrationsändamål använder vi en Vref på 5V, och du kan använda en lägre Vref som 3.3V eller vad du vill att det maximala värdet ska vara … men det måste vara mindre än matningsspänningen.

Observera att när det finns en belastning på den analoga utgången (en verklig situation), kommer den maximala utspänningen att sjunka-databladet (som du laddade ner) visar en 10% minskning för en 10kΩ belastning. Nu till vår demonstrationskrets.

Observera användningen av 10kΩ uppdragningsmotstånd på I2C-bussen och 10μF-kondensatorn mellan 5V och GND. I2C -bussadressen ställs in med en kombination av stift A0 ~ A2, och med dem alla till GND är adressen 0x90. Den analoga utgången kan tas från stift 15 (och det finns en separat analog GND på stift 13. Anslut också stift 13 till GND och krets GND till Arduino GND.

För att styra DAC måste vi skicka två byte med data. Den första är kontrollbyten, som helt enkelt aktiverar DAC och är 1000000 (eller 0x40) och nästa byte är värdet mellan 0 och 255 (utgångsnivån). Detta visas i följande skiss:

// Exempel 52.1 PCF8591 DAC -demo

#inkludera "Wire.h" #define PCF8591 (0x90 >> 1) // I2C -bussadress tomrumsinställning () {Wire.begin (); } void loop () {för (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (0x40); // kontrollbyte - slå på DAC (binärt 1000000) Wire.write (i); // värde att skicka till DAC Wire.endTransmission (); // avsluta överföring}

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

{Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (0x40); // kontrollbyte - slå på DAC (binärt 1000000) Wire.write (i); // värde att skicka till DAC Wire.endTransmission (); // avsluta överföring}}

Märkte du bitskiftet i bussadressen i #define -uttalandet? Arduino skickar 7-bitars adresser men PCF8591 vill ha en 8-bit, så vi byter byten med en bit.

Steg 2:

Bild
Bild

Resultaten av skissen visas i bilden, vi har anslutit Vref till 5V och oscilloskopproben och GND till den analoga utgången respektive GND.

Steg 3:

Bild
Bild

Om du gillar kurvor kan du generera sinusvågor med skissen nedan. Den använder en uppslagstabell i en array som innehåller de nödvändiga förberäknade datapunkterna:

// Exempel 52.2 PCF8591 DAC demo - sinusvåg

#inkludera "Wire.h" #define PCF8591 (0x90 >> 1) // I2C -bussadress 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, 0xD 0, 0xD 0, 0xD 0, 0xD, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF0, 0xF, 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xB9, 0xB, 0xB, 0xB 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7, 0x6, 0x6 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, 0x0, 0x0, 0x0, 0x0 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0, 0x0, 0x0, 0x3 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x20, 0x20, 0x, 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5, 0x6, 0x6, 0x6, 0x6, 0x6 0x70, 0x74, 0x77, 0x7A, 0x7D}; void setup () {Wire.begin (); } void loop () {för (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (0x40); // kontrollbyte - slå på DAC (binärt 1000000) Wire.write (sinus_våg ); // värde att skicka till DAC Wire.endTransmission (); // avsluta överföring}}

Steg 4:

Bild
Bild

För följande DSO -bilddump ändrade vi Vref till 3,3V - notera ändringen av maxima på sinusvåg.

Nu kan du experimentera med DAC för att göra ljudeffekter, signaler eller styra andra analoga kretsar.

Steg 5: Använda ADC: erna (analog-till-digital-omvandlare)

Om du har använt analogRead () -funktionen på din Arduino (långt tillbaka i kapitel ett) så är du redan bekant med en ADC. Utan PCF8591 kan vi läsa en spänning mellan noll och Vref och den kommer att returnera ett värde mellan noll och 255 som är direkt proportionellt mot noll och Vref.

Till exempel bör mätning av 3.3V returnera 168. Upplösningen (8-bitars) för ADC är lägre än den inbyggda Arduino (10-bitars) men PCF8591 kan göra något som Arduinos ADC inte kan. Men vi kommer till det om ett ögonblick. För det första, för att helt enkelt läsa värdena för varje ADC -pin skickar vi en kontrollbyte för att berätta för PCF8591 vilken ADC vi vill läsa. För ADC noll till tre är kontrollbyten 0x00, 0x01, ox02 respektive 0x03.

Sedan ber vi om två byte med data från ADC och lagrar den andra byten för användning. Varför två byte? PCF8591 returnerar det tidigare uppmätta värdet först - sedan den aktuella byte. (Se figur 8 i databladet). Slutligen, om du inte använder alla ADC -stiften, anslut de oanvända till GND. Följande exempelskiss hämtar helt enkelt värden från varje ADC -stift en i taget och visar dem sedan i seriemonitorn:

#inkludera "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C -bussadress #define ADC0 0x00 // kontrollbyte för avläsning av enskilda ADCs #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 byte värde0, värde1, värde2, värde3; void setup () {Wire.begin (); Serial.begin (9600); } void loop () {Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (ADC0); // kontrollbyte - läs ADC0 Wire.endTransmission (); // sluttransmission Wire.requestFrom (PCF8591, 2); värde0 = Wire.read (); värde0 = Wire.read (); Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (ADC1); // kontrollbyte - läs ADC1 Wire.endTransmission (); // sluttransmission Wire.requestFrom (PCF8591, 2); värde1 = Wire.read (); värde1 = Wire.read (); Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (ADC2); // kontrollbyte - läs ADC2 Wire.endTransmission (); // sluttransmission Wire.requestFrom (PCF8591, 2); värde2 = Wire.read (); värde2 = Wire.read (); Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (ADC3); // kontrollbyte - läs ADC3 Wire.endTransmission (); // sluttransmission Wire.requestFrom (PCF8591, 2); value3 = Wire.read (); value3 = Wire.read (); Serial.print (värde0); Serial.print (""); Serial.print (värde1); Serial.print (""); Serial.print (värde2); Serial.print (""); Serial.print (värde3); Serial.print (""); Serial.println (); }

När du kör skissen presenteras värdena för varje ADC i seriemonitorn. Även om det var en enkel demonstration för att visa dig hur du individuellt läser varje ADC, är det en besvärlig metod att få mer än en byte i taget från en viss ADC.

Steg 6:

För att göra detta, ändra kontrollbyten för att begära automatisk inkrement, vilket görs genom att ställa in bit 2 i kontrollbyten till 1. Så för att börja från ADC0 använder vi en ny kontrollbyte i binär 00000100 eller hexadecimal 0x04. Begär sedan fem byte med data (återigen ignorerar vi den första byten) vilket kommer att få PCF8591 att returnera alla värden i en kedja av byte. Denna process visas i följande skiss:

#inkludera "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C bussadress byte värde0, värde1, värde2, värde3; void setup () {Wire.begin (); Serial.begin (9600); } void loop () {Wire.beginTransmission (PCF8591); // väck upp PCF8591 Wire.write (0x04); // kontrollbyte - läs ADC0 och sedan automatiskt öka Wire.endTransmission (); // sluttransmission Wire.requestFrom (PCF8591, 5); värde0 = Wire.read (); värde0 = Wire.read (); värde1 = Wire.read (); värde2 = Wire.read (); value3 = Wire.read (); Serial.print (värde0); Serial.print (""); Serial.print (värde1); Serial.print (""); Serial.print (värde2); Serial.print (""); Serial.print (värde3); Serial.print (""); Serial.println (); }

Tidigare nämnde vi att PCF8591 kan göra något som Arduino ADC inte kan, och detta är att erbjuda en differentiell ADC. I motsats till Arduinoens enda ände (dvs den returnerar skillnaden mellan den positiva signalspänningen och GND, accepterar differential ADC två signaler (som inte nödvändigtvis behöver refereras till jord) och returnerar skillnaden mellan de två signalerna Detta kan vara bekvämt för att mäta små förändringar i spänningar för lastceller och så vidare.

Steg 7:

Bild
Bild

Att konfigurera PCF8591 för differentiell ADC är en enkel fråga om att ändra kontrollbyten. Om du går till sidan sju i databladet, överväg sedan de olika typerna av analog ingångsprogrammering. Tidigare använde vi läge '00' för fyra ingångar, men du kan välja de andra som är tydligt illustrerade, till exempel bilden.

Så för att ställa in kontrollbyten för två differentialingångar, använd binär 00110000 eller 0x30. Då är det en enkel fråga att begära databyte och arbeta med dem. Som du kan se finns det också kombinationen singel/differential och en komplex tre-differential ingång. Men vi lämnar dem tills vidare.

Förhoppningsvis fann du detta intressant, oavsett om du lägger till en DAC i dina experiment eller lär dig lite mer om ADC. Vänligen överväg att beställa din PCF8591 från PMD Way.

Det här inlägget kommer till dig av pmdway.com - allt för tillverkare och elektronikentusiaster, med gratis leverans över hela världen.

Rekommenderad: