Raspberry Pi

29) 12-bitový D/A převodník (MCP4921)

V článku č. 18 jsem vysvětloval zprovoznění A/D převodníku. V tomto článku se zaměřím na obvod, který má úplně opačnou funkci.
Do obvodu se z raspíčka pošle digitální číslo, a obvod ho převede na napětí.

Existují různé typy takovýchto převodníků. Některé komunikují přes sběrnici I2C, jiné mají pro každý bit vkládaného čísla samostatný vývod. Obvody se také liší citlivostí a rozsahem.

Protože ovládání pomocí sběrnice I2C je velice jednoduché a už jsem ho tu v různých článcích vysvětloval několikrát, vybral jsem si pro tento článek obvod, který komunikuje pomocí starší sběrnice SPI (stejně, jako výše uvedený A/D převodník v článku 18).

Tento D/A převodník má označení MCP4921

Sběrnice SPI potřebuje na rozdíl od I2C o trochu víc GPIO portů. 
Obvody, které se na takovouto sběrnici připojují, mají hodinový a datový vodič (stejně jako I2C). Pomocí těchto vodičů je možné propojovat paralelně jednotlivé obvody.
Navíc však potřebuje každý obvod ještě další vodič, pomocí kterého se určuje, jestli mu patří data na sběrnici. 

Tento vodič se obvykle označuje jako "Chip Select" (nebo "Chip Enable") -  zkráceně "CS" (nebo "CE"). Obvykle platí, že pokud je na něm logická "1", nevšímá si obvod signálů, které má na hodinovém a datovém vstupu. Když se tento "CS" signál nastaví na "0", začne obvod přijímat data.

Schéma zapojení je zde:

Šedou barvou je zobrazeno případné připojení A/D převodníku ze článku č.18. Jak je vidět, datové a hodinové vstupy obou obvodů jsou propojené.
Výběr D/A nebo A/D převodníku se provádí pomocí řídících signálů "CS" na GPIO21 a GPIO22.
Pokud je "0" na GPIO21, je právě aktivní A/D převodník. 
Když je "0" na GPIO22, je aktivní D/A převodník.
Nesmí však nastat situace, kdy by oba řídící signály byly v "0".  

Program pro ovládání D/A převodníku jsem vytvořil podle této části katalogového listu:

#!/usr/bin/env python
import sys
import time
import RPi.GPIO as GPIO


# podprogram pro kratke nastaveni hodin do "1" a navraceni do "0" - (tikani)
def tik():
  GPIO.output(SPISCK, True)   # SPISCK -> "1"
  time.sleep(pauza)
  GPIO.output(SPISCK, False)  # SPISCK -> "0"
  time. sleep(pauza)



pauza = 0.001 # delka pauzy pro "tikani" v sekundach

# pripojeni D/A prevodniku ke GPIO konektoru:
SPISCK = 11    # SCK   (noha 3) => GPIO11
SPISDI = 10    # SDI   (noha 4) => GPIO10
SPICS  = 22    # CS    (noha 2) => GPIO22
SPILDAC = 9    # LDAC  (noha 5) => GPIO9
#                Vdd   (noha 1) => +3,3V 
#                VrefA (noha 6) => +3,3V
#                AVss  (noha 7) => GND
#                VoutA (noha 8) .... to je analogovy vystup


# nastaveni GPIO portu
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(SPISCK , GPIO.OUT)
GPIO.setup(SPISDI , GPIO.OUT)
GPIO.setup(SPICS  , GPIO.OUT)
GPIO.setup(SPILDAC, GPIO.OUT)




#parametr prikazove radky (cislo v rozsahu 0 az 4095) se prevede na binarni tvar
hodnota = int(sys.argv[1])
binhodnota = str(bin(hodnota))[2:]

#promenna "binhodnota" se doplni zleva nulami na delku 12 znaku (bitu) 
while len(binhodnota) < 12: 
  binhodnota = "0" + binhodnota


# prevod zacina se vsemi signaly (mimo hodin) v "1" 
GPIO.output(SPICS  , True)
GPIO.output(SPISCK , False)
GPIO.output(SPISDI , True)
GPIO.output(SPILDAC, True)

time.sleep(pauza)

GPIO.output(SPICS  , False) # Chip Select na "0" = zahajeni komunikace


# prvni 4 bity jsou pro konfiguraci prevodniku
# dalsich 12 bitu je hodnota k prevedeni
# po kazdem bitu se provede na hodinovem vstupu "tiknuti"


# ---- 1. bit ---- (A/B)
# v pripade pouziti dvojiteho D/A prevodniku (MCP4922) se pomoci tohoto bitu voli kanal
# pri pouziti jednoducheho D/A prevodniku (MCP4921) musi byt nastaveno False
GPIO.output(SPISDI, False) # (False = kanal A ; True = kanal B)
tik()


# ---- 2. bit ----  (BUF)     buffer pro referencni napeti 
GPIO.output(SPISDI, False)  # (True = Buffered ; False = Unbuffered)
tik()


# ---- 3. bit ----  (GA)     zesileni vystupniho clenu
GPIO.output(SPISDI, True)  # (True = 1x ; False = 2x) 
tik()


# ---- 4. bit ----  (SHDN)   odpojovac vystupu
GPIO.output(SPISDI, True)  # (True = normalni rezim ; False = vystup odpojen)
tik()


# ---- dalsich 12 bitu prevadene hodnoty od MSB do LSB ----
for b in range(12): 
  bit = binhodnota[b:b+1]
  if (bit == "1"):
     GPIO.output(SPISDI, True)  
  else:
     GPIO.output(SPISDI, False)  
 
  tik()


GPIO.output(SPICS, True)  # Chip Select prepnout do "1"  = ukonceni komunikace


# prepsani analogove hodnoty na vystup kratkym nulovym pulsem na LDAC
GPIO.output(SPILDAC, False)  # LDAC -> "0"
time.sleep(pauza)
GPIO.output(SPILDAC, True)   # LDAC -> "1"




A tady je video z činnosti předchozího programu.
D/A převodník se nastavuje pomocí číselného parametru (mezi 0 a 4095):

Odkaz na YouTube

 

... a k čemu je to vlastně dobré?

Takovýto převodník sám o sobě není schopný regulovat svit žárovky, ani měnit otáčky stejnosměrného motoru. 
Regulace svitu LED diody je sice možná, ale jen v omezeném rozsahu (LEDka potřebuje k rozsvícení asi 2,5 V, takže když je na výstupu převodníku nižší napětí, tak LEDka nesvítí.)
Dá se použít jako regulovatelná napěťová reference, nebo jako programovatelný testovací zdroj stejnosměrného signálu 0 až 3,3V.

Obvod dokáže z výstupu dodat jen malý proud. Proto je třeba pro větší zátěže ten výstup ještě nějak zesílit a upravit.

Jako nejjednodušší zesilovač může posloužit třeba tranzistor.
Pomocí raspíčka se pak může například ovládat jas malé žárovičky.

Další možností je připojení k obvodu NE555. Pak se pomocí výstupu D/A převodníku může řídit frekvence nebo střída generátoru.
Změna frekvence je užitečná například pro generování tónů.
Pomocí změny střídy je možné třeba regulovat jas LED diod (PWM modulace).

Po přibastlení několika dalších součástek se pomocí D/A převodníku může vytvořit počítačově regulovatelný zdroj proudu (například 4 až 20mA), pomocí kterého je možné na velkou vzdálenost přenášet analogové signály, nebo dokonce digitálně komunikovat pomocí protokolu HART.

 

 

 


úvodní strana webu AstroMiK.org

poslední úprava stránky 19.1.2013