Učím se s AD převodníkem

Ahoj, potřeboval bych pár rad ohledně AVR ADC. S AVR jsem začátečník, a navíc s ADC jsem nikdyyy nic nedělal.
Pro začátek jsem si zvolil řekl bych ne zas tak moc obtížnou věc, a to zkusit vyrobit voltmetr s ATmega8, zobrazení na 4 místném 7seg LED displeji (4místný multiplex mám již zapojený, tak proč ho nepoužít, přinejhoršim se bude zobrazovat na míň míst).

JIž jsem pročítal datasheet, a něco jsem i pochopil. Napíšu vám, jak bych si to asi představoval, že to s tím ADC je, kdyžtak mě vyveďte z mých mylných dojmů:

Nejprve je potřeba ADC z inicializovat.
Použijeme vstup ADC0 MUX3:0=0000
rozsah 0…2.56V, zvolíme vnitřní referenci REFS1:0=11
“zarovnání” výsledku vpravo ADLAR=0
tedy registr ADMUX=0b11000000
Zajímalo by mě jakou kapacitu asi tak může mít ten kondenzátor venku na VREF, cca 100nF?? 1uF???

Nastavení ADC - registr ADCSRA:
Zapneme ADC (ADEN=1)
ADSC=0 (nic zatím nekonvertovat)
ADFR=0 (jen po jednom vzorku)
ADIF=0 - nejsem si jist, popis v datasheetu je nějaký pofidérní popis k tomuto bitu…??
Pochopil jsem, že bit je nastaven, je-li dokončena konverze. Pokud je ADIE=1, I=1, tak vznikne přerušení, a HW vynuluje tento bit po vzniku přerušení. A tedka to, co se mi nějak nezdá a nechápu:
Alternativně ADIF je vynulován zapsáním logické 1 do něj, (WTF?) atd, atd… zbytek odstavce jsem nepochopil (na straně 207 v datasheetu) - vysvětlíte mi to někdo, co s tím ADIF?
ADIE=0 přerušení nechci
Používám Xtal 4MHz, hodiny zvolím bezpečně 125kHz, tedy dělička 32:
ADPS2:0=101
tedy ADCSRA=0b10000101

pak už jen stačí dát bit ADSC do log.1, potom počkat až se zpět vrátí do nuly, a vyčíst výsledek: nejprve číst registr ADCL, potom ADCH.

Ovšem vůůůbec mi není jasné, kde a čím nastavím rozlišení AD převodníku, když chci třeba jen 8 bitový.

Zapomněl jsem ještě na něco, nebo je to takle správně (já si myslím že mi tam něco ale chybí, ale nevim co) :slight_smile:
MOC DIKY VSEM, KDO POMOHOU
Honza

Tady je už hotovej voltmetr i se zdrojákem tuxgraphics.org/electronics/200706/mini-digital-voltmeter.shtml

Je to v céčku…

Nebo se mrkni sem: avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48009&postdays=0&postorder=asc

Díky, ale tohle mě moc nezajmá :slight_smile:
Jediný co můžu je podívat se tak akorát jak to maji udělaný… ale taky se z toho dá něco vyčíst… Navíc z toho mojeho nebude voltmetr, ale půjde to do “digitálního” labozdroje, který stavím, a snad dostavím…, bude to měřit i daleko jinačí věci, ale pro jednoduchost jsem napsal voltmetr… :slight_smile:
Zároveň jsem naschvál nepsal že chci kody, a v asm, protože potřebuju vědět kde co nastavit, co kde zapsat do kterýho registru atd… to je to, co mě zajmá… Jinak kody Cčkový přelouskám taky, jen prostě se z toho nedá pochopit všecko, ale pouze nastavení ADc pro konkrétní zařízení…

Nemáš s ADC nějaký zkušenosti i ty?

Začal jsem to házet už do simulátoru, zdá se že by to takhle mohlo fungovat…

Jen jsem přišel na malý detajl, po skončení konverze se sice bit ADSC vynuluje HW, ale stejně musím SW vynulovat potom i bit ADIF, pokud nepoužívám přerušení.

Díky, Honza

V ATmega nenastavujes 8b prevod. Nie je dovod. Prevod je vzdy 10bitovy. Ak Ta ale z nich zaujima iba hornych 8 bitov, zarovnanie vysledku daj do lava (tusim, pisem z pamati). Potom po nacitani jedneho registra mas “8bitovy” vysledok. Ak by sa Ti zdalo, ze mas vo vysledku vyssi sum, pouzi vacsi deliaci pomer. Pouzivam 64 a nebadam ziaden sum od procesora, takze nie je potrebne vypinat jadro pocas prevodu. Aj 32 je dobre, ale moze Ti to uz robit +/-1-2LSB (z 10 bitov). Vyskusaj si nejaky maly pomer a budes pozrerat, co sa generuje ak nerealizujes vsetky doporucenia vyrobcu. To ma ale zmysel iba pri vysokych vzorkovacich frekvenciach. Myslim, ze vo vacsine pripadov (dc volmeter) to vonkoncom neprekaza.

Co sa tyka nulovania zapisanim jednicky, nie je to WTF. Je to vlastnost AVR jadra, najdes to na viacerych miestach , tak si daj na to pozor.

Martin

MArtine dík za vysvětlení, už sem to konečně pochopil… pomocí toho ADLAR se nastavuje jakoby rozlišení toho ADC. Pokud je to 0, tak je 10bitů, jinak 8 bitů (v ADCH).

No to druhý je wtf, protože nejdřív napíšou že se to má vynulovat 0, a pak zas něco 1čkou…

Prostě je to nějaká blbost, kterou nechápu. Prostě po dokončení konverze se ten bit nastaví do log.1, a po vzniku přerušení (jeli povolené) se HW vynuluje. (dál citace datasheetu) Alternativně ADIF je vynulován zapsáním log.1 do něj. … … No dává tohle smysl? Mě zatim ne.

Jasne, ze dava. Zapis do bitu registra log.1 a po naslednom nacitani tam bude nula. Co je na tom nepochopitelne? Je to presne ako si napisal, len tomu odmietas uverit, lebo to nie je obvykle. Ale ako som uz napisal, tyka sa to len niektorych malo bitov v takychto registroch. Nevyplyva z toho teda to, ze ak chces niekde v RAM mat bit s hodnotou log.0, ze tam zapises log.1.
Ono to v tych malo pripadoch funguje ako RS register. Ak nastavis na S log.1 vystup Q bude mat hodnotu log.1, aj ked neskor budes mat na S log.0. Ak na R nastavis log.1, Q na nastavi do log.0. Normalne klasicky RS obvod. Zapisom log.1 do R nastavis vystup Q na log.0.
Nesmies podlahnut iluzii, ze zapisom na adresu takehoto speci registra sa data ukladaju priamo do neho. Tie jednotlive bity si system zuzitkuje ako potrebuje, napriklad pre resetovanie bitov, ktore su interne vystupmi nejakych RS obvodov. Podobne to mas, ako ked z jednej adresy po sebe nacitas dve hodnoty a kazda je ina. Procesor tak “setri” adresny priestor na tych cinnostiach, kde je to implicitne mozne a z hladiska jeho architektury i vhodne. On by si zbytocne pamatal hodnotu bitu, ktorou by si chcel ADIF nulovat. Je pravda, ze z Tvojho pohladu by bolo “logickejsie”, keby si tam zapisoval log.0 a tym si priznak ADIF nuloval. Potom by sa jednalo o obvod S/R. Preco tam ten invertor nedali neviem, asi k tomu mali nejaky konstrukcny dovod. Pre Teba vobec nie je dolezite vediet preco to tak je, ale ze to tak je. Hlavne je sa nepomylit :slight_smile:

Martin

aha tak to bacha… už sem to asi pochopil, a i ty jseš tedka asi trochu vedle…
Opravdu se to nuluje nulou (zkoušel jsem to v AVR studiu - sice tam neni nijak extra dokonalý simulátor, ale snad se tomu věřit dá…
Prostě po nahození ADSC do log.1 je to v tomto stavu do skončení převodu, po skončení se ADSC=0, a bit ADIF se nastaví do log. 1, a čeká se na uživatelovo vynulování nulou.
Ovšemže jiné je to když tam zapíšeš 1 násilím (do ADIF) tak se to asi prostě zase hned samo vynuluje, jako když tam nejde zapsat log. 1, ale jen log. 0.

SNad to chápu dobře…

Martin to vysvětluje trochu složitě. U všech AVR platí jednoduché pravidlo. Pokud se jedná o control registr, nastavují se jeho bity do 1 zápisem 1 a nulují zápisem 0. Pokud jde o status registr, je defacto určen pro čtení stavu, neboť jeho bity signalizují stav jisté periferie. Zápis do takového registru by logicky neměl mít smysl. Jsou ale případy, kdy periférie status bit nastaví a je třeba jej nulovat. V takových případech to neze řešit jinak, než zápisem 1 do příslušného bitu. Je to proto, aby bylo možné vybrat jen ten požadovaný a ostatní přitom neměnit a to vše v jediné instrukci.
U ADC jsou řídící bity a stavové z úsporných důvodů sloučeny do jediného registru ADC Control and Status Register.
Spouštění ADC je popsáno v datasheetu na str. 198. Pokud nechceš používat přerušení, nemá smysl se zabývat stavem ADIF. Převod je ukončen, když ADSC = 0.

no já jen mám podezření, že pokud nebudu bit ADIF nulovat SW, tak neproběhne další převod, dokud ADIF nevynuluju

Další převod by měl proběhnou. Pakticky jsem nikdy nepoužil ADC bez přerušení, takže to nenám vyzkoušené. On totiž převod trvá dost dlouho a čekat na výsledek v nějaké smyčce mi příjde značne neefektivní.
Pro měření napětí jako u voltmetru je nutné nasbírat více vzorků a nějak je statistiky vyhodnocovat, takže pak má AVR dost práce.
U ATmega8 lze převodník spouštět jen softwarem nebo ho nechat volně běžet. Lépe jsou na tom novější AVR jako např. ATmega88, kde je možné ADC spouštět některou periférií (AC, Timer,…). V mnoha případech je nutné, aby start ADC byl přesně načasován.

Tak zejtra to zkusim “dát do reálu” zapojim si AVRko, vymyslim nějaký jednoduchý program, a uvidíme, jak to půjde…

ad mega88… joo, kdyby nebyly tak drahý… (kapesný moc malý :wink: )

Díky moc všem, dám vědět jak to dopadlo, hned jak to vyzkouším
Honza

jak to teda dopadlo ?
Leží mně v šilíku akcelerometr a rád bych si udělal loger do letadla a právě přemýšlím kterak oživit AD převodník.

Jak moc se létají ty vzorky ?
Plánuju to naprogramovat stylem odměř napětí porovnej to s minimální dosud naměřenou hodnotou - pokud je menší přepiš to též s největší hodnotou a tak furt dokola. Tak aby se mně neuložila jako největší hodnota nějaká špička nebo šum

Kupodivu jsem to zatím zkoušel jen v nedostatečném simulátoru AVR…
do reálu jsem se nedostal…

Otevři datasheet, a pokud pro tebe angličtina není problém, postupuj přesně podle toho DS. Já tak učinil, a v simulátoru jsem fungoval úspěšně na prvý krát… (ale v reálu to může vypadat už jinak)…

Jak moc se “létají” ty vzorky? - nechápu… ??
šum tam až zas tak moc nehrozí… Navíc můžeš to AVRko dávat do sleep modu,… pak bude šum minimální…

Jinak ten postup, jhak bys to programoval, mi není úplně jasný…
napeti= namerena hodnota
jestlize napeti < než CO? tak to přepiš “též” (??!!) s největší hodnotou (čeho??)

Pormiň byl večer.

Cílem je zachytit největší a nejmenší napětí. A cílem dotazu bylo zjistit jaké je pravděpodobnost toho že mi ADC vyplivne nějakou totální kravinu. Když se tak stane tak je výsledek nepoužitelný.

to že ti vyplivne totální kravinu by se stát nmělo… leda tak bude trocha šumu plus mínus pár LSB…

záleží taky, jak často chceš měřit, co dalšího ten procík bude dělat,…

Takže jenom zjistit největší a nejmenší naměřenou hodnotu?
<<pokud tam máš akcelerometr, tak lkogicky, nejmenší hodnota bude 0, nebo ne?

  1. to sem rád šum to nerozhodí
    2)poběží to ve freerunning módu takže měřím furt. mezitím než se změří by měl porovnat jestli to co změřil je věší než to co je v registru max a případně to přepsat a potom jestli je to menší než min a případně přepsat. potom se zacyklí na kotrole jeli seplý vypínač a nebo jeli změřeno. při sepnutém vypínači skočí do smyčky která vypíše min a max na display a zacyklí se dokud je vypínač sepnutý.
    a to je všecko.

Teď mně napadá že bude asi lepší spouštět měření ručně. Běží to celé na interním oscilátoru 1MHz a předdělička je jenom 16.

Co se stane pokud bude A/D měřit na měnší frekvenci než je těch doporučovaných 50khz ? Pujde přesnot taky do kytek ? pro měn by bylo nejlepší kdyby měřil třeba 10Hz - nechci snímat vibrace ale regulární přetížení.

Jo a taky si nejsem jistý co s tím referenčním napětím. Z akcelerometru leze pří maximu (50G) Vcc a pří druhém extrému (-50G) 0V beztížný stav je 0,5Vcc Přičemž Vcc by mělo být 5V.
V Meze mám na výběr ze třech možností

AREF, Internal Vref turned off - jestli dobře chápu tak pin Aref připojím na horní mez napětí čili Vcc a to je všecko

AVCC with external capacitor at AREF pin - Vcc připojit na pin AVCC a na Aref připojit konda

Třetí je interní zdroj 2,65V to nepotřebuju… Takže který z těch dvou je pro mně to pravé ?
Díky.

[/list]

B je spravne. :slight_smile:, ale iba ak akcelerometer pouziva ako referenciu svoje Ucc.

Pouzi ako referenciu AVcc. Z AVcc mozes priamo napajat ten akcelerometer
Medzi Vcc a AVcc daj tlmivku (malu, par uH, podla doporucenia z datasheetu) a medzi AVcc a GND kondik.

Ak ma ale akcelerometer svoju internu referenciu a signal na vystupe len zosilni aby dosiahol 5V, potom vystup z akcelerometra vydel dvoma odporovym delicom 1:1, prived na vstup AD a ako referenciu pouzi aspon jeho internu 2.56V

Martin

dobrý Martine, už to spolu řešíme po ICQ… bude to dělat tak jak ty řikáš…
:slight_smile:
zbytek dořešujeme taky :slight_smile:
Honza

Díky.

Ale eště mně vratá hlavou proč je A špatně .

Nepovedal som, A je zle, ale ze B je spravne. Dalo by sa pouzit aj A, ale uz ked v samotnom procesore maju moznost volby referencie ako AVcc bez hw prostriedkov, tak preco to nevyuzit ? Aj ked sa to za urcitych okolnosti moze zdat byt zdvojene, lebo skutocne staci prepojit AVcc s Uref.

Martin