Skocz do zawartości

Używanie ADC na ATtiny85


deshipu

Pomocna odpowiedź

Muszę przyznać, że trochę utknąłem. Przeczytałem już datasheet 4 razy, porównałem swój kod z przykładami w Internecie i nadal nie mogę zrozumieć co jest nie tak. Może ktoś z was ma z tym jakieś doświadczenie albo zauważy oczywisty błąd. Zatem do rzeczy.

Próbuję odczytać przy pomocy ADC na ATtiny85 wartość z nóżki ADC3 (czyli przypadkiem akurat PB3). Niestety, wydaje się, że odczyt jest robiony tylko raz (o ile jest robiony) i cały czas dostaję tę samą wartość w okolicach 512, inną po każdym restarcie, niezależną od tego czy nóżka sobie wisi, jest podpięta do masy czy do zasilania.

Mój kod wygląda obecnie tak:

#include <util/delay.h>
#include <avr/io.h>

void TxByte(char);

void uart(const char* str) {
  while (*str)TxByte(*str++);
}

uint16_t adc() {
   ADCSRA |= 1<<ADSC;
   while (ADCSRA & (1<<ADSC));
   return ADCH<<8 | ADCL;
}

int main() {
   char buf[100] = {};
   // Init ADC.
   ADMUX = 1<<MUX1 | 1<<MUX0; // pin ADC3
   DIDR0 |= 1<<ADC3D; // disable PB3
   ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1 | 1<<ADPS0; // /128 prescaler

   while (1) {
       itoa(adc(), buf, 10);
       uart(buf);
       uart("\r\n");
       _delay_ms(200);
   }
}

Uprościłem go ile się dało. Używam seriala z http://nerdralph.blogspot.ch/2013/12/writing-avr-assembler-code-with-arduino.html więc żeby to skompilować, trzeba dodać ten plik assemblerowy. Ale to nie powinno mieć znaczenia.

Jakiekolwiek pomysły?

Link do komentarza
Share on other sites

Ten ADC nie odda nowego wyniku dopóki nie skasujesz flagi ADIF. Normalnie robi to sprzęt po wejściu do obsługi przerwania, ale jeśli obsługujesz ADC "ręcznie" to musisz po odczycie wyniku wpisać 1 do bitu ADIF (co go kasuje). Jeśli robię pooling czekam właśnie na zapalenie ADIF a nie na koniec ADSC.

Acha, nie musisz kombinować z przesuwaniem przy odczytach bo to jest groźne. Biblioteka ma wbudowane operacje (makra) na rejestrach 16-bitowych, które nota bene robią to w odpowiedniej kolejności, bo to nie jest dowolne:

uint16_t wynik = ADC; // 🙂

Link do komentarza
Share on other sites

No właśnie jeden problem znalazłem -- czytanie ADCL musi być przed ADCH. Po poprawieniu tego zacząłem dostawać różne odczyty -- niestety nieskorelowane z pinem ADC3, tylko takie bardziej sobie losowo falujące. Spróbuję wyczyścić flagę ADIF, choć przerwań nie mam włączonych.

Link do komentarza
Share on other sites

Być może opadnięcie ADSC oznacza jedynie koniec konwersji. Za to ustawienie ADIF oznacza na pewno koniec konwersji i uaktualnienie rejestrów wyjściowych. To nie musi być ten sam moment w czasie z dokładnością do taktu zegara więc możesz czytać jakieś śmiecie.

Czekaj na ADIF i kasuj go. I nie używaj operacji read-modify-write (np. ADSRA |= cośtam) bo to niechcący niszczy takie bity kasowane przez zapis jedynki.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dobra, rozwiązane, bardzo dziękuję za pomoc.

Problemy były dwa. Pierwszy, to odczytywanie ADCL i ADCH w odwrotnej kolejności, co powodowało, że się zapadka na nich nie zwalniała. Drugi, to biedny ATtiny85 którego mam do tych eksperymentów wlutowanego w płytkę z nóżkami, dla wygody, i którego używam już od 2 lat do różnych dziwnych rzeczy. Najprawdopodobniej uszkodziłem mu w pewnym momencie w jakiś sposób ADC. Ten sam program wgrany na inny chip działa bez problemów.

Link do komentarza
Share on other sites

Czyli raczej pin, bo samego ADC w środku trudno popsuć. Hm, może jakoś przez VREF?

Spróbuj na innym pinie - tak z ciekawości 🙂

Wojciech: ten zakres musisz spełnić gdy chcesz uzyskać parametry ADC podawane przez producenta. Zupełnie spokojnie możesz ADC puścić na 1MHz - dostaniesz wtedy może 7-8 bitów znaczących a reszta to śmieci. Za to masz wtedy ponad 70ksps 🙂

W drugą stronę (przy mniejszych częstotliwościach taktowania niż 50kHz) błędy mogą być bardziej subtelne i trudniejsze do korekcji, bo część toru analogowego opiera się na pojemnościach a te nie mogą ładunku utrzymywać zbyt długo z uwagi na upływności. Na szczęście ATMEL musi gwarantować działanie w całym zakresie temperatur a technologia łamie się najbardziej przy wysokich. Dlatego w normalnych warunkach ADC będzie działał nawet przy taktowaniu procka z zegarkowego kwarcu 32kHz (próbowałem).

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.