Categories
AVR-ek programozása

Az AVR-ek analóg bemenetei

Az előző cikkben megnéztük miként lehet az IO-Portokat kezelni. Ahogy az elején ígértem, így már elég sok mindenre képesek lehetünk a kontrollerünkkel. Bemeneteket olvashatunk, kimeneteket írhatunk, szóval ezekkel a műveletekkel már meg tudunk oldani egyszerű problémákat. Előfordulhat azonban, hogy nekünk nem elég az, hogy képesek vagyunk megállapítani, hogy egy bemeneten van – e feszültség, vagy sem. Adódik néha alkalom, amikor azt is szeretnénk tudni, hogy azon a lábon éppen mekkora feszültség van jelen. Nos, a jó hír az, hogy erre találták ki az ADC-t vagyis az Analog Digital Converter-t ami az analóg feszültségszinteket digitális jellé alakítja.

Ez a gyakorlatban annyit tesz, hogy egy adott feszültségértékhez egy digitális érték tartozik, amit a kontroller már értelmezni képes. Fontos tulajdosága az ADC-eknek a felbontása, és a referenciafeszültség értéke.
Például egy 8 bites ADC a 0 -255 tartományban, míg egy 10 bit-es ADC a 0- 1023 tartományban képes megadni hogy mekkora jelszint mérhető éppen a bemeneten. Jó, jó.. tegyük fel, hogy az ADC-n végzett mérésünk a 127 értéket adta vissza. Mit tudunk mi ezzel kezdeni? Itt jön képbe a referenciafeszültség ami megadja, hogy a maximum érték (8 bit esetén például a 255) hány Volt feszültséget jelent.

Van lehetőség természetesen ennek a fordítottjára is, azaz hogy megadunk egy digitális értéket, hogy az annak megfelelő feszültségértéket adjuk ki a kontroller lábán. Sajnos az a helyzet, hogy az ATmega, és ATtiny sorozat egyik típusa sem tartalmaz beépített Digital-Analog átalakítót (DAC). Ez a funkció elsőként az XMEGA sorozatban lett elérhető, de a két széria között lévő különbségek miatt ezt ebben a jegyzetben nem tárgyaljuk. Az Analóg jellé alakítás történthet azonban PWM-el, és annak gyors DC szűrésével, vagy egy úgynevezett R2R hálózattal. Ettől függetlenül természetesen van lehetőség speciális építőelemeket is A/D, és D/A átalakításra használni, és ezeket egy digitális interfészen ( SPI vagy I2C ) keresztül egy AVR-el vezérelni.

Egy AVR mikrokontroller nem csak analóg jelszinteket mérni, hanem azokat összehasonlítani is képes. Ezt az áramkört Analog Comparator-nak nevezzük. Nézzük hát, hogy mi is ez.

 

AC (Analog Comparator)

A komparátor összehasonlítja az AIN0 és AIN1 lábokon lévő feszültségértékeket, és megállapítja melyik a nagyobb a kettő közül. AIN0 a referencia feszültség, és AIN1 az összehasonlítandó feszültség. Referencia feszültségként lehet alternatív, belső referenciafeszültséget is választani.

Ha a vizsgált feszültség a referenciafeszültség alatt van, a komparátor logikai 1 értéket, míg ha a vizsgált feszültség a referencia feszültség felett van 0-át ad ki.

A komparátor teljesen önállóan, vagy a processzorral párhuzamosan dolgozik. Hordozható alkalmazásnál ajánlott kikapcsolni, mert különben felesleges fogyasztóvá válik. A komparátor lehet interrupt (megszakítás) vezérelt, vagy lekérdezés üzemű.

A vezérlő, vagy státusz regiszter a következő felépítésű:

Bit 7 ACD
Analog Comparator Disable: 0 = komparátor be, 1 = komparátor ki. Ha ez a bit megváltozik, megszakítás léphet fel. Ennek megakadályozása érdekében a Bit3 ACIE-t – ha van ilyen – ki kell kapcsolni.

Bit 6 ACBG
Analog Comparator Bandgap Select: Lehetővé teszi a belső és külső referenciafeszültség közötti átkapcsolást. 1 = belső (~1,3 V), 0 = külső ( az AIN0 lábon lévő ) referenciafeszültség.

Bit 5 ACO
Analog Comparator Output: Itt látható az összehasonlítás ereménye. Típusonként változó, de általában 1 – 2 órajel alatt meg van az eredmény.

Vvizsgált < Vreferencia → 1
Vvizsgált > Vreferencia → 0

Bit 4 ACI
Analog Comparator Interrupt Flag: Ennek a bitnek a hardware ad értéket, ha egy megszakítás esemény – ami a nulladik bitben, és az első bitben definiált – fellép. Ez a bit nem vált ki megszakítást! Az interrupt rutin csak azután fut le, ha a Bit 3 ( ACIE ) 1 értéket kap, és a globális megszakítások engedélyezve vannak ( I-Bit az SREG regiszterben = 1 ). A Bit 4 ( ACI ) értéke újra törlődik, ( 0 lesz ), ha az interrupt rutin lefut, vagy manuálisan 1 –re nem állítjuk. Bit lekérdezésekhez használható, de nem vezérli, vagy konfigurálja a komparátort.

Bit 3 ACIE
Analog Comparator Interrupt Enable: Ha a bit értéke 1, minden esetben fellép egy megszakítás, ha a Bit 1-ben és Bit 0-ban definiált esemény fellép.

Bit 2 ACIC
Analog Comparator Input Capture Enable: Ha a bit értéket kap ( 1 ), a komparátor kimenet összeköttetésbe kerül a Counter 1-el. Ezzel például az összehasonlítások számát számlálhatjuk meg a Counter 1 számláló segítségével. A komparátort, a Timer 1 –el való összeköttetéshez a Timer regiszter TICIE1 bitjének kell (1) értéket adni. A trigger mindig akkor aktiválódik, amikor a Bit 1-ben, és Bit 0-ban definiált esemény fellép.

Bit 1, Bit 0 ACIS1, ACIS0
Analog Comparator Interrupt Select: Itt definiálható, hogy melyik esemény váltson ki megszakítást:

00 = megszakítás minden él váltáskor 10 = megszakítás lefutó él esetén 11 = megszakítás felfutó él esetén

Ha ezek a bitek módosulnak, megszakítást eredményezhet. Ennek megelőzéséhez a Bit 3 értékét törölni (0) kell.

ADC (Analog Digital Converter)

Az Analóg – Digitális Átalakító (ADC) az analóg jeleket digitális értékekké alakítja, amiket a kontroller már értelmezni képes. Egyes AVR típusokban többcsatornás ADC van beépítve. A pontosság – amivel egy analóg jel felbontható – az ADC felbontásától függ. Ez lehet 8 és 10 bites. Jelenleg az AVR- ekben a 10 bites felbontású ADC a legnagyobb.

Egy 8 Bites felbontású ADC a maximum érték 1/256-odának pontosságára képes. Minél nagyobb az ADC felbontása, annál pontosabban írja le a digitális érték az analóg feszültség szintet.

Az AVR-ben lévő belső ADC
Ha a feladat egy kicsit nagyobb pontosságot kíván meg, szükségünk van egy AVR-re, ami rendelkezik belső ADC-vel, ami több csatornával rendelkezik. A csatornák ebben az értelemben analóg bemenetek, de csak egyetlen ADC áll rendelkezésre, ami ezeket a bemeneteket kezeli. A tényleges mérést tehát megelőzi annak meghatározása, hogy melyik mérni kívánt csatorna (bemeneti láb) legyen az átalakítóval összeköttetésben.

Az AVR AGND és AVCC lábai csatlakoztatva kell legyenek. Pontos mérésekhez az AVCC egy L-C hálózaton keresztül kell a VCC- hez kapcsolódnia, a feszültségcsúcsok – és letörések kiszűrése érdekében. Az adatlapon erről található egy kapcsolás, ami 10uH-t, és 100nF-ot ír elő.

Az analóg – digitális átalakítás a referencia feszültségen alapul. Jelenleg az AVR-ek három lehetőséget nyújtanak ennek a feszültségnek a megválasztására:

Külső referenciafeszültség a maximális VCC-től az AREF lábra. A legkissebb (külső) referencia feszültség nem lehet bármilyen alacsony, ennek értékét az alkalmazott kontroller adatlapjából tudjuk meg
Belső referencia feszültség. Minden jelenlegi AVR, aminek van belső AD átalakítója, rendelkezik ilyennel. Az adatlap határozza meg ennek az értékét, valamint az érték pontosságát.
Az AVCC-re kapcsolt feszültség használható referenciafeszültségként.

Az AVCC, vagy a belső referencia feszültség használatakor ajánlott az AREF láb, és a GND közé egy kondenzátort kapcsolni. A használni kívánt referencia feszültség megválasztása az ATmega16 esetében például az ADMUX regiszterben található REFS1/REFS0 bitekkel történik. A mérendő feszültség az AGND, és az AREF közötti feszültség tartományban (mindegy, hogy külső, vagy belső) kell legyen.

Az ADC két különböző üzemben alkalmazható:

Egyszerű átalakítás (Single Conversion)
Ebben az üzemben a program kezdeményezésére indul a mérés

Szabadon futó (Free Running)
Ebben az üzemi módban az átalakító folyamatosan kiértékeli a rajta lévő feszültséget, és az eredményt az ADC Data Regiszter-ben tárolja.

Az ADC regiszterei

Az ADC saját regiszterrekel rendelkezik. Az alábbiakban egy ATmega16 Regisztereinek leírását láthatjuk, ami 8 ADC csatornával rendelkezik, a regiszterek mégsem térnek el jelentősen a többi AVR- től. (lásd: adatlap)

ADEN (ADC Enable)
Ennek a bitnek éréke kell legyen ahhoz, hogy aktiváljuk az ADC-t. Ha a bit értéke törölve van, a lábak I/O lábakként használhatóak.

ADSC (ADC Start Conversion)
Ezzel a bittel indul a mérési folyamat. Szabadon futó üzemben a bit értéke 1 kell legyen, a folytatólagos mérés aktiválásához. Ha a bitnek, az ADEN (1) értékadása után először adunk (1) értéket, először egy kiegészítő, és csak aztán a tényleges átalakítás megy végbe. A kiegészítő átalakítás inicializálási célból történik. A bit értéke csak addig marad 1, amíg az átalakítás végbe nem megy, míg inicializáláskor addig, amíg a második átalakítás nem történik meg, és ezt követően értéke ismét 0 lesz.

ADFR (ADC Free Run select)
Ezzel a bittel választjuk ki az üzemi módot. Ha a bit értéke 1, akkor az ADC “Free Running” módban üzemel, így az adatregiszter folyamatosan frissül. Ha a bit értéke 0, akkor csak egyetlen átalakítást hajt végre az ADC.

 

ADIF (ADC Interrupt Flag)
Ennek a bitnek az ADC akkor ad értéket, amikor egy átalakítás lefutott, és az ADC Data Register frissült. Az ADC(L,H) regiszter olvasó hozzáférésekor a bit értéke automatikusan törlődik (0).
Ha az ADIE bitnek valamint az I-bitnek az AVR Status regiszterében az értéke 1, az ADC Interrupt aktiválódik, és az interrupt kezelő rutin meghívódik
A bit értéke automatikusan 0 lesz, ha az interrupt kezelő rutin meghívódik.

ADIE (ADC Interrupt Enable)
Ha ez a bit, valamint az SREG Status Regiszterben található I-bit értéke 1, aktiválódik az ADC – Interrupt.

ADPS2 .. ADPS0 (ADC Prescaler Select Bits)
Ezek a bitek határozák meg az órajel, és az ADC bemeneti clock osztótényezőjét.
Az ADC-nek szüksége van egy saját órajelre, amit saját magának állít elő a CPU órajeléből. Az ADC órajele 50, és 200 kHz között kell legyen.
Az előosztót tehát úgy kell beállítani, hogy CPU órajel osztva az osztótényezővel értéke 50 – 200 kHz közötti tartományban legyen.
Például egy 4 MHz-es CPU órajelnél így számolunk:

Így az osztó tényező ebben az esetben 32, vagy 64 lehet. A gyorsabb átalakítási idő érdekében itt most a 32-őt állítjuk be tényezőként.

ADCL, ADCH (ADC Data Register)

Ha egy átalakítás lefutott, ebben a két regiszterben található a mérés eredménye. Az ADCH-ban csak a két alacsonyabb értékű bit van kihasználva, Mindig a két regisztert együtt kell kiolvasni, méghozzá
a következő sorrendben: ADCL, ADCH.

x = ADCL; //uint16_t 
x += (ADCH << 8);

vagy

x = ADCW // AVR-enként akár x = ADC is lehet ( lásd avr/ioxxx.h)

ADMUX (ADC Multiplexer Select Register) bitjei

Ezzel a regiszterrel lehet kiválasztani a mérendő csatornát. A 90S8535-nél a PORTA minden lába használható az ADC bemeneteként. (ez 8 csatorna)
A regiszter felépítése a következő:

REFS1 .. REFS0 (ReferenceSelection Bits)
Ezekkel a bitekkel lehet beállítani a referencia feszültséget. Az átállításnál a várakozási időre figyelni kell, amíg az ADC bevetés kész nem lesz. (adatlap)

ADLAR (ADC Left Adjust Result)
Az ADLAR bit megváltoztatja az A/D átalakítás eredményének kinézetét. Egy logika 1 értéknél balra igazítva lesz kiadva az eredmény, míg 0-nál jobbra igazítva. Ennek a bitnek a módosítása azonnal befolyásolja az eredményt, attól függetlenül, hogy egy átalakítás éppen fut -e, vagy sem.

MUX4 .. MUX0

Ezzel az öt bittel lehet a mérendő csatornát meghatározni. Ha egy egyszerű egy csatornás ADC-t használunk, egyszerűen a lábnak a számát a 0..2 bitbe kell írni.
Ha a regiszter egy átalakítás közben írva lett, az éppen futó átalakítás az eddigi csatornán fejeződik be. Ez mindenek előtt szabadon futó üzemmódban megfontolandó.

Ajánlott a szabadon futó üzemmódot csak egyetlen analóg bemenet használatakor használni, hogy elkerüljük az átkapcsolgatások okozta problémákat.

 

 

Az ADC használata

Az ADC aktiválásához az ADCSR regiszterben található ADEN bitnek értéket kell adni. Ugyanabban a lépésben adjuk meg az ADC üzemmódját.

Az alábbi kód egy példa a ”single conversion” módra, és a belső referenciafeszültség használatára egy ATmega169 –el. ( ennél a típusnál a belső referencia 1,1 V, de más AVR-eknél ez 2,56 V is lehet. A bemeneti jelnek ezt a feszültséget nem szabad túllépnie. Adott esetben ezt egy feszültségosztóval kell megoldani. A rutin eredménye az ADC értéke: 0 a 0V, és 1023 a referencia feszültség.

A gyakorlati alkalmazásokban a program induláskor először konfigurálják az ADC-t, azután különböző csatornákon mérnek. Ezt a két dolgot legtöbbször el kell választani egymástól, ugyan is az ADC bekapcsolása, és a referencia feszültség kiválasztása több mikroszekundumba telik, ezenkívül az első eredmény érvénytelen, és el kell vetni.

// ADC inicializálása 
void ADC_Init()
{
    uint16_t result;
    ADMUX = (1 << REFS1) | (1 << REFS0); // Belső referenciafeszültség használata 
    ADCSRA = (1 << ADPS1) | (1 << ADPS0); //frekvencia előosztó
    ADCSRA = |= (1 << ADEN) // ADC bekapcsolása.

    /* Az ADC bekapcsolása után ajánlott egy kiolvasás, amit aztán elvetünk. 
    Ez az ADC ”Bemelegítéséhez” szükséges. */

    ADCSRA |= (1 << ADSC); // egy ADC átalakítás

    while(ADCSRA & (1 << ADSC)) // vár az átalakátás befejeztére
    {
    }

    /* Az ADCW regisztert egyszer ki kell olvasni különben a következő
    átalakítás eredménye nem lesz érvényes*/

    result = ADCW;
}

 

/* ADC egyszerűmérés */

uint16_t ADC_Read(uint8_t channel) 
{

    //csatorna választása más bitek befolyásolása nélkül. 
    ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);


    // átalakítás indítása
    ADCSRA |= (1 << ADSC); 

    while (ADCSRA & (1 << ADSC)) // konverzió végére vár

    {
    }

    return ADCW;
}

 

/* többszöri mérés átlagérték képzéssel */

uint16_t ADC_Read_Avg(uint8_t channel, uint8_t average) 
{

    for (uint8_t i = 0; i < average; i++) 
    result += ADC_Read(channel); 
    return (uint16_t)(result / average); 
} 

// Példa függvényhívások 
int main()
{
    uint16_t adcval; 
    ADC_Init(); 
    while(1)
    {
        adcval = ADC_Read(0); // 0. Csatorna
        // csinálsz valamit az adcval változóval.

        adcval = ADC_Read_Avg(2, 4); // 2. Csatorna középérték 4 mérésből
        // csinálsz valamit az adcval változóval.
    }
}

A példában az ADC folyamatosan fut. Ha takarékoskodni akarunk az árammal, például az alvó módok alkalmazásával, az ADC-t minden mérés után ki kell kapcsolni, és a következő mérés előtt be kell kapcsolni, ami persze több idő, és a kezdő átalakítás is szükséges.

 

AD átalakítás belső ADC nélkül ellenállásméréssel:

ADC nélkül, indirekt módon is meghatározhatunk analóg értékeket. Az elkövetkezőkben egy potenciométer beállított értékének mérési módjára kapunk magyaráztatot, ami egy kondenzátor terhelési görbéjén alapul. Ennél a módszernél nincs szükségünk ADC-re vagy vagy analóg komparátorra, csupán egy port lábra. Ehhez egy kapacitás és egy ellenállás sorba van kötve, és a tápfeszültség, valamint a test közé van kapcsolva (úgynevezett R- C hálózat ). A port lába össze van kötve a kondenzátor, és a potméter csomópontjával. A következő levezetésben értelmezzük a kapcsolást.

A port lába kimenetként konfigurált ( a példában
DDRD |= (1 << PD2); ), és ez a kimenet logikai 1
szintre van állítva
( PORTD |= (1 << PD2); ), így a kondenzátor
mindkét lába azonos potenciálon van, tehát a
kondenzátor ezáltal kisütött állapotú. ( Elsőre hülyén
hangozhat, hogy a tápfeszültséggel kisütjük, de ez így van, mivel a kondenzátor mindkét oldala azonos potenciálon van, így a kondenzátor fegyverzetei között lévő potenciálkülönbség 0 V -> a kondenzátor kisült)

Egy bizonyos időn belül a kapacitás kisül, és nagy ellenállású lesz. A port lábat bemenetként konfiguráljuk. ( DDRD &= ~(1 << PD2); PORTD &= ~(1 << PD2); ). A bemeneti láb állapota logikai 1. A kondenzátor a potméteren keresztül feltöltődik, így nő a feszültségesés a kondenzátoron, és a potméteren csökken. Ha a potméteren lévő feszültségesés a bemeneti láb küszöbértéke alá esik (2/5 VCC tehát körülbelül 2V), a bemeneti jel alacsony szintnek fog minősülni. A kisütésről töltésre átkapcsolás időtartama, és a bemeneti jel magas szintről alacsony logikai szintre való váltása a potenciométer beállított ellenállás értékétől függ. Ezen idő mérésére a kontroller egy meglévő időzítőjét használhatjuk. A 220 Ω –os ellenállás a bemenet védelmére szolgál.

 

AD átalakítás belső ADC nélkül komparátor használatával

Feszültség mérésére van még egy módszer, méghozzá az analóg komparátor (AC) használatával, ami szinte minden AVR-ben adott.

A mérendő jel a komparátor invertáló bemenetére kerül. Ezenkívül a komparátor nem invertáló bemenetére egy referencia jel kerül. A referencia jel itt is egy R-C tag lesz, ezúttal állandó kapacitás és ellenállás értékkel.

A mérés elve az előbbihez hasonló. A 2-es láb alacsony logikai szintre állítása miatt a kondenzátor először kisül. Itt is figyelni kell arra, hogy a kisülési folyamat elegendően hosszú ideig tartson. Ezután a 2-es lábat magas logikai szintre állítjuk, a kondenzátor töltődik. Ha a kondenzátoron levő feszültség eléri a bemeneti lábon lévő feszültésghatárt a komparátor átvált. Az idő ami a kondenzátor töltéséhez szükséges, ugyan csak az 1-es lábon lévő feszültségre enged következtetni.

Nos, a témánk végére értünk, legközeleb megnézzük hogyan állíthatunk elő analóg jeleket.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.