|
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):
... 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.
|
|
|