Raspberry Pi

18) A/D převodník MCP3208

POZOR

Všechny návody a příklady na této stránce
 platí pro Raspberry Pi verze 1 
(starší verze bez dvou montážních otvorů v desce) 

Novější verze 2 má trochu jinak číslované některé
vývody na GPIO konektoru.

Popis rozdílů obou variant je zde: http://elinux.org/....28GPIO.29


Samotné Raspíčko neumí zpracovávat analogové signály. Stačí k němu ale připojit jeden obvod a okamžitě je k dispozici 8 analogových vstupů. Takže se dá RasPi použít jako osminásobný voltmetr. Pokud se přidělají ještě nějaké vstupní převodníky, bude možné měřit nejen napětí, ale také třeba proud, odpor nebo i střídavé signály a jiné elektrické veličiny. Tato rozšíření zde ale nebudu uvádět. Zaměřím se jen na ten základ, a to je osminásobný stejnosměrný voltmetr.

Hned na začátku musím upozornit, že přesnost měření závisí hodně na referenčním napětí, které je přivedeno na vývod č.15 A/D převodníku. V následujícím popisu je tento vývod připojen na napájecí napětí 3,3V. Toto napětí ale není úplně přesné a také trochu kolísá podle aktuálního výkonu procesoru a podle počtu a stavu připojených periférií. Pokud byste chtěli větší přesnost, muselo by se na tento referenční vstup připojit přesné a stabilní napětí. Například pomocí napěťové reference (vysvětlení třeba zde: hw.cz).

Při zprovozňování A/D převodníku jsem vycházel z těchto stránek:
http://learn.adafruit.com/reading-a-analog-in-and-controlling-audio-volume-with-the-raspberry-pi/overview

Místo převodníku MCP3008, který je tam uvedený, jsem použil MCP3208. Je podobný a má i stejně zapojené vývody.
Liší se pouze v rozlišení. MCP3008 je desetibitový a MCP3208 je dvanáctibitový.
To znamená, že pokud je referenční napětí nastaveno na 3,3V, odpovídá změna čísla A/D převodu o jedničku u desetibitového obvodu MCP3008 změně napětí asi 3,2mV. U dvanáctibitového obvodu MCP3208 je to asi 0,8mV.

Jako vstup jsem použil víceotáčkový trimr, který jsem zapojil jako dělič napětí a připojil jsem ho jedním koncem na napájecí napětí (3,3V) a druhým koncem na GND (0V). Střední vodič jsem pak přímo přivedl na první vstup A/D převodníku (CH0), takže se na tomto vstupu mohlo plynule regulovat napětí od 0 do 3,3V. Zároveň jsem na tomto vstupu kontroloval napětí multimetrem.

 

Protože jsem chtěl pouze měřit napětí, přeskočil jsem z výše uvedeného návodu všechny kroky, které se zabývaly ovládáním hlasitosti.
Takže zbylo jen toto:

1) Nainstalovat nejnovější Python:

sudo apt-get install python-dev


2) Pokud není nainstalována Pythoní podpora pro GPIO z minulých příkladů, tak je třeba jí doinstalovat:
sudo apt-get install python-pip
sudo pip install rpi.gpio


3) Vytvořit soubor v /home/pi/ a nazvat ho třeba adc.py
sudo nano /home/pi/adc.py

 ... a vložit do něj kód z těchto stránek:
http://learn.adafruit.com/reading-a-analog-in-and-controlling-audio-volume-with-the-raspberry-pi/script  
Pak uložit a zavřít (Ctrl+X, Y, Enter)


Protože jsem už měl nějaké GPIO obsazené z předchozích pokusů (připojení displeje), musel jsem trochu upravit zapojení na volné GPIO porty a v konfiguraci skriptu jsem tyto nově zapojené porty musel nadefinovat:

Změny byly v těchto 4 vodičích:
- noha 13 u MCP3208 (CLK) byla původně GPIO18 (pin12) a já to změnil na GPIO11 (pin23)
- noha 12 u MCP3208 (DOUT) byla původně GPIO23 (pin16) a já to změnil na GPIO9 (pin21)
- noha 11 u MCP3208 (DIN) byla původně GPIO24 (pin18) a já to změnil na GPIO10 (pin19)
- noha 10 u MCP3208 (CS) byla původně GPIO25 (pin22) a já to změnil na GPIO21 (pin13)



A protože nechci řídit hlasitost, tak jsem vyházel kusy kódu, které se o tu hlasitost staraly. 
Nechal jsem jen zobrazovat hodnotu A/D převodníku a přepočtenou hodnotu napětí.
Také jsem musel ve skriptu změnit o dva bity rozlišení převodníku.

Takže celý upravený skript vypadá takto:

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

GPIO.setmode(GPIO.BCM)

# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
        if ((adcnum > 7) or (adcnum < 0)):
                return -1
        GPIO.output(cspin, True)

        GPIO.output(clockpin, False) # start clock low
        GPIO.output(cspin, False) # bring CS low

        commandout = adcnum
        commandout |= 0x18 # start bit + single-ended bit
        commandout <<= 3 # we only need to send 5 bits here
        for i in range(5):
                if (commandout & 0x80):
                        GPIO.output(mosipin, True)
                else:
                        GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

        adcout = 0

        # read in one empty bit, one null bit and 12 ADC bits
        # pro desetibitovy prevodnik tu bylo puvodne cislo 12
        for i in range(14):
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)
                adcout <<= 1
                if (GPIO.input(misopin)):
                        adcout |= 0x1

        GPIO.output(cspin, True)
        
        adcout >>= 1 # first bit is 'null' so drop it
        return adcout

# change these as desired - they're the pins connected from the
# SPI port on the ADC to the Cobbler
SPICLK = 11    # zmena z puvodniho 18
SPIMISO = 9    # zmena z puvodniho 23
SPIMOSI = 10   # zmena z puvodniho 24
SPICS = 21     # zmena z puvodniho 25

# set up the SPI interface pins
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)

# 10k trim pot connected to adc #0
potentiometer_adc = 0;

while True:
        # a tady jen cyklicke cteni dat a prepocet trojclenkou na napeti
        # vsechno ostatni jsem vyhazel

        trim_pot = readadc(potentiometer_adc, SPICLK, SPIMOSI, SPIMISO, SPICS)

        # 3,3V je reference (rozsah mereni), 4095 je maximalni hodnota prevodniku
        napeti = 3.3 * trim_pot / 4095 

        print "Digital:", trim_pot , "\t Napeti:", round(napeti,3), "V"

        time.sleep(0.5)


exit (0)

Proměnná potentiometer_adc udává, ze kterého vstupu se má napětí převádět.
Je možné měřit až 8 nezávislých vstupů se společnou zemí (0 až 7).

V návodu se píše, že má mít skript nastaven atribut spustitelnosti, ale fungovalo to i když jsem ho nenastavoval.

Na závěr už stačí skript spustit a koukat, jak převodník při otáčení trimru měří napětí.

sudo python /home/pi/adc.py

(Ukončení běhu skriptu se provede klávesami Ctrl+C)

Když už jsem měl program vyzkoušený, upravil jsem ho tak, aby napětí a hodnotu A/D převodníku zobrazoval přímo na připojeném displeji.
Protože referenční napětí nebylo přesně 3,3V, upravil jsem v kódu hodnotu reference na skutečné napětí (3,32V)

Tady je úprava hlavní smyčky výše uvedeného programu pro zobrazení hodnoty na displeji:


while True:
        trim_pot0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
        napeti0 = round(3.32 * trim_pot0 / 4095 ,2)

        prikaz = "sudo python /home/pi/display 'Napeti = " + str(napeti0) + " V' 'Digit = " + str(trim_pot0) + "'"
        os.system (prikaz)
        time.sleep (0.5)

 

A tady je video (asi 6MB):
 
Odkaz na YouTube

 

 


Pokud vám stačí měřit pouze jeden napěťový kanál, popisuji v článku 57) A/D převodník MCP3021

 

 


úvodní strana webu AstroMiK.org

poslední úprava stránky 7.5.2015