Inhoudsopgave:

Arduino en PCF8591 ADC DAC IC - Ajarnpa
Arduino en PCF8591 ADC DAC IC - Ajarnpa

Video: Arduino en PCF8591 ADC DAC IC - Ajarnpa

Video: Arduino en PCF8591 ADC DAC IC - Ajarnpa
Video: Модуль ADS1115, 16-Bit АЦП, Обзор 2024, November
Anonim
Arduino en PCF8591 ADC DAC IC
Arduino en PCF8591 ADC DAC IC

Heb je ooit meer analoge ingangspinnen op je Arduino-project willen hebben, maar niet op zoek naar een Mega? Of wilt u analoge signalen genereren? Bekijk dan het onderwerp van onze tutorial – de NXP PCF8591 IC.

Het lost beide problemen op, aangezien het een enkele DAC (digitaal naar analoog) converter heeft en vier ADC's (analoog naar digitaal converters) - allemaal toegankelijk via de I2C-bus. De PCF8591 is verkrijgbaar in DIP-, opbouw- en modulevorm, waardoor het gemakkelijk is om mee te experimenteren.

Download het gegevensblad voordat u verder gaat. De PCF8591 kan zowel op 5V als op 3,3V werken, dus als je een Arduino Due, Raspberry Pi of een ander 3,3 V-ontwikkelbord gebruikt, zit je goed. Nu zullen we eerst de DAC uitleggen, daarna de ADC's.

Stap 1: Gebruik van de DAC (digitaal-naar-analoog converter)

De DAC (digitaal-naar-analoog converter) gebruiken
De DAC (digitaal-naar-analoog converter) gebruiken

De DAC op de PCF8591 heeft een resolutie van 8 bits, zodat hij in 255 stappen een theoretisch signaal tussen nul volt en de referentiespanning (Vref) kan genereren. Voor demonstratiedoeleinden gebruiken we een Vref van 5V, en u kunt een lagere Vref gebruiken, zoals 3,3V of wat u maar wilt, de maximale waarde is … deze moet echter lager zijn dan de voedingsspanning.

Merk op dat wanneer er een belasting is op de analoge uitgang (een praktijksituatie), de maximale uitgangsspanning zal dalen - het gegevensblad (dat u hebt gedownload) toont een daling van 10% voor een belasting van 10 kΩ. Nu voor ons demonstratiecircuit.

Let op het gebruik van 10kΩ pull-up weerstanden op de I2C-bus, en de 10μF condensator tussen 5V en GND. Het I2C-busadres wordt ingesteld door een combinatie van pinnen A0 ~ A2 en met allemaal naar GND is het adres 0x90. De analoge uitgang kan worden genomen van pin 15 (en er is een aparte analoge GND op pin 13. Sluit ook pin 13 aan op GND en schakel GND in op Arduino GND.

Om de DAC te besturen, moeten we twee bytes aan gegevens verzenden. De eerste is de besturingsbyte, die eenvoudig de DAC activeert en is 1000000 (of 0x40) en de volgende byte is de waarde tussen 0 en 255 (het uitgangsniveau). Dit wordt gedemonstreerd in de volgende schets:

// Voorbeeld 52.1 PCF8591 DAC-demo

#include "Wire.h" #define PCF8591 (0x90 >> 1) // I2C busadres void setup() { Wire.begin(); } void loop() { for (int i=0; i<256; i++) { Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (0x40); // control byte - schakel DAC in (binair 1000000) Wire.write (i); // waarde om te verzenden naar DAC Wire.endTransmission (); // eind transmissie }

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

{ Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (0x40); // control byte - schakel DAC in (binair 1000000) Wire.write (i); // waarde om te verzenden naar DAC Wire.endTransmission (); // eindtransmissie } }

Heb je de bitverschuiving van het busadres opgemerkt in het #define-statement? Arduino verzendt 7-bits adressen, maar de PCF8591 wil een 8-bit, dus we verschuiven de byte met één bit.

Stap 2:

Afbeelding
Afbeelding

De resultaten van de schets worden getoond in de afbeelding, we hebben de Vref aangesloten op 5V en de oscilloscoop-sonde en GND op respectievelijk de analoge uitgang en GND.

Stap 3:

Afbeelding
Afbeelding

Als je van bochten houdt, kun je sinusgolven genereren met de onderstaande schets. Het gebruikt een opzoektabel in een array die de benodigde vooraf berekende gegevenspunten bevat:

// Voorbeeld 52.2 PCF8591 DAC-demo - sinusgolf

#include "Wire.h" #define PCF8591 (0x90 >> 1) // I2C-busadres 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, 0xD8, 0x 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFE, 0xFD, 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, 0xC1, 0xB 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 0x74, 0x77, 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, 0,0, 0x0F, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0,x 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,x 0x67, 0x64 0x70, 0x74, 0x77, 0x7A, 0x7D }; void setup() { Wire.begin(); } void loop() { for (int i=0; i<256; i++) { Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (0x40); // control byte - schakel DAC in (binair 1000000) Wire.write (sine_wave ); // waarde om te verzenden naar DAC Wire.endTransmission (); // eindtransmissie } }

Stap 4:

Afbeelding
Afbeelding

Voor de volgende DSO-afbeeldingsdump hebben we de Vref gewijzigd in 3,3V - let op de verandering in de maxima op de sinusgolf.

Nu kun je experimenteren met de DAC om geluidseffecten, signalen te maken of andere analoge circuits aan te sturen.

Stap 5: Gebruik van de ADC's (analoog-naar-digitaal converters)

Als je de functie analogRead() op je Arduino hebt gebruikt (ver terug in hoofdstuk één), dan ben je al bekend met een ADC. Zonder PCF8591 kunnen we een spanning lezen tussen nul en de Vref en het zal een waarde tussen nul en 255 retourneren die recht evenredig is met nul en de Vref.

Het meten van 3,3 V zou bijvoorbeeld 168 moeten opleveren. De resolutie (8-bit) van de ADC is lager dan de Arduino aan boord (10-bit), maar de PCF8591 kan iets doen wat de ADC van de Arduino niet kan. Maar daar komen we zo op terug. Ten eerste, om eenvoudig de waarden van elke ADC-pin te lezen, sturen we een controlebyte om de PCF8591 te vertellen welke ADC we willen lezen. Voor ADC's nul tot drie is de controlebyte respectievelijk 0x00, 0x01, ox02 en 0x03.

Vervolgens vragen we twee bytes aan gegevens terug van de ADC en slaan de tweede byte op voor gebruik. Waarom twee bytes? De PCF8591 retourneert eerst de eerder gemeten waarde – daarna de huidige byte. (Zie afbeelding 8 in het gegevensblad). Als u ten slotte niet alle ADC-pinnen gebruikt, sluit u de ongebruikte pinnen aan op GND. De volgende voorbeeldschets haalt eenvoudig de waarden één voor één op van elke ADC-pin en geeft ze vervolgens weer op de seriële monitor:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C-busadres #define ADC0 0x00 // control bytes voor het lezen van individuele ADC's #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 byte value0, value1, value2, value3; void setup() { Wire.begin(); Serieel.begin(9600); } void loop() { Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (ADC0); // controlebyte - lees ADC0 Wire.endTransmission (); // eindtransmissie Wire.requestFrom (PCF8591, 2); waarde0=Draad.lezen(); waarde0=Draad.lezen(); Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (ADC1); // controlebyte - lees ADC1 Wire.endTransmission (); // eindtransmissie Wire.requestFrom (PCF8591, 2); waarde1=Draad.lezen(); waarde1=Draad.lezen(); Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (ADC2); // controlebyte - lees ADC2 Wire.endTransmission (); // eindtransmissie Wire.requestFrom (PCF8591, 2); value2=Draad.lezen(); value2=Draad.lezen(); Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (ADC3); // controlebyte - lees ADC3 Wire.endTransmission (); // eindtransmissie Wire.requestFrom (PCF8591, 2); value3=Draad.lezen(); value3=Draad.lezen(); Serial.print(waarde0); Serieel.print(" "); Serial.print(waarde1); Serieel.print(" "); Serial.print(waarde2); Serieel.print(" "); Serial.print(waarde3); Serieel.print(" "); Serieel.println(); }

Bij het uitvoeren van de schets krijgt u de waarden van elke ADC in de seriële monitor te zien. Hoewel het een eenvoudige demonstratie was om u te laten zien hoe u elke ADC afzonderlijk kunt lezen, is het een omslachtige methode om meer dan één byte tegelijk van een bepaalde ADC te krijgen.

Stap 6:

Om dit te doen, wijzigt u de besturingsbyte om auto-increment aan te vragen, wat wordt gedaan door bit 2 van de besturingsbyte in te stellen op 1. Dus om vanaf ADC0 te beginnen, gebruiken we een nieuwe besturingsbyte van binair 00000100 of hexadecimaal 0x04. Vraag dan vijf bytes aan data aan (we negeren wederom de eerste byte), waardoor de PCF8591 alle waarden in één keten van bytes retourneert. Dit proces wordt gedemonstreerd in de volgende schets:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C-busadres byte waarde0, waarde1, waarde2, waarde3; void setup() { Wire.begin(); Serieel.begin(9600); } void loop() { Wire.beginTransmission (PCF8591); // wakker worden PCF8591 Wire.write (0x04); // controlebyte - lees ADC0 en verhoog vervolgens automatisch Wire.endTransmission (); // eindtransmissie Wire.requestFrom (PCF8591, 5); waarde0=Draad.lezen(); waarde0=Draad.lezen(); waarde1=Draad.lezen(); value2=Draad.lezen(); value3=Draad.lezen(); Serial.print(waarde0); Serieel.print(" "); Serial.print(waarde1); Serieel.print(" "); Serial.print(waarde2); Serieel.print(" "); Serial.print(waarde3); Serieel.print(" "); Serieel.println(); }

Eerder vermeldden we dat de PCF8591 iets kan doen wat de ADC van de Arduino niet kan, en dit is een differentiële ADC. In tegenstelling tot de Arduino's single-ended (dwz het retourneert het verschil tussen de positieve signaalspanning en GND, accepteert de differentiële ADC twee signalen (die niet noodzakelijkerwijs naar aarde hoeven te worden verwezen) en retourneert het verschil tussen de twee signalen Dit kan handig zijn voor het meten van kleine veranderingen in spanningen voor loadcellen, enzovoort.

Stap 7:

Afbeelding
Afbeelding

Het instellen van de PCF8591 voor differentiële ADC is een kwestie van eenvoudig de besturingsbyte wijzigen. Als u naar pagina zeven van het gegevensblad gaat, overweeg dan de verschillende soorten analoge ingangsprogrammering. Voorheen gebruikten we modus '00' voor vier ingangen, maar u kunt de andere selecteren die duidelijk worden geïllustreerd, bijvoorbeeld de afbeelding.

Dus om de stuurbyte voor twee differentiële ingangen in te stellen, gebruikt u binair 00110000 of 0x30. Dan is het een kwestie van de bytes aan data opvragen en ermee werken. Zoals je kunt zien, is er ook een combinatie van enkelvoudig / differentieel en een complexe invoer met drie differentiëlen. We laten ze echter voorlopig staan.

Hopelijk vond je dit interessant, of je nu een DAC aan je experimenten toevoegt of iets meer leert over ADC's. Overweeg om uw PCF8591 bij PMD Way te bestellen.

Dit bericht aangeboden door pmdway.com - alles voor makers en elektronica-enthousiastelingen, met gratis levering wereldwijd.

Aanbevolen: