logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Brak stabilnych wskazań po konwersji A/D w ATMega 8

slawek55 08 Gru 2007 16:10 2997 22
  • #1 4565702
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Bardzo Was proszę o pomoc bo nie mogę sobie dać rady.

    Uruchamiam przetwornik ADC w ATMega 8. Mam podłączony wyświetlacza LCD 2x16 do prezentacji wyników. Jako źródło napięcia stosuję napięcie zasilające 5V.
    I nie mogę uzyskać stabilnych wskazań. Po konwersji cały czas wynik jest inny. Jako płytkę testową stosuję AVT948 bo miałem pod ręką tyle tylko że inny wyświetlacz. Kwarc 16MHz.
    Zrobione jest tam wszystko jak trzeba, napięcie zasilające przetwornik filtrowane, napięcie zasilające też.

    Pomóżcie co mam zrobić i gdzie jest błąd.
    Podsyłam fragment programu.
    
    nt main(void)
    {
    	
    	DDRB=0xFF;
    	
    	DDRC=0x00;
    	DDRD=0xFF;
    	
    	PORTC=0x00;
    	PORTD=0xFF;
    		
        Lcd_init();
    	
    	    ADMUX=0x40;
    	//ADC channel 0, internal vref=5V
    	ADCSR=0x86; //single conversion,  prescaler=64
    	ADCSR|=0x40;
    	//start first dummy conversion - here ADC is adjusting himself
    	while((ADCSR & 0x40)!=0);
    	
    		
    		Lcd_clear();
    			
    	while(1)
    	{
    		
    	Waitms(100);   
    	Lcd_home();
    	dana=GetADC();
    	Lcd_write(itoa(dana, table, 10));
    	Lcd_write_rom(PSTR("      "));
    	
    	}
    	
    return 0;
    }	
    
    
    
    unsigned int GetADC(void)
    {
    ADCSR|=0x40;
    while((ADCSR&0x40)!=0);
    return ADC;
    }
  • #2 4566600
    MirekCz
    Poziom 35  
    Posty: 2220
    Pomógł: 330
    Ocena: 62
    1.Co to znaczy, że wynik jest cały czas inny?

    2.Daj dokładny schemat urządzenia i najlepiej też layout (PCB)
  • #3 4566683
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    1. To znaczy że jak na wejscie podam np 1.2V to zamiast stabilnej liczby 246 dec (przy napięciu Vref=5V) otrzymuje wynik od 200 do 300 dec za każdym pomiarem inny (tzn za każdym obiegiem pętli pomiarowej na ww. listingu)

    2. Link do PCB http://www.ep.com.pl/pobierz.php?id=2865

    Schemat jest tu: http://www.ep.com.pl/pobierz.php?id=15753

    czyli w EP09/06
  • #4 4568653
    migod
    Poziom 21  
    Posty: 462
    Pomógł: 29
    Ocena: 8
    Też tak mam, pomimo dobrego filtrowania i tak muszę uśredniać kilka kolejnych pomiarów. Nic lepszego nie wymyśliłem.
  • #5 4568764
    Dr_DEAD
    Poziom 28  
    Posty: 829
    Pomógł: 126
    Ocena: 3
    Czyli z 10-cio bitowego przetwornika ADC uzyskujecie 4 bity stabilnego wyniku a 6 bitów to szum?? A zmniejszenie czestotliwości zegara ADC nie daje efektów?
  • #6 4568781
    snow
    Poziom 31  
    Posty: 1825
    Pomógł: 178
    Ocena: 201
    Spróbuj podczepić między pin przetwornika a masę jakiś kondensator i sygnał podaj szeregowo przez jakiś opornik. Powinno sie trochę ustabilizować (link do schematu niestety płatny)
  • #7 4568979
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Płatny, jedyne co mogę to zeskanować i podczepić na elektrodzie.
    A nie posiadacie Ep?


    Ja sprawdziłem jeszcze coś takiego.
    Podłączyłem pod przetwornik (we0) zwykłą baterie paluszka, Plus na wejscie ADC0 a minus baterii na masę i to nie przy uC tylko przy stabilizatorze i wskazania są dobre, natomiast jak mierze napięcie zasilające uC nawet przez dzielnik i kondenstaor filtrujący to i tak mi wynik skacze. Najgorsze, że mój układ jest zasilany z tego samego niapęcia co uC.
  • #8 4569816
    PiotrPitucha
    Poziom 34  
    Posty: 2658
    Pomógł: 201
    Ocena: 424
    Cześć
    Nie stosowałbym 5V jako napięcia odniesienia, wewnętrzne Ref jest zwykle stabilniejsze.
    Blokujemy zasilanie Atmegi jak najbliżej nóżek.
    Blokujemy do masy przez 100nF Vref
    Blokujemy do masy przez 100nF AVCC
    Dławik powinien być niskooporowy bo Atmega ma błąd w strukturze i VCC i AVCC jest zwarte wewnątrz rezystancją około 10ohm.
    Od strony programowej jestem noga, ale z tego co pamiętam to był jakiś wątek na temat usypiania ( ?? ) Atmegi na czas pomiaru AC
    Piotr
  • #9 4570165
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Niestety muszę mieć napięcie odniesienia 5V, ponieważ czujnik ma zakres wyjściowy 0 do 4.8V a nie chcę stosować wzmacniacza doperacyjnego dzielącego napięcie z czujnika.
    A powiedz mi skąd ta wiadomość o tym błędzię że ATmega 8 ma zwartę VCC i AVCC zwarte prze 10om. Przeszukałem notę katalgową i nic tam nie pisze w erracie też nic nie znalazłem. Możesz mi coś podesłać o tym, albo gdzie to znaleść. A Atmel wypuścił jakąś notę o używaniu jego przetworników ADC np. projekcie płytki itp.
  • #10 4570765
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    slawek55 napisał:
    A powiedz mi skąd ta wiadomość o tym błędzię że ATmega 8 ma zwartę VCC i AVCC zwarte prze 10om. Przeszukałem notę katalgową i nic tam nie pisze w erracie też nic nie znalazłem. Możesz mi coś podesłać o tym, albo gdzie to znaleść.


    Najprościej - zmierz sobie sam.

    Przed chwilą sprawdziłem, nie ma tego w AT90S4433, ATmega16 i ATmega32, natomiast w ATmega8 (kilka sztuk) jest 6.9ohm (o ile miernik pokazuje poprawnie, bo bateria słaba).
  • #12 4571653
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    Nowe też raczej mają tego "buga", sprawdzałem rok 2005, 2006 i z początku 2007.

    Kiedyś szukałem czegoś o tym na stronach Atmela i nie znalazłem. Teraz też sprawdziłem i nic nie znalazłem. Możliwe że było tak jak w wypadku Dallasa, nie udostępnili publicznie tej informacji, ale rozesłali ją do większych odbiorców. Stosowna informacja, owszem, znajduje się na stronie producenta, ale nie wyświetla się jako jeden z dokumentów dotyczących układów z wadą (termometry DS1820). Może też zwyczajnie stwierdzili że nie stanowi to problemu, bo i tak wszędzie piszą, że na AVcc musi być to samo napięcie (+/- odrobinę) co na Vcc.

    Możesz spróbować podłączyc AREF przez filtr LC do napięcia zasilania (chociaż nie spodziewam się cudów), albo jakiś stabilizator UltraLDO (na przykład TPS76950DBV, 2 zł z groszami kosztuje) na część analogową i jeżeli to mozliwe, napięcie na Vcc podnieść o powiedzmy 0.1V, tylko że to już jest kombinowanie.

    Ja bym raczej dał dzielnik napięcia z dwóch rezystorów na sygnał i TL431, albo wewnętrzne źródło jako odniesienie.

    Jeszcze takie pytanie, czym to zasilasz?
  • #13 4571685
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Zasilanie to zwykły 7812 z dużym kondensatorem na wejściu (4700u) a na samej płytce 7805 i to zasila uC.

    A czy podczas pomiaru tej rezystancji wewnątrz ATmega8 podłaczyłeś + multimetru do końcówki VCC a (-) do AVCC. A czy to w ogóle ma znaczenie. Czy można tak uszkodzić uC?

    A możesz mi pomóc jeszcze w czyms takim.
    Chce napisac funkcje obliczającą
    unsigned int press(unsigned int vall)
    {
    volatile unsigned long temp;
    temp=1087*vall;		
    temp=temp+105556;
    temp=temp/1000;
    
    return ((unsigned int)temp);
    }


    Jeśli przekazuje do finkcji np wartośc 814 to powinienem otrzymać 990 jako wynik a zwraca mi tylko 138. Co tu jest nie tak?
  • #14 4571780
    Dr_DEAD
    Poziom 28  
    Posty: 829
    Pomógł: 126
    Ocena: 3
    slawek55 napisał:

    unsigned int press(unsigned int vall)
    {
    volatile unsigned int temp;
    temp=1087*vall;		
    temp=temp+105556;
    temp=temp/1000;
    
    return ((unsigned int)temp);
    }


    Jeśli przekazuje do finkcji np wartośc 814 to powinienem otrzymać 990 jako wynik a zwraca mi tylko 138. Co tu jest nie tak?

    Używasz zmiennej typu int, a int ma zdaje sie dwa bajty, czyli w tej zmiennej możesz zapisać liczby z przedziału od 0 do 2^16 (od 0 do 65536). A u Ciebie przykładowo linijka kodu "temp=1087*vall" dla vall = 814 daje wynik przekraczający ten zakres:
    temp = 1087 * 814 = 884818
    Rozwiązanie to użycie zmiennej long lub float lub przekształcenie obliczeń tak aby każde z działań nie przekroczyło zakresu co może oznaczać zmniejszenie dokładności obliczeń.

    Dodano po 1 [minuty]:

    PS. nie piszę w C, więc to są tylko takie moje domysły.
  • #15 4571987
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Przepraszam tam wkradł się błąd przy pisaniu posta.
    Tam powinno byc
    volatile unsigned long temp;


    I na zmiennej long sprawdzałem że nie działa.
  • #16 4572101
    Dr_DEAD
    Poziom 28  
    Posty: 829
    Pomógł: 126
    Ocena: 3
    U mnie ta funkcja tyle że na unsigned long działa dobrze. Kompilowana pod IAR na MSP430. Dlaczego zmienna temp jest typu volatile? to chyba trochę bez sensu.
  • #17 4572122
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Bo jak nie dałem volatile to mi tylko zero sie pojawiało w wyniku. Jakoś kompilator ucinał kilka obliczeń.
    Trochę nie moge porównywać tych kompilatorów, IAR jest płatny i powiem profesjonalny.
  • #18 4573771
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    slawek55 napisał:
    Zasilanie to zwykły 7812 z dużym kondensatorem na wejściu (4700u) a na samej płytce 7805 i to zasila uC.

    Ważne jest co i w jakiej odległości znajduje się za stabilizatorem, i jednym, i drugim, w szczególności chodzi o indukcyjności i pojemności, a także udbiorniki pobierające duży prąd (rzędu setek mA i więcej).

    slawek55 napisał:
    A czy podczas pomiaru tej rezystancji wewnątrz ATmega8 podłaczyłeś + multimetru do końcówki VCC a (-) do AVCC. A czy to w ogóle ma znaczenie. Czy można tak uszkodzić uC?

    Obojętnie, procka nie uszkodzi, chyba że prąd pomiarowy będzie bardzo duży, tak duży że spali ten rezystor. W miernikach ten prąd jest w powalającej większości przypadków bezpiecznie mały.

    slawek55 napisał:
    temp=1087*vall;

    vall jest typu unsigned int, taki też typ zostanie przyporządkowany do wartości 1087 i tego samego typu będzie wynik mnożenia, czyli "ucięty", a dopiero potem zostanie on rozszerzony do typu unsigned long.

    Poprawnie było by tak:
    temp=1087*(unsigned long)vall;

    W takiej konstrukcji operand vall zostanie zrzutowany i będzie miał typ unsigned long, i do takiego samego typu zostanie zrzutowany drugi operand (1087).

    A już całkiem klawo było by tak:
    temp=1087UL*(unsigned long)vall;

    Nic to nie zmieni w stosunku do poprzedniego, ale przynajmniej widać co będzie wykonywane.
    Niestety C jako taki nie przewiduje bardziej zoptymalizowanych operacji mnożenia, typu 16 bitów * 8 bitów -> 24 bity z rozszerzeniem do 32.

    Na innej architekturze, zwłaszcza trzydziestodwubitowej (np. PC) Twój kod będzie działało tak jak się spodziewasz, dlatego że tam typ int jest 32 bitowy, a typ ten przypisywany jest domyślnie, między innymi do wartości podanych w formie numerycznej. W rezultacie drugi operand (vall) zostanie również zrzutowany na 32 bitowy typ i operacja zostanie wykonana na 32 bitach.
  • #19 4575106
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    Działa dziękuję.
    A możesz mi powiedzieć skąd Ty bierzesz takie informacje?

    A czy przy okazji mogę się podpytać o taką rzecz.
    Mam układ ATMega162 z zewnętrzną pamięcią RAM 62256.
    Całość jest pisana w AVR-GCC używając AVR Studio.
    Potrzebuję aby ta pamięć RAM była tylko do przechowywania takich danych jak np tablica.
    Jak zmusić AVR Studio tzn gdzie i co wpisać, aby kompilator mógł korzystać z niej jako dodatkowa pamięć ale nie zmieniał umiejscowienia typowych sekcji takich jak stos, .bss itd. Te maja być w wewnętrznej RAM. Najlepiej jakby dało się stworzyć dodatkową sekcję oznaczoną np EXRAM coś takiego jak EEPROM.
    Walczę z tym od jakiegoś czasu w sensie poszukiwań informacji ale z marnym skutkiem.
  • #20 4577451
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    slawek55 napisał:
    A możesz mi powiedzieć skąd Ty bierzesz takie informacje?

    z dokumentacji, z internetu, z doświadczeń i prób.

    slawek55 napisał:
    A czy przy okazji mogę się podpytać o taką rzecz.
    Mam układ ATMega162 z zewnętrzną pamięcią RAM 62256.
    Całość jest pisana w AVR-GCC używając AVR Studio.
    Potrzebuję aby ta pamięć RAM była tylko do przechowywania takich danych jak np tablica.
    Jak zmusić AVR Studio tzn gdzie i co wpisać, aby kompilator mógł korzystać z niej jako dodatkowa pamięć ale nie zmieniał umiejscowienia typowych sekcji takich jak stos, .bss itd. Te maja być w wewnętrznej RAM. Najlepiej jakby dało się stworzyć dodatkową sekcję oznaczoną np EXRAM coś takiego jak EEPROM.

    Taki kod na szybko, bez wodotrysków, to znaczy bez inicjalizacji zmiennych znajdujących się w tej sekcji (zmienna indeks2 nie zostanie zinicjalizowana):
    #include <avr/io.h>
    #include <stdint.h>
    
    #define XRAM __attribute__ ((section (".xram")))
    
    uint8_t tmp=0;
    uint8_t indeks=0;
    XRAM uint8_t indeks2=48;
    
    uint16_t suma=0;
    uint16_t bufor2[256];
    
    XRAM uint8_t bufor[256];
    XRAM uint32_t histogram[256];
    
    int main(void) {
    	if(indeks == 0) {
    		bufor2[indeks2++] = suma;
    		suma = 0;
    	}
    	while(1) {
    		tmp = bufor[indeks];
    		bufor[indeks] = PORTC;
    		PORTD = tmp;
    		suma += tmp;
    		histogram[tmp] += 1;
    		if(tmp > 127) {
    			PORTB = histogram[indeks] & 0xff;
    		} else {
    			PORTB = bufor2[indeks] & 0xff;
    		}
    		indeks++;
    	}
    	return 0;
    }


    Program jest oczywiście bez sensu ;]

    Do Makefile trzeba dopisać to:
    -Wl,--section-start,.xram=0x0800460

    W szablonie Makefile z WinAVR jest nawet na to miejsce stosowne przeznaczone, gdzieś w okolicach połowy:
    EXTMEMOPTS = -Wl,--section-start,.xram=0x0800460

    Adres początku sekcji wziął się stąd, że wszystko co ma być umieszczone w pamięci RAM zaczyna się od adresu 0x0800000. Na początku tego obszaru znajduje się plik rejestrów, potem pamięć "pokładowa" mikrokontrolewra i dopiero za nią dostępny jest zewnętrzny RAM, tak mi się przynajmniej wydaje, dlatego do 0x0800000 należy dodać długości pliku rejestrów i pamięci "pokładowej".

    Ponadto w sekcji poświęconej malloc() w dokumentacji avr-libc ("Memory Areas and Using malloc()"), oraz w dziale poświęconym obszarom pamięci ("Memory Sections") są opisane różne sposoby na wykorzystanie zewnętrznego RAMu.
  • #21 4578916
    slawek55
    Poziom 23  
    Posty: 788
    Pomógł: 3
    Ocena: 61
    W AVRStudio4 jest taka zakładka w opcjach. Czy wiesz jak ja wypełnić dla zewnętrznego RAMu (rzut ekranu poniżej)
    Załączniki:
    • Brak stabilnych wskazań po konwersji A/D w ATMega 8 options.jpg (34.2 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #22 4579274
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    Memory type: sram
    Name: .xram
    Address: 0x800460
    W pomocy zresztą jest napisane.

    Program taki sam jak w moim poście powyżej, tj. dodaje do opcji linkera taką linię:
    LDFLAGS += -Wl,-section-start=.xram=0x800460


    Niestety AVRStudio uparcie nie chce wygenerować listingu, a symulator się zawiesza, więc nie za bardzo mam jak sprawdzić. Mogłem zajrzeć tylko do pliku .map, tam są adresy w porządku.

Podsumowanie tematu

✨ Problem dotyczy niestabilnych wskazań przetwornika ADC w mikrokontrolerze ATMega8 zasilanym napięciem 5V i podłączonym wyświetlaczem LCD 2x16. Pomiar napięcia na kanale ADC0 wykazuje duże wahania wartości pomiarowych (np. od 200 do 300 przy oczekiwanej stabilnej wartości 246 dla 1.2V). Testy z użyciem baterii jako źródła napięcia dają stabilne wyniki, natomiast pomiary napięcia zasilającego mikrokontroler, nawet po filtracji, są niestabilne. Wskazano, że w ATMega8 istnieje wewnętrzna rezystancja około 7Ω między pinami VCC i AVCC, co może wpływać na stabilność pomiarów ADC. Zalecane jest stosowanie filtrów kondensatorowych (np. 100nF do masy na Vref i AVCC) oraz niskooporowych dławików na linii zasilania analogowej części mikrokontrolera. Wskazano również, że wewnętrzne napięcie odniesienia jest stabilniejsze niż zasilanie 5V, jednak w tym przypadku konieczne jest użycie 5V jako Vref ze względu na zakres czujnika. Jako rozwiązanie częściowe sugerowano uśrednianie wielu pomiarów oraz zastosowanie kondensatora i rezystora szeregowego na wejściu ADC. Wątpliwości dotyczą także poprawności obliczeń w funkcji przetwarzającej wartości ADC, gdzie problemem jest rzutowanie typów zmiennych w C, co powoduje przepełnienie podczas mnożenia. Podano poprawne sposoby rzutowania na typ unsigned long, aby uniknąć błędów. Dodatkowo poruszono temat wykorzystania zewnętrznej pamięci RAM 62256 z mikrokontrolerem ATMega162 w środowisku AVR-GCC i AVR Studio, gdzie wskazano sposób deklaracji zmiennych w dodatkowej sekcji pamięci (.xram) oraz konfigurację linkera do umieszczenia tej sekcji pod odpowiednim adresem pamięci zewnętrznej.
Wygenerowane przez model językowy.
REKLAMA