ADC Mega8 dva vstupy

C,C++,C#

Moderátori: psichac, Moderátori

Používateľov profilový obrázok
madboy
Okoloidúci
Okoloidúci
Príspevky: 30
Dátum registrácie: 25 Aug 2012, 19:58

ADC Mega8 dva vstupy

Príspevok od používateľa madboy » 23 Aug 2013, 21:57

Mam dotaz či nemate niekto skusenosti v ATMEGA8 a čitania viacerych hodnot a zobrazovania na LCD alebo ine využitie Dakujem za každu radu popripadne nejaky vzor.
0

loony
Stály člen
Stály člen
Príspevky: 100
Dátum registrácie: 10 Jan 2008, 00:00
Bydlisko: ruzomberok
Vek: 34

Re: ADC Mega8 dva vstupy

Príspevok od používateľa loony » 23 Aug 2013, 22:31

A ten fajnovy serial o programovani v AVR si už čítal?
0

Používateľov profilový obrázok
kelwin
Stály člen
Stály člen
Príspevky: 336
Dátum registrácie: 31 Máj 2013, 12:16

Re: ADC Mega8 dva vstupy

Príspevok od používateľa kelwin » 23 Aug 2013, 22:46

ADC0-ADC5 mas ADC kanaly vcom je problem? len si vyberies iny kanal kde mas iny analog senzor a precitas
ADC0-ADC3 su dokonca solo cize nekoliduju s inou funkciou na danom pine.

Kód: Vybrať všetko

ADMUX = ..... MUX0 alebo MUX1 alebo MUX2.... a tak dalej vzdy iba jeden
Este som zabudol jednu vec dopisat ze prve citanie z ADC konverzie treba ignorovat to je nepouzitelne
bud si spravis funkciu ktora to spravi a az druhe citanie ti vrati hodnotu alebo to sprav ze zavolas 2x tu istu funkciu adc_read
A este je asi dolezite spomenut ze na ten port PORTC a hned vedla ADC nedavaj nieco co ho zatazi
ledky alebo rozkmitane piny daj na PORTC tj piny (PCx) alebo PORTD (PDx) aby si menej ovplyvnoval tu ADC konverziu (menej rusis)
Atmel ma jeden datasheet ako znizit noise a ako ma vyzerat cela bizuteria okolo ADC vstupu a pripadny oversampling tusim 12bit rozlisko zneho dostanes ak by ti 10bit nestacil.

nieco taketo

Kód: Vybrať všetko




uint16_t adc_read(uint8_t channel) 
 {  
  #define    VREF_CFG  0 // toto si zmen podla datasheet page 199
                                  // REFS0 a REFS1 mas tie bity co znamenaju
  ADMUX|= VREF_CFG | channel ; 
 _delay_ms(200); 
   ADCSRA|=(1<<ADSC); 
   while ( !(ADCSRA & (1<<ADIF))); 
   ADCSRA|=(1<<ADIF); 
   return (ADC); 
 }
potom pouzitie moze byt napriklad takto

Kód: Vybrať všetko


#define KANAL1 1 //ADC1 pin23
#define KANAL2 2 //ADC2  pin24

adc_init(); // treba inicializovat ADC zapnut a pod.
uint16_t cidlo1, cidlo2;

cidlo1 =  adc_read(KANAL1); // prve citanie po inite treba zahodit nieje validne

/// tu zacina co ta zaujima 

cidlo1 =  adc_read(KANAL1l)  // citam teplomer 1

cidlo2 = adc_read(KANAL2)   // citam teplomer 2 napriklad

....... // rob uz co treba 
....... // nieco pocitas z vysledku pre zobrazenie na LCD
....... //

Parameter funkcie adc_read(channel) nieje poradove cislo ADC pinu (aj ked to sedi)
ale je to cislo ktorym binarne maskujes ADMUX prepinas vstup na prevodnik.

Spravnu hodnotu si musis skontrolovat v datasheete tvojho ATmega8 strane 188
Tabulka 72. Analog Comparator Multiplexed Input
Ma kolonku MUX2..0 - zapis MUX2..0 znamena ze su to 3 bity ADMUX registra tj kombinacia troch nul alebo jedniciek
tie bity sa nazyvaju ( MUX2 MUX1 MUX0 )

Hodnoty v stlpci su ale binarne cize to musis vediet prepocitat na decimalne priklad.
binarne 001 = 1(decimal), binarne 010 = 2 (decimal), binarne 011 = 3 (decimal) (dufam ze toto je jasne)

Potom daj vediet ako sa dari pripadne aj nedari ;)
0

Používateľov profilový obrázok
madboy
Okoloidúci
Okoloidúci
Príspevky: 30
Dátum registrácie: 25 Aug 2012, 19:58

Re: ADC Mega8 dva vstupy

Príspevok od používateľa madboy » 24 Aug 2013, 21:44

loony: Jasne že čital a je to ten najlepší navod na AVR čo som na celom internete našiel a vdaka nomu som na strednej spreavyl soč a zmaturoval :) tymto sa chcem zawin-ovy podakovat keby to nahodou čital :)
Kelwin : Dakujem za obširnejšie popisanie navodu našiel som na nete dobry vzor http://winavr.scienceprog.com/example-a ... inavr.html podarylo sa mi pomocou toho v protheus rozchodit to ale ja použivat knižnice od zawina s toho serialu o programovany tak zajtra sa idem do toho pustit študovat ako to upravyt alebo napisat an to program
P.S ešte mam dotaz kedže som trocha začiatočnik su nejake pravidla pri pisani knižnic?? alebo ich uprave???
0

Používateľov profilový obrázok
madboy
Okoloidúci
Okoloidúci
Príspevky: 30
Dátum registrácie: 25 Aug 2012, 19:58

Re: ADC Mega8 dva vstupy

Príspevok od používateľa madboy » 24 Aug 2013, 21:51

inak ten link je asi presne to čo potrebujem jedine čo som asi zatial skušal je pokus s klavesnicou co som si len tak postavil a kod je asi dost zbytečne dlhy nič lachšie ma nenapadlo

Kód: Vybrať všetko

    #include <avr/io.h>  
    #include <util/delay.h>  
    #include <avr/interrupt.h>  
    #include <stdlib.h>  
    #include <stdio.h>  
    #include "lcd.h"  
      
    
    volatile unsigned int adc;  
      
 
    ISR(ADC_vect){  
      
        adc=ADC;  
      
    }  
      
    int main(){  
	
		DDRB = 0b11111111;
		char text[32];
      
        ADMUX |=  (1 << REFS0);
        ADCSRA |= (1 << ADEN) | (1 << ADSC) | (1 << ADFR) | (1 << ADIE) | (1 <<ADPS2) | (1 <<ADPS1)  | (1 <<ADPS0);  
        sei();
      
        lcd_init(LCD_DISP_ON);
		 lcd_home();
		lcd_clrscr();
		lcd_puts(" Ahoj");
		_delay_ms(2000);

		int cislo = 0;
      
        while(1){
		if(adc > 1000)
		{
			cislo = 0;
			_delay_ms(20);
		} 
        if(adc >= 980)
		{
			if(adc <= 1000)
			{
				cislo = 1;
				_delay_ms(20);
			}
		} 
		if(adc >= 870)
		{
			if(adc <= 980)
			{
				cislo = 3;
				_delay_ms(20);
			}
		} 
		if(adc >= 650)
		{
			if(adc <= 870)
			{
				cislo = 2;
				_delay_ms(20);
			}
		} if(adc >= 500)
		{
			if(adc <= 650)
			{
				cislo = 4;
				PORTB = 0b11111111;
				_delay_ms(1);
				PORTB = 0b00000000;
				_delay_ms(19);
			}
		}  if(adc >= 300)
		{
			if(adc <= 500)
			{
				cislo = 5;
				_delay_ms(20);
			}
		} if(adc >= 175)
		{
			if(adc <= 300)
			{
				cislo = 6;
				PORTB = 0b11111111;
				_delay_ms(2);
				PORTB = 0b00000000;
				_delay_ms(18);
			}
		} if(adc >= 100)
		{
			if(adc <= 175)
			{
				cislo = 7;
				_delay_ms(20);
			}
		} if(adc >= 25)
		{
			if(adc <= 100)
			{
				cislo = 8;
				_delay_ms(20);
			}
		} if(adc <= 25)
		{
			cislo = 9;
			_delay_ms(20);
		}
        sprintf(text," Stlacene: %d", cislo);
		lcd_clrscr();
		lcd_puts(text);
		lcd_gotoxy(0,0); 
        }  
      
    }  
0

anonymousCoward
Stály člen
Stály člen
Príspevky: 150
Dátum registrácie: 12 Máj 2013, 11:09
Bydlisko: KE

Re: ADC Mega8 dva vstupy

Príspevok od používateľa anonymousCoward » 25 Aug 2013, 00:06

Par pripomienok ku kodu:
1) Volatile je presne to co v tomto pripade potrebujes - davas tym kompilatoru najavo ze hodnota takto deklarovanej premennej sa moze 'neocakavane' zmenit. To ale tiez znamena, ze porovnavanie hodnot premennej 'adc' v kode vo 'while(1)' nie je v pravom slova zmysle deterministicke - napriklad, ak prave pred vykonanim riadku 'if (adc >= 980)' skonci ADC konverzia, a vykona sa ISR ktore do tejto premennej ulozi hodnotu 981, 'hlavny' program bude pokracovat telom podmienky. Kym sa caka v delay, skoro urcite skonci dalsia konverzia, nasledne ISR moze nastavit premennu 'adc' na inu hodnotu, napriklad 971, v dosledku coho sa vykona aj telo inej zodpovedajucej podmienky.
Riesenim je pouzit pomocnu premennu, do ktorej na zaciatku cyklu 'while (1)' skopirujes aktualnu hodnotu premennej 'adc', a dalej budes pracovat len s hodnotou tejto pomocnej premennej. To ale znamena ze stratis nejake vysledky konverzii, comu sa pri tak dlhom cakani aj tak nevyhnes.
2) Priradenie premennej typu 'unsigned int' nemusi byt v pripade ATmega8 atomicke. Zavisi to od toho, co kompilator chape pod 'unsigned int', a to zase zavisi od neprijemne vela dalsich veci, viac ci menej zjavnych. Atomicita je vlastnost prikazu, resp. bloku prikazov ktora zaruci ze sa vykona prikaz (blok) cely bez prerusenia.
V prvom rade Ti silno odporucam nepouzivat 'klasicke' C typy, kedze nie su pre tento ucel presne definovane. Namiesto nich pouzi zodpovedajuci typ zo <stdint.h>, v Tvojom pripade to bude uint16_t. Pouzitie takychto ciselnych typov okrem mensieho zmatenia kompilatora a programatora ma aj tu vyhodu, ze mas moznost pouzit najmensi mozny vyhovujuci typ (varianty Xint_fastXX_t), co je optimalizacia k nezaplateniu; nieco zoptimalizuje aj kompilator, ale obcas by na to potreboval vediet citat myslienky, co nastastie este mozne nie je.
Atomicitu pre blok si vynutis pomocou makier z <util/atomic.h> - tie sice nerobia nic ine nez 'cli()' a 'sei()' (ehm), ale robia to spravne a minimalizuju priestor pre chybu programatora.
3) Porovnavanie hodnot 'adc' vo 'while (1)' nie je celkom optimalne, a vzhladom na to ze porovnavas 'volatile' premennu Ti to nezoptimalizuje ani kompilator. Rada z bodu #1 tomu sice pomoze, ale je dobra praktika napisat to priamo, tak ako si to nakoniec aj (asi) myslel - t.j. namiesto 'if (nieco) {} if (nieco_ine_co_bude_true_ak_a_iba_ak_je_false_to_predtym) {} ...' napis if (nieco) {} else if (nieco_ine...) {} atd.'.

Pre ilustraciu, nejako takto:

Kód: Vybrať všetko

// inicializacia
...
sei();
...
// hlavny cyklus
while(1) {
   uint16_t pomocneAdc; // toto prosim premenuj na nieco rozumne
   ATOMIC_BLOCK(ATOMIC_FORCEON) {
      pomocneAdc = adc;
   }
   if (pomocneAdc < 1000) { // resp. bisekcia, ak sa da
      if (pomocneAdc > ...) {
      } else if (pomocneAdc ...) {
      } else if (...) {
         ...
      }
   } else {
      // nieco
   }
}
Funkcie k LCD a ich pouzitie som neoveroval, ale zvysok vyzera OK. Pri buducich problemoch by to chcelo vidiet schemu, a idealne aj PCB. Kontrolna otazka - ako mas riesene napajanie ADC ?

K Tvojej otazke o pravidlach pri pisani kniznic - odpoved ma dve stranky:
* Technicku o modularite v C - k tomu pozri toto, alebo v matercine toto.
* 'coding conventions' a 'best practices', ktore ciastocne zahrnaju aj technicku stranku veci (globalne premenne, naming, atd). Na webe som narychlo nenasiel nic presvedcive k AVR GCC, resp. embedded C; snad len appnote AVR035 a appnote AVR4027. Vseobecne k C/GCC je toho viac: Linux Kernel coding style, http://www.doc.ic.ac.uk/lab/cplus/cstyle.html, mozno http://www.jetcafe.org/jim/c-style.html. V rodnom, ci bratskych jazykoch som nenasiel na webe nic, ale mozem odporucit vynikajuci Viriusov preklad a rozsirenie knihy 'C traps & pitfalls', s nazvom 'Pasti a propasti jazyka C'. Original je tu.

Kazdy vacsi (open source) projekt by mal mat vlastne pravidla. Plati ze kolko projektov, tolko konvencii, a niektore su dokonca v priamom rozpore, hlavne v castiach o pomenovavaniach a formatovani :) To ale nevadi - taketo elaboraty su vzdy len zaklad pre zamyslenie sa; kazde uvedene pravidlo by malo mat svoj zmysel a dovod. Dolezite je pochopit co je za tym, namiesto slepeho aplikovania. Vyber si z nich aspon nejake pravidla ktorym rozumies a ktore budes konzistentne dodrziavat od zaciatku, a postupne si pridavaj dalsie.
0
War is peace. Freedom is slavery. Ignorance is strength.
There is no such thing as a well-adjusted slave.

Používateľov profilový obrázok
madboy
Okoloidúci
Okoloidúci
Príspevky: 30
Dátum registrácie: 25 Aug 2012, 19:58

Re: ADC Mega8 dva vstupy

Príspevok od používateľa madboy » 28 Aug 2013, 19:32

]Dakujem za suprove vyvetlenie snažim sa to pochopit :) v tom liknu čo som dával je funkčny program len sa ho snažim pochopit a prerobit na knižnice čo použivam nech to možem použivat ajja :) abych mohol vytvorit si knižnice pre ADC pre intADC a čitanie viacerích hodnot naraz ... čo sa tíka PCB mam spravene podla mna dost dobre
prikadam foto schemy
Prílohy
povedal by som že je to najelpšuie vyriešeny KIT pre atmega8 na testovanie a ako univerzalne zapojenie pre naučenie sa programovania a ako mozog do robota
povedal by som že je to najelpšuie vyriešeny KIT pre atmega8 na testovanie a ako univerzalne zapojenie pre naučenie sa programovania a ako mozog do robota
0

anonymousCoward
Stály člen
Stály člen
Príspevky: 150
Dátum registrácie: 12 Máj 2013, 11:09
Bydlisko: KE

Re: ADC Mega8 dva vstupy

Príspevok od používateľa anonymousCoward » 29 Aug 2013, 12:00

Kedze pises ze to je schema 'najlepsie rieseneho kitu pre ATmega8', tak si dovolim - uz len pre fun & profit - byt prehnane kriticky:
1) Za LE33 je v scheme popiska 6V, to asi nie je spravne - u tohoto regulatora je vystup 3.3V +- 2% resp +- 4%, uz podla suffixu.
2) Na nRESET je spinac ktory ho skratuje do zeme, a preto by som tam kvoli debouncingu dal maly kondenzator, vybijany cez spinac a rezistor. Urcenie konkretnych hodnot je dobre cvicenie na preopakovanie si casovej konstanty - alebo na citanie AVR HW Design Considerations. Urcite tam ale nepatri nieco s privelkou kapacitou, pretoze by to mohlo prekazat pri programovani cez SPI. Dalsim vylepsenim by bola dioda medzi nRESET a Vcc, a/alebo Zenerka medzi nRESET a zemou.
3) Vstup cez K1 nema osetrenie prepolovania, ani sa nikde nedeje osetrenie prekrocenia nejakeho maximalneho povoleneho napatia. Na vstupe LM1085 moze byt nanajvys 25V, co zodpoveda max napatiu na C12, ale chcelo by to aspon jednosmerny transil, a namiesto K1 koncovku, ktora zabrani nespravnemu pripojeniu zdroja.
4) Zbytocne velke maximalne napatie C3, ciastocne to plati aj pre C11. V tomto pripade to znamena len viac zabrateho miesta na PCB, a drahsiu suciastku. Je ale rozhodne dobre nechat nejaku primeranu rezervu - vyrobcovia odporucaju nestresovat trvalo Al elektrolyty viac nez 70% z maximalneho urceneho napatia; niekedy je na mieste ist az na 40 ci 50% (derating kvoli starnutiu, nizsi leakage prud). Vynimkou su Al el kondenzatory na vyssie napatia (stovky V - co nie je tento pripad) kde moze dojst k rychlejsiemu starnutiu pri trvalom pouziti ovela nizsieho napatia nez je to maximalne urcene. Pre C3 a C11 staci pouzit 10V kondenzatory; menej radsej nie, hlavne ak pojde o vyrobcu ktory rad setri.
5) Neviem ci planujes pouzivat externy krystal, ale ak ano, bolo by vhodne vyviest cim blizsie k pinom XTAL1 a XTAL2 preciznu paticu (DIP-8, resp -6 ak zozenies) pre pripojenie krystalu, startovacich kondenzatorov, a mozno inej bizuterie. A ak by vodice z XTALx iduce do J7 mali byt dlhsie nez par centimetrov, alebo by isli popri inych aktivnych vodicoch, bolo by tiez kvoli minimalizacii rusenia vhodne tesne za paticu pridat dva jumpery pre odpojenie tychto vodicov.
6) Kapacita kondenzatora C11 za regulatorom LM1085 je pomerne velka. Nastastie, LM1085 je linearny regulator typu quasi-LDO - taketo regulatory su menej citlive na vhodny vyber vystupneho kondenzatora nez standardne (NPN) LDO regulatory, ktore sa pri primalej alebo privelkej hodnote ESR (dajme tomu, ze krat kapacita) ich kondenzatorov mozu dostat do oscilacii. Datasheet LM1085 hovori ze 'recommended load/decoupling capacitance is a 10uF tantalum or a 50uF aluminum. These values will assure stability for the majority of applications', ale hovori tiez ze privelka kapacita nevadi, skor naopak. Ak by si ale chcel pouzit este vacsi vystupny kondenzator (>1m, podla datasheetu), tak by bolo dobre pridat ochrannu diodu ktora vybije tento kondenzator mimo regulator, pre pripad ze sa vstup regulatora skratuje do zeme - a to sa moze stat pri prepolovani, alebo pri zlyhani C12 do skratu.
7a) Problem s oscilaciami mozu sposobit kondenzatory C9 a C1 - su to pravdepodobne keramicke kondenzatory, a tie zvyknu mat velmi male ESR. Kedze budu asi pripojene blizko k vystupu LM1085, tak vsetko zavisi od ich frekvencnych charakteristik vzhladom na kriticke frekvencie regulatora, lenze taketo data som k LM1085 nenasiel, a co mam, je 'approximately' (citat z datasheetu). Najlepsie by bolo vobec ich neosadzovat, kedze v regulatore Ti sum ktory by mohli potlacit aj tak nevznikne, a na jeho vstupe uz mas C8.
7b) Este stale Ti ale zostanu kondenzatory decouplujuce MCU, ktore budu sice fyzicky dalej, ale mozno nebudu dost daleko (tym nechcem povedat ze mas mat metrovy plosak). Atmel odporuca oddelit napajanie MCU cez feritovy bead - ak ho nemas, a nemas ani vhodnu alternativu, tak sprav Babicu a daj tam 0.1 Ohmovy odpor. Nebude to sice filtrovat vyssie frekvencie, ale ma to sancu zabranit oscilaciam kvoli spatnej vazbe LM1085. Tak ci tak sa ale nevyhnes dlhodobemu pozeraniu do osciloskopu, uz len pre istotu.
osem) Atmel v datasheetoch pouziva na oddelenie AVCC od VCC 10uH feritovy bead, ty mas 100uH. Dolezitejsia nez induktancia je v tomto pripade impedancia na vyssich frekvenciach; tie ktore pouziva Atmel maju DC odpor do 0.3 Ohmu, a impedanciu na 100MHz az 1K Ohm. To je len odporucanie, konkretne hodnoty zavisia od ocakavanych ruseni zo zdroja resp. z prostredia. Okrem toho je dobrou praktikou dat paralelne ku keramickemu kondenzatoru medzi AVCC a zem aj nejaky mensi tantal, resp. elektrolyt (alebo idealne viac keramik s rozlicnymi kapacitami, a teda s rozlicne posunutymi zavislostami ESR od frekvencie). To vsetko ma zabezpecit filtrovanie mozneho rusenia z VCC, a sucasne aj poskytnut dostatocny narazovy prud pri rychlych konverziach.

Ak sa nebojis, ukaz PCB :) Layout je snad este dolezitejsi nez to vsetko co som napisal vyssie.
0
War is peace. Freedom is slavery. Ignorance is strength.
There is no such thing as a well-adjusted slave.

Napísať odpoveď