Skocz do zawartości

Używanie ADC na ATtiny85


Pomocna odpowiedź

Napisano

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?

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; // 🙂

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.

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.

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

To czego mam używać? Datasheet twierdzi, że SBI też ma ten problem.

deshipu, a jaką masz częstotliwość CPU? Bo zalecane f_ADC to 50 - 200 kHz, czyli w Twoim przypadku f_CPU powinno się mieścić w przedziale: 6.4 - 25.6 MHz

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.

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).

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...