Voltmetr řízený mikroprocesorem

Navržené zařízení bylo vyvinuto v rámci semestrální práce do předmětu Mikroprocesorová technika na VOŠ v Kutné Hoře.

Autoři: Tomáš Havlíček, Pavel Knytl, Jiří Rohan

Zadání semestrální práce:
Navrhněte voltmetr řízený jednočipovým mikropočítačem z rodiny Atmel AT89C.... Voltmetr bude měřit napětí v rozsahu 0 až 10V. Naměřený údaj s přesností 0,1 V vhodně zobrazujte na displeji. Řešte ochranu vstupů proti přepětí. Zařízení bude napájeno ze stejnosměrného nestabilizovaného zdroje napětí 24V. Navržené zařízení realizujte na desce plošných spojů.

Teoretický úvod
Jednočipové mikropočítače jsou často určeny pro aplikace, ve kterých se zpracovávají a generují analogové signály. Jsou proto přímo vybaveny analogově-číslicovými a číslicově-analogovými převodníky a nebo tyto převodníky jako samostatné součástky tvoří skupinu tzv. podpůrných obvodů mikropočítače. Tato práce demonstruje právě druhou zmíněnou možnost a to část převodníků analogově-číslicových (A/D).

Přeměnou analogového signálu na číslicový lze provést dvěma způsoby:
Způsoby kvantování analogovového signálu
Obr.1 Obr.2
Po A/D převodu tedy dostaneme číslicový signál, pro který platí, že hodnota signálu se mění po skocích, signál může nabývat pouze omezeného počtu předem stanovených hodnot. Počet těchto hodnot určuje použitou číselnou soustavu. V případě mikroprocesorové techniky je nejčastěji používanou číselnou soustavou soustava dvojková (binární), jež tedy může nabývat dvou stavů - log. 0 a log.1.

Ja bylo naznačeno výše, k převodu analog.signálu (napětí) na jemu odpovídající číslo vyjádřené v dané soustavě nám slouží A/D převodníky.
Podle toho, jakou hodnotu vstupního napětí převádějí na číslo, se A/D převodníky dělí na integrační a neintegrační. Integrační převodníky převádějí na číslo průměrnou hodnotu měřeného napětí za určitý časový interval. Neintegrační převodníky převádějí na číslo okamžitou hodnotu měřeného napětí v určitém okamžiku doby převodu. My jsme v naší práci zvolily neintegrační A/D převodník a to typ s postupnou aproximací. Obecně je jeho výhodou vysoká rychlost převodu, jež bývá kolem 10µs, nevýhodou je to, že není odolný proti sériovému rušení. Rozlišení může být až 0,0018%.

Princip funkce A/D převodníku s postupnou aproximací

Nejdůležitější částí námi navrženého měřidla je bezesporu A/D převodník pracující metodou postupné aproximace.

Vnitřní blokové schéma A/D převodníku s postupnou aproximací
Obr.3  Vnitřní blokové schéma A/D převodníku s postupnou aproximací
Ux - měřené napětí
UK - kompenzační napětí
NK - napěťový komparátor
PR - posuvný registr
MSB - (angl. Most Significant Bit) - nejvýznamnější bit
LSB - (angl. Least Significant Bit) - nejméně významný bit

Popis funkce:
Převod probíhá v n krocích. V prvním kroku je určena hodnota MSB - odpovídající signál je vyslán jako log.1 z posuvného registru (ostatní výstupy PR jsou v log.0). Pomocí D/A převodníku je převeden na napětí UK=UR/2 (kde UR je vstupní rozsah A/D převodníku) a porovnán pomocí napěťového komparátoru s Ux. je-li UKx, ponechá se MSB v log.1, v opačném případě se nastaví MSB do log.0. V dalším kroku je testován bit MSB-1 pomocí jemu odpovídajícho napětí UR/4, které se přičte k napětí na výstupu D/A převodníku z předchozího kroku. Výsledné napětí UK je opět srovnáno s Ux - je-li UK>Ux, je testovaný bit nastaven na log.0. Stejný postup se opakuje pro zbývající bity D/A převodníku. Počet kroků převodu n je tak roven počtu bitů převodníku.

A/D převodníky s postupnou aproximací se vyrábějí jako 8 až 16-bitové, s odpovídajícím rozlišením 0,4% až 0,0018%. Zopakujeme ještě jednou ostatní vlastnosti, a to velkou rychlost převodu, která bývá zhruba 10µs a schopnost dosáhnout 104 až 105 odběrů(měření) za sekundu. Vyžadují konstantní vstupní napětí během doby převodu, jinak může dojít ke značným chybám, a proto se na jejich vstup umisťuje vzorkovač s pamětí (Sample and Hold). Tyto převodníky jsou citlivé na rušivá napětí, nejsou odolné proti sériovému rušení.

A/D převodník ADC0804
Pro naše účely jsem si vybraly integrovaný A/D převodník ADC0804, vyráběný firmou National Semiconductor. Jedná se o 8-bitový aproximační převodník, jehož funkce vychází z výše uvedeného obecného principu. Maximální celková chyba je ±1 LSB, doba převodu je 100µs. Převodník má třístavové datové výstupy pro připojení na sběrnici, původně byl určen pro připojení k mikroprocesoru i8080 a jeho klonům. Má diferenciální napěťové vstupy, vstupní rozsah je 0 až 5V při napájení z 5V. Nevyžaduje nastavení nuly, všechny log.vstupy a výstupy jsou CMOS/TTL kompatibilní. Pro řízení převodu se používá vnitřní hodinový signál o frekvenci maximálně 1,5 MHz. Převodník nevyžaduje připojení vnějšího referenčního napětí (vnitřně 1/2 Vcc), je možné připojit i externí ref.zdroj (např. LM336). Převodník může pracovat i jako volněběžící, je schopen dosáhnout až 9700 měření/s. Převodník nemá vestavěn vzorkovací obvod typu "Sample and Hold”, takže pokud to daná aplikace vyžaduje, je nutné použít vnější vzorkovací obvod (např. LF398). Bližší popis funkce převodníku a časování signálů lze najít v tomto datasheetu na str. 18 až 24.

Pouzdro obvodu ADC0804

DB0 – DB7 ---------------- dig. výstup z převodníku
Vref/2 ------------------- referenční napětí
Vin +, Vin - ------------------- difer. napěťové vstupy
Clk in, Clk r ----------------- hodinové vstupy
INTR --------------------- přerušení do procesoru
GND ---------------------- zem
RD ----------------------- příkaz pro čtení
WR ----------------------- příkaz pro zápis
CS ----------------------- povolovací vstup
A GND ----------------------- analogová zem
D GND ----------------------- digitální zem

Zapojení obvodu na obrázku č.4 nám dobře posloužil k ověření funkce a vlastností převodníku (testovací obvod dle doporučení výrobce). Bylo třeba zjistit binární hodnotu odpovídající vstupnímu napětí, které se připojuje na piny 6 a 7 (A GND).Pin 6 je vstupní a pin 7 je spojen s analog.zemí(pin 8). Protože jsme měli za úkol sestrojit voltmetr měřící napětí 0 až 10 voltů, museli jsme na vstupu převodníku použít dělič, který je vidět na obrázku č.5. Převodník má v tomto zapojení vstupní rozsah napětí pouze 0 až 5V, z čehož plyne, že jsme použili dělič 1:2. Detailnější rozbor převodníku a způsob zjištění binární hodnoty, která odpovídá vstupnímu napětí, je vysvětlen v části popisující funkci programu.
Dále bylo nutné ošetřit vstup voltmetru před napětím vyšším než 10V. Nejdříve jsme chtěli použít omezovací obvod sestavený přesně pro naše účely, ale jeho cena by nebyla nejnižší a vzhledem ke snadnější realizaci ochrany vstupu pomocí Zenerovy diody jsme využili právě tuto možnost. Bylo potřeba zjistit předřadný odpor k Zenerově diodě, který jsme nejprve zvolili 300W. Po krátkém zkoušení se nám jako nejlepší hodnota předřadného odporu jevila hodnota 34W, která je nastavována pomocí trimru TR1 (viz schéma zapojení).
Trimr TR2 slouží k přesnému doladění vstupního děliče A/D převodníku. Mohli jsme sice použít pevný rezistor, ale z důvodu teplotní nestálosti součástek jsme pro dosažení přesného měření použili právě trimr (vst.rozsah tak lze před měřením zkalibrovat).
bvod pro ověření funkce převodníku
Obr.4  Obvod pro ověření funkce převodníku
Odporový dělič na vstupu převodníku

Obr.5  Odporový dělič na vstupu převodníku



POZN: Při návrhu voltmetru s A/D převodníkem je známo, že je nutné rozlišovat tzv. "analogovou" a "číslicovou zem". Během našeho zkoušení jsme došli k názoru, že vzájemné propojení těchto zemí není kritické a voltmetr fungoval i tak naprosto správně a přesně. Dále bylo nutné dodržet aplikační podmínky obvodu ADC0804 ohledně blokování napájecího napětí a minimalizace délky vodičů pro připojení měřeného napětí.


Připojení displeje

Displej HDSP 5621
Jde o 2-místný sedmisegmentový LED zobrazovač, barva znaků zelená, výška znaků 14 mm, společná anoda, úhel viditelnosti ± 50°, vynikající kontrast, dobrá viditelnost až do vzdálenosti 7m.
Displej HDSP 5621 Podrobné informace o HDSP 5621 najdete zde.
Informace o dalších typech sedmisegmentových displejů najdete zde.
Protože displej ovládáme staticky, displej si pro svoji potřebu zabral celé dva v/v porty mikroprocesoru (viz schéma zapojení). Pokud bychom si nemohli takový "přepych" dovolit, může se pro připojení použít nějaký dekoder BCD/7-segment (např. 74247) nebo použít dynamické řízení (přes spínací tranzistory),čímž se značná část vývodů portu ušetří.
Displej je připojen klasicky - na společnou anodu je připojeno napájení +5V, na jednotlivé segmenty jsou připojeny sériové odpory, jejichž hodnotu lze vypočítat z jednoduchého vzorce:
R = (Ucc - UD) / ID = (5 - 1,7) / 0,015 = 220 W
, kde proud diodou (jedním segmentem) ID uvažujeme 15 mA, což je optimální hodnota jak z hlediska dostatečné svítivosti, tak životnosti diody (segmentu).

Popis funkce programu

Program má za úkol zpracovat výstupy A/D převodníku a zobrazit na displeji hodnoty napětí, které této kombinaci odpovídají.

Hlavní část programu je vlastně velice jednoduchá. Obsahuje jen nastavení čítače, určení některých konstant apod. Veškeré výpočty a důležité úkony se provádějí v části obsluhy přerušení.


STOVKY          DATA    50H                     ; určení adres pro pomocné výpočty
DESITKY         DATA    51H
JEDNOTKY        DATA    52H
ZBYTEK          DATA    53H

                ORG     0H
                JMP     START

                ORG     0BH                     ;přerušení čítače/časovače 0
                LJMP    PRERUS
 
START:          ORG     20H                     ;vlastní program
                MOV     R0,#250D                ;nastavení počtu cyklů čítače
                MOV     DPTR,#100H              ;pomocná hodnota při výpočtech - displej
                MOV     TMOD,#00000010B         ;nastavení čítače – mód s předvolbou            
                MOV     TH0,#5D                 ;nastavení předvolby čítače (255 – 250 = 5 µs)
                MOV     TL0,#5D
                SETB    ET0                     ;povolení přerušení od čítače 0
                SETB    EA
                SETB    TR0

KONEC:          JMP     KONEC                   ; nekonečná smyčka. 
Při běhu nekonečné smyčky je každých 250 µs vyvoláno přerušení. Zpracuje se vstup od A/D převodníku a aktualizuje se údaj na displeji.

Přerušení
Je povoleno jedno přerušení – od čítače/časovače 0. Obsluhu přerušení řídí tyto řádky :

PRERUS:         DJNZ    R0,CYKLUS
                MOV     R0,#250D
				.
				.
CYKLUS:         RETI
V registru R0 je konstanta, která určuje, jak často se má měnit údaj na displeji. V našem případě je to hodnota 250. Při každém volání se R0 zmenší o jednčku. Pokud je R0 rovno 0, doplní se na výchozí hodnotu a zpracuje se tělo přerušení. Jelikož se přerušení volá každých 250 µs a v registr R0 je hodnota 250, jsou příkazy v přerušení zpracovávány každých 250 * 250 = 62500 µs = 62,5 ms. Vždy po této době se zpracuje vstup a na výstup displeje se přivede aktualizovaný údaj hodnoty napětí.

Vlastní zpracování vstupů

Převodník je 8-bitový. Jeho výstupem je tedy číslo 0 až 255. Protože pracujeme v rozsahu 0 až 10V, je číslo 255 poněkud nevhodné - číslo 10 děleno 255 dá číslo 0,039215. Toto číslo odpovídá diferenci D – rozdílu jednotlivých stavů výstupu. V osmibitové matematice se s tímto číslem nedá moc dobře počítat.

Pokud ale zmenšíme rozsah na 0 – 250, diference D bude jenom 0,04. Tím se naše počty velice zjednoduší. Vlastní algoritmus je velice jednoduchý. Řekněme, že dekadickou hodnotu výstupu A/D převodníku budeme značit D (D jako Dekadická hodnota výstupu). V tom případě napětí ve voltech získáme ze vzorce U = D* D* 100 [V] Pro lepší zřetelnost je celá závislost zakreslena na grafu :



V praxi je to řešeno následovně : data jsou přiváděna z A/D převodníku na bránu P1. Nejdřív se otestuje, jestli hodnota přesahuje 250. Ve vyšších jazycích, jako napři. Pascal nebo C by to šlo napsat třeba „If X > 250 then “ , ale v assembleru porovnávání velikostí není. Můžeme jen využít příkaz CJNE, který otestuje, jestli se daná čísla rovnají. Pokud ne, skočí na zadané návěští:

POZN. (Michal Fuksa): Tady si asi pozorný čtenář všimnul, co je ve výše uvedených řádcích uvedeno za chybu - instrukce CJNE přece umožňuje plnohodnotné porovnávání dvou proměnných. Tady to autoři programu trochu ustřelili (zřejmě hodně spěchali, takže si správné použití CJNE na tomto místě programu neuvědomili), jak je ale vidět dále, kompletní funkce instrukce CJNE jim byla známa.

                MOV     A,P1                                                      
                CJNE    A,#11111010B,PRVNI      ; Otestuje, jestli  A =250
                LJMP    DESET
PRVNI:          CJNE    A,#11111011B,DRUHY      ; Otestuje, jestli  A =251
                LJMP    DESET
DRUHY:          CJNE    A,#11111100B,TRETI      ; Otestuje, jestli  A =252
                LJMP    DESET
TRETI:          CJNE    A,#11111101B,CTVRTY     ; Otestuje, jestli  A =253
                LJMP    EE
CTVRTY:         CJNE    A,#11111110B,PATY       ; Otestuje, jestli  A =254
                LJMP    EE
PATY:           CJNE    A,#11111111B,NENI_DESET ; Otestuje, jestli  A =255
                                                ; když ne,skok na NENI_DESET, kde
                                                ; pokračují další výpočty a vlastně
                                                ; ta nejdůležitější část programu 
EE:             MOV     P0,#10001100B
                MOV     P2,#00001100B     
CYKLUS1:        LJMP    CYKLUS                  ;skok na konec cyklu
DESET:          MOV     P0,#11110011B
                MOV     P2,#01000000B
                LJMP    CYKLUS                  ;skok na konec cyklu
Návěští CYKLUS1 je vlastně meziskok. Některé příkazy, jako CJNE nebo DJNZ, mohou provést skok maximálně o 128 bytů. V našem případě to nestačí a tak je řádek

CYKLUS1:        LJMP    CYKLUS
jen jakýsi odrazový můstek, který tyto příkazy využívají, aby se dostali na konec programu.

Problém je osmibitová matematika. Vzorec ve formě U = D* D* 100 [V] této formě se nemůže použít. Pokud ale rozdělíme číslo D na stovky, desítky a jednotky, můžeme využít jiný přístup. Nejprve rozdělíme číslo do tří proměnných : STOVKY, DESITKY, JEDNOTKY. Pak každou proměnnou vynásobíme 4. Ve dvouciferném výsledku pak použijeme hodnotu v proměnné STOVKY jako počet desítek, DESITKY jako počet jednotek a jednotky použijeme jako zaokrouhlovací pomocnou proměnnou, aby hodnota výsledku odpovídala. Použijeme definici rozkladu čísel :

Když číslo dělíme číslem 100, získáme počet stovek a zbytek je roven počtu desítek. Dělíme-li počet desítek 10, získáme počet desítek a zbytek je roven počtu jednotek. V praxi to vypadá pro některá náhodně vybraná čísla takto :

V assembleru se dá tento algoritmus zapsat třeba takto: (Návěští se jmenuje NENÍ_DESET, protože před skokem na toto místo došlo k otestování, jestli na vstupu není 10 či více voltů.)

NENI_DESET:     MOV     B,#100D                 ;rozdělení čísla na stovky, desítky a jednotky                                              
                DIV     AB
                MOV     STOVKY,A                ; Stovky
                MOV     A,#10D
                XCH     A,B
                DIV     AB
                MOV     DESITKY,A               ; Desítky
                MOV     JEDNOTKY,B              ; Jednotky
A teprve nyní všechny tři proměnné vynásobíme 4 :

                MOV     A,STOVKY
                MOV     B,#4D
                MUL     AB
                MOV     STOVKY,A                ; STOVKY = STOVKY * 4
                MOV     A,DESITKY
                MOV     B,#4D
                MUL     AB
                MOV     DESITKY,A               ; DESITKY = DESITKY * 4
                MOV     A,JEDNOTKY
                MOV     B,#4D
                MUL     AB
                MOV     JEDNOTKY,A              ; JEDNOTKY = JEDNOTKY * 4
Následuje zaokrouhlení a upřesnění hodnoty výsledku. Obvykle se zaokrouhluje nahoru, když je číslo větší než 5 a dolů, pokud je menší. My místo čísla 5 používáme číslo 7. Je to kompenzace nepřesnosti vstupu. Vstup voltmetru je napěťový dělič z odporů. Bohužel odpory a potenciometry se nedají nastavit s nekonečnou přesností. Ne každý se dá nastavit zcela přesně, je to dáno jak technologií, tak ladícími prvky (šroubovací závity a podobně). Proto v praxi, i když s tím počítáme, není diference D = 4, ale v praxi se o několik setin či tisícin liší. U malých čísel to nevadí, ale odchylka postupně narůstá. Proto jsme zvolili mez zaokrouhlování na hodnotě ne rovné polovině 10, ale spíše jedné třetině, tedy 7.

                MOV     B,#10D
                DIV     AB                                         
                MOV     ZBYTEK,A                ;v A jsou (JEDNOTKY * 4 ) /10
                MOV     A,B                     ;v B je zbytek po dělení 10
                CJNE    A,#7D,MENSI_NEZ_7       ;skok při nerovnosti, mění příznak přenosu  
                                                ;C=1 if A < 7, jinak C=0
                LJMP     VETSI_NEZ_7
A nyní jak a kam se bude zaokrouhlovat podle výsledku :

MENSI_NEZ_7:    JNC     VETSI_NEZ_7             ;druhé otestování 
                MOV     A,DESITKY
                MOV     B,ZBYTEK
                ADD     A,B                     ;součet desítek a zbytku po operací s jednotkami        
                MOV     B,#10D 
                DIV     AB                      ;vydělíme deseti – počet desítek v součtu (v reg. A)
                MOV     JEDNOTKY,B              ;druhé číslo výsledku (zbytek dělení) - výstup
                MOV     B,STOVKY
                ADD     A,B                     ;přičte se výsledek předchozího výpočtu
                MOV     DESITKY,A               ;první číslo výsledku po zaokrouhlení - výstup
                LJMP    VYSTUP                  ;výsledek na displej
VETSI_NEZ_7:    MOV     B,ZBYTEK                ;zde je zbytek větší nebo roven 7
                MOV     A,#1D
                ADD     A,B
                MOV     ZBYTEK,A                ;zbytek = zbytek + 1 
                MOV     A,DESITKY
                MOV     B,ZBYTEK
                ADD     A,B                     ;součet desítek a zbytku
                MOV     B,#10D
                DIV     AB                      ;A = počet desítek v součtu
                MOV     JEDNOTKY,B              ;druhé číslo výsledku
                MOV     B,STOVKY
                ADD     A,B                     ; + počet stovek
                MOV     DESITKY,A               ;první číslo výsledku
V proměnných DESITKY a JEDNOTKY jsou uloženy čísla, která se dostanou na displej ve tvaru : Rámečky samozřejmě znamenají jednomístný LED displej a ukazují číslo od 0 do 9.

Zobrazování na displeji

Hardwarová část připojení displeje byla popsána výše. Zbývá ještě probrat softwarovou část. Zobrazování je řešeno staticky. Proto stačí jen přivést na příslušnou bránu patřičnou kombinaci 0 a 1 (tj. segmenty, které budou svítit a které ne). To řeší následující část (umístěno v obsluze přerušení – viz dále) :

                MOV     A,DESITKY
                MOVC    A,@A+DPTR       
                MOV     P0,A
                MOV     A,JEDNOTKY
                MOVC    A,@A+DPTR       
                MOV     P2,A
V proměnných DESITKY a JEDNOTKY jsou hodnoty v intervalu 0 – 9. Obsah proměnných se postupně dostane do registru A. Následuje řádek

                MOVC    A,@A+DPTR
který do registru A dosadí hodnotu na A + DPTR. V registru DPTR je hodnota 100h, proto se do registru A dosadí hodnota A + 100h, která odpovídá kombinaci pro rozsvícení jednotlivých segmentů displeje. Pokud je tedy v A hodnota 0, do A se dosadí hodnota z adresy 100h, která odpovídá číslu 0 atd.
číslo ABCDEFGH
0 0 0 0 0 0 0 1 1
1 1 1 0 0 1 1 1 1
2 0 0 1 0 0 1 0 1
3 1 0 0 0 0 1 0 1
4 1 1 0 0 1 0 0 1
5 1 0 0 1 0 0 0 1
6 0 0 0 1 0 0 0 1
7 1 1 0 0 0 1 1 1
8 0 0 0 0 0 0 0 1
9 1 0 0 0 0 0 0 1
Označení segmentů

Na konci celého programu jsou do paměti dat umístěny konstanty - kombinace svítících/nesvítících segmentů displeje (první konstanta je pro 0, poslední pro 9). Je jedno, jestli jsou tyto konstanty uvedeny na konci, na začátku nebo uprostřed programu, ale nakonec jsme se rozhodli umístit je na konec. Vyplynulo to při programování – umístili jsme je tam při programování první verze a pak už nebyl důvod to měnit.

                ORG     100H
                DB      01000000B,01110011B,00100100B,00100001B,00010011B
                DB      00001001B,00001000B,01100011B,00000000B,00000001B
                END


Schéma zapojení
kliknutím na obrázek získáte schéma zapojení v plné velikosti
Náhled schámatu zapojení

Soupiska použitých součástek pro desku plošných spojů:
(značení součástek dle katalogu GM Electronic)

Položka

Množství

Referenční označení

Typ

1

1

IO1 ADC0804CN

2

1

IO2 AT89C51

3

1

ST1 7805

4

1

ZD1 BZX 85V010 (Zenerka 10V/1,3W)

5

1

Displej HDSP - 5621

6

1

X1 krystal 12 MHz

7

3

R1,R2,R3 10k

8

1

R4 8k2

9

15

R5 až R19 220R

10

1

TR1 trimr 250R (PT10VE250)

11

1

TR2 trimr 25k (PT10VK025)

12

1

C5 10uF/25V

13

1

C1 150pF

14

3

C2,C6,C7 100nF

15

1

C8 470uF/50V

16

2

C3,C4 33pF

17

2

Vstup 0 až 10V, Ucc 24V svorkovnice ARK 550/2

Další použité komponenty:
1 x patice SOKL20 (20-pin DIP)
1 x patice SOKL40 (40-pin DIP)
1 x patice SIL 10 PZ (jednořadá - pro displej)

Zhodnocení, přednosti a nedostatky:


Program ASM  Výpis programu pro mikrokontroler AT89C51

Zpět na hlavní stránku