Fyzikální kabinet FyzKAB
Články Modul Arduino (něco navíc) Arduino – D/A výstup

Arduino – D/A výstup

Doplnění modulu Arduino o D/A převodník pro získání plnohodnotného analogového výstupu

Modul Arduino UNO (Leonardo) je unikátní svou všestrannou univerzálností, přesto má jednu slabost. Tou je absence plnohodnotného analogového výstupu. Modul sice umožňuje analogový výstup „mírně” nahradit výstupem s PWM modulací, ale pokud chceme skutečně výstup, na kterém se bude měnit napětí v zadaném intervalu, PWM nám moc nepomůže.

Pokusíme se zde ukázat několik způsobů, jak tento nedostatek odstranit.

Převodník PWM-Analog

První možností je převedení PWM signálu na napěťovou úroveň. Jedno takové zapojení můžeme vidět na obrázku č. 1.

převodník PWM-D/A
Obr. 1 – převodník signálu PWM na anologový výstup

Na straně PWM vstupuje pulzně modulovaný signál, ten si můžeme představit jako součet dvou složek – střídavé a stejnosměrné. Změnou šířky signálu (PWM – šířkově modulovaný signál) se vlastně mění vzájemný podíl těchto dvou složek. Podaří-li se nám tedy z PWM signálu získat jen složku stejnosměrnou, měla by být její velikost úměrná šířce signálu, tedy vysílané hodnotě. K tomu použijeme RC filtr – tzv. dolní propusť (zapojení vidíme na obr. 1 v levé části). Přes rezistor R1 přichází signál na kondenzátor C1, který střídavou složku „uzemňuje” a naopak se nabíjí složkou stejnosměrnou. Napětí na tomto kondenzátoru je tedy úměrné šířce napěťových pulzů PWM modulace. Následný operační zesilovač (kupř. TLV274) toto napětí proudově posílí (napěťový sledovač) a přes rezistor R2 je napěťový výstup přiveden na výstup (analogový) DAC.

Tento obvod pak lze připojit na jakýkoliv PWM výstup modulu Arduino – například piny 3, 5, 6, 9, 10, 11 (13 u modulu Leonardo).

D/A převodník

Další možností je připojení některého z dostupných D/A převodníků na digitální výstupy modulu Arduino. Je na zvážení každého z vývojářů, nač budou modul Arduino využívat – dle toho je možné využít D/A převodník paralelním, či sériový.

Paralelní D/A převodník

Paralelní převodník má výhodu rychlého zápisu dat na vstup a tedy téměř okamžitou analogovou hodnotu na výstupu. Na druhou stranu paralelní přístup vyžaduje několika bitovou vstupní sběrnici a tedy obsazení hned několika digitálních výstupních pinů modulu Arduino.

převodník TLC7524
Obr. 2 – vývody D/A převodníku TLC7524 (popř. AD7524)

Poměrně jednoduchým paralelním D/A převodníkem je obvod TLC7524 (popř. AD7524). Jedná se o paralelní osmibitový D/A převodník – jeho jednotlivé vývodu vidíme na obr. č. 2.

Piny 4–11 jsou datové vstupní signály (jednotlivé bity převáděné hodnoty). Pin 12 slouží pro aktivaci celého obvodu (Chip Select). Pin 13 (WR) slouží pro řízení zápisu vstupních dat do převodníku a na výstup (viz časové schéma dále – obr. č. 3).  Vývody 15 a 16 souvisí s referenčním napětím potřebným pro převod (viz datový list obvodu). A konečně piny 1 a 2 jsou piny analogového výstupu převodníku.

Pro naše „digitálně-analogové hrátky” s tímto převodníkem využijeme jeden takový malý trik, kdy využijeme jeho vnitřní rezistorové struktury. Při standardním zapojení přesvodníku se k výstupům ještě připojuje operační zesilovač. My však využijeme tento obvod DA převodníku samotný. Pochopitelně naše zapojení je proudově omezeno, ale pokud potřebujeme čistě napěťový výstup, tak je to zapojení ideální.

Obvod trvale aktivujeme – tedy vývod 12 (CS) připojíme trvale k úrovni LOW (0 V). Řízení D/A převodu pak bude probíhat přesně dle dále uvedeného časového diagramu (obr. 3).

TLC7528 - časový diagram
Obr. 3 – časový diagram D/A převodníku TLC7528

Řízení tedy provádíme jen pomocí signálu WR. Přivedením úrovně LOW na signál WR, převedeme obvod do režimu zápisu, tedy datové signály se načtou do vstupního bufferu obvodu. Převedením signálu WR do stavu HIGH se data z tohoto bufferu zapíší do vnitřní paměti (Latch) a jsou převedeny do analogové podoby. Tam vydrží až do okamžiku další změnu signálu WR ze stavu LOW do HIGH.

Schéma

Jak bylo zmíněno dříve, jedná se o trochu nestandardní (leč zcela elektronicky legální!) zapojení. Pro vstup referenčního napětí +5 V slouží pin OUT1, který jinak slouží jako analogový výstup převodníku. Druhý výstupní pin OUT2 je připojen na zem GND. Výstupní napětí, které svou velikostí odpovídá vstupní digitální hodnotě, je jako výstup převodníku vyvedeno z vývodu Vref. Celé zapojení znázorňuje schéma na obrázku 4.
I když toto zapojení vypadá poněkud podivně, je doporučeno datovým listem převodníku AD7524 a máme ho i osobně vyzkoušené.

zapojeni DAC AD7524 k Arduino
Obr. 4 – zapojení D/A převodníku TLC7524 (popř. AD7524) k modulu Arduino
Kód
/* Arduino DAC out s AD7524JN */

// DA prevodnik
#define DAC_WR1 A1   // A1 - /WR1 (zapis do DAC)
#define DAC_D0 13   // 13 - D0 (1. bit DAC)
#define DAC_D1 12   // 12 - D1 (2. bit DAC)
#define DAC_D2 11   // 11 - D2 (3. bit DAC)
#define DAC_D3 10   // 10 - D3 (4. bit DAC)
#define DAC_D4 9   // 9 - D4 (5. bit DAC)
#define DAC_D5 8   // 8 - D5 (6. bit DAC)
#define DAC_D6 7   // 7 - D6 (7. bit DAC)
#define DAC_D7 6   // 6 - D7 (8. bit DAC)

float value = 0; // promenna pro vystup

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup () {
   pinMode(DAC_WR1, OUTPUT);   // /WR1
   pinMode(DAC_D0, OUTPUT);   // DATA 0
   pinMode(DAC_D1, OUTPUT);   // DATA 1
   pinMode(DAC_D2, OUTPUT);   // DATA 2
   pinMode(DAC_D3, OUTPUT);   // DATA 3
   pinMode(DAC_D4, OUTPUT);   // DATA 4
   pinMode(DAC_D5, OUTPUT);   // DATA 5
   pinMode(DAC_D6, OUTPUT);   // DATA 6
   pinMode(DAC_D7, OUTPUT);   // DATA 7

   digitalWrite(DAC_WR1,HIGH);   //vychozi nastaveni WR na HIGH
}

void DAC (byte X) { // odeslani X na DAC
   if (X & 1) digitalWrite(DAC_D0,HIGH);   // vymaskovani 1. bitu z promenne X
   else digitalWrite(DAC_D0,LOW);
   if (X & 2) digitalWrite(DAC_D1,HIGH);   // vymaskovani 2. bitu z promenne X
   else digitalWrite(DAC_D1,LOW);
   if (X & 4) digitalWrite(DAC_D2,HIGH);
   else digitalWrite(DAC_D2,LOW);
   if (X & 8) digitalWrite(DAC_D3,HIGH);
   else digitalWrite(DAC_D3,LOW);
   if (X & 16) digitalWrite(DAC_D4,HIGH);
   else digitalWrite(DAC_D4,LOW);
   if (X & 32) digitalWrite(DAC_D5,HIGH);
   else digitalWrite(DAC_D5,LOW);
   if (X & 64) digitalWrite(DAC_D6,HIGH);
   else digitalWrite(DAC_D6,LOW);
   if (X & 128) digitalWrite(DAC_D7,HIGH);
   else digitalWrite(DAC_D7,LOW);

   digitalWrite(DAC_WR1,LOW);   // zapis nastavenych bitu do DAC
   delayMicroseconds(10);
   digitalWrite(DAC_WR1,HIGH);
}

// funkce LOOP bezi stale dokola.
void loop() {
   for(int i=0; i<=4096; i++) {
     value = (int) 128*sin((2*PI/4096)*i)+127;
     DAC(value);
//   delay(50); // nastaveni rychlosti generovane sinusoidy (nyni co nejrychlejsi)
   }
}

Sériový D/A převodník

Sériový D/A převodník má oproti paralelnímu tu výhodu, že data se do něj zapisují postupně a tedy vystačí zpravidla s dvěma signálovými vodiči (DATA a synchronizační CLOCK). Díky tomu lze u sériového převodníku dosáhnout i vyššího rozlišení – lze např. postupně do převodníku zaslat 12 bitů, což by v případě paralelního převodníku zabralo skoro všechny digitální výstupy modulu Arduino. Negativním efektem toho je však všeobecná nevýhoda sériových D/A převodníků, a to nutný čas pro postupné načtení všech bitů převáděné hodnoty – nižší celková rychlost převodníku.

převodník MCP4921
Obr. 5 – vývody D/A převodníku MCP4921

Jedním z levnějších, ale opět pro naše pokusy zcela dostačujícím, převodníkem je obvod MCP4921. Jedná se o sérový D/A převodník s 12 bitovým rozlišením. Rozložení jeho pinů vidíme na obrázku č. 5. Kromě napájecích pinů 1 a 7, zde vidíme pin 2 – CS (Chip Select) pro aktivaci zápisu do obvodu, pin 3 – CLK (hodinový signál pro zápis dat), pin 4 – SDI (Seriál Data Input – sériový vstup dat), pin 6 – Vref (referenční napětí pro převod) a pin 8 – Vout (výstupní analogové napětí). Pin 5 – LDAC obsluhuje dvojitý vnitřní buffer (zápis dat ze vstupu na výstup) – my tento vývod připojíme k úrovni LOW, čímž vnitřní buffer překleneme, a tak zápisem sérových dat se okamžitě zadaná data zobrazí na výstupu.

Ještě je třeba dodat, že se přes pin 4 (SDI) do převodníku nezapisuje jen 12 bitů převáděné hodnoty, ale předcházejí jim 4 bity konfigurační (doporučuji nahlédnout datový list obvodu). Komunikace by obecně měla probíhat podle níže uvedeného schéma (obr. č. 6).

převodník MCP4921 - časový diagram
Obr. 6 – časový diagram převodníku MCP4921

My celkovou komunikaci uzemněním pinu LDAC zjednodušíme – zápis zaházíme pomocí nastavení signálu CS na LOW. Pak následuje načtení dat pomocí CLK a SDI. Převod a vystavení výstupní hodnoty se provede zdvižením signálu CS na hodnotu HIGH.

Obvod MCP4921 není jen obyčejným sériovým D/A převodníkem, ale jeho sériové vstupy jsou navrženy tak, aby je bylo možné připojit ke sběrnici se standardem SPI™. Jelikož se jedná o standardní komunikační protokol, existuje již pro modul Arduino hotová knihovna, která nám celé řízení převodníku pomocí SPI™ zjednoduší.

Schéma
Připojení převodníku MCP4921 k Arduino
Obr. 7 – schéma připojení D/A předovníku MCP4921 k modulu Arduino

Dále uvedený kód má za úkol vytvořit z modulu Arduino jednoduchý generátor funkce sinus s rozsahem 0–5 V (12 bitové rozlišení).

Kód:
//-------------------------------
// 12 bit ADC  MCP4921
// inspired by Bart Venneker - thank!
//-------------------------------
// arduino pin 9  = SS (Slave select, pin 2 on the chip)
// arduino pin 11 = Data In (pin 4 on device)
// arduino pin 13 = clock (pin 3 on device)
// output of the DAC goes to the scope (pin 8 on the chip)
#include <SPI.h>
#define CS_DAC 9
float value = 0;

void setup() {
  pinMode(CS_DAC,OUTPUT);
  digitalWrite(CS_DAC,HIGH);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV2);
}

void Write4921(int value, int CS) {
  byte data;
  digitalWrite(CS, LOW);
  data = highByte(value);
  data = B00001111 & data;
  data = B00110000 | data;
  SPI.transfer (data);
  data = lowByte(value);
  SPI.transfer (data);
  digitalWrite(CS, HIGH);
}

void loop() {
  for(int i=0; i<=4096; i++) {
    value = (int) 2048*sin((2*PI/4096)*i)+2048;
    Write4921(value, CS_DAC);
//    delay(50); // nastaveni rychlosti generovane sinusoidy (nyni co nejrychlejsi)
  }
}

Výše popsaným způsobem lze modul Arduino rozšířit o D/A převodník MCP4921 a tím získat plnohodnotný napěťový analogový výstup – viz obr. 7.

rozšíření modulu Adruino D/A převodníkem MCP4521
Obr. 7 – připojení D/A předovníku MCP4921 k modulu Arduino
Autor článku: Miroslav Panoš
UPOZORNĚNÍ:
Nesouhlasíme s vyřazením Newtonových zákonů, Ohmova zákona a zákona zachování energie z učiva fyziky základních škol v České republice!