Skocz do zawartości

PWM w Atmega328p timer counter0


choco_amore

Pomocna odpowiedź

Cześć Wszystkim! Mam problem związany z wykorzystaniem 8 bitowego timer/counter0 w mojej płytce Arduino UNO. Programuję w czystym C z wykorzystaniem Visual Studio Code. Założeniem programu jest odczyt wartości napięcia z pinu A0, a następnie regulacja wypełnienia sygnału PWM na podstawie wartości tego napięcia.

Program zrealizowałem w następujący sposób:

Konfiguracja sygnału PWM na pinach PD5 i PD6(odpowiednio OC0B i OC0A). Tryb FAST PWM, preskaler 1024, ustawianie pinów w momencie zgodności licznika timera z OCR0A i OCR0B, zerowanie przy wartości maksymalnej licznika.

Konfiguracja ADC.

W nieskończonej pętli while przypisywanie wartości z ADC dla rejestrów OCR0A i OCR0B na podstawie czego jest ustawiane wypełnienie na wyjściach OC0A i OC0B.

 

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

//definicja funkcji przetwornika ADC i pinu wejsciowego
#define ADC_PIN			0
uint16_t adc_read(uint8_t adcx);

int main(void)
{
    // ustawiamy PD5 i PD6 jako wyjścia
    DDRD  = 0b111111;

    // ustawiamy tryb PWM 3
    // wyjście PD5 pracuje w trybie normalnym
    // wyjście PD6 pracuje w trybie normalnym
    TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(1<<COM0B1)|(0<<COM0B0)|(1<<WGM02)|(1<<WGM01)|(1<<WGM00);
    
	// Ustawiamy rejestry porównań
    OCR0A = 1;
	OCR0B = 1;

	//ustawienie prescalera
    TCCR0B = (1<<CS02)|(0<<CS01)|(1<<CS00);

	//uruchomienie ADC
  	ADCSRA |= (0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN); 

    while (1)
    {
	// przypisanie wartosci rejestru OCRnX wartosci napiecia z ADC
	_delay_ms(10);
	OCR0A = adc_read(ADC_PIN)/4;
	OCR0B = adc_read(ADC_PIN)/4;
    }
}


uint16_t adc_read(uint8_t adcx) {

	//wybor pinu wejscia
	ADMUX	=	0b01000000;
	ADMUX	|=	adcx;

	//uruchomienie konwersji 
	ADCSRA |= _BV(ADSC);

	//petla do oczekiwania na koniec konwersji, bit ADCSRA jest zerowany na koniec konwersji
	while ( (ADCSRA & _BV(ADSC)) );
	//zwracanie wartosci konwersji
	return ADC;
}

W przypadku pinu PD5 układ działa zgodnie oczekiwaniami. Przy zmniejszaniu napięcia na wejściu ADC LED gaśnie, przy zwiększeniu napięcia LED świeci mocniej.

Problem pojawia się dla PD6. LED nie świeci.

 

Piny mają identyczną konfiguracje, natomiast działają inaczej. W czym może być problem? Dokumentację techniczną przejrzałem 10 razy i nie mogłem znaleźć żadnej informacji co może wywoływać taki stan.

Link do komentarza
Share on other sites

W tym trybie OCR0A używany jest zdaje się jako TOP czyli maksymalna wartość licznika. Spróbuj `(0<<WGM02)|(1<<WGM01)|(1<<WGM00);` bo wtedy TOP jest na stałe 0xFF i powinno działać jak chcesz. Nawiasem mówiąc dziwne że cokolwiek działa.

  • Lubię! 1
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

Czekaj czekaj...a w tym trybie nie wykorzystujesz przypadkiem obu rejestrow (OCRA/OCRB) do generowania czestotliwosci i wypelnienia?? OCRA=czestotliwosc, OCRB=wypelnienie? 

(Ok pomylka...teraz zauwazylem ze uzywasz 3 trybu)

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

No i mialem racje...uzywasz trybu 7! A nie 3...w tym trybie pin A nie jest uzywany bo jego rejestr jest zarezerwowany dla czestotliwosci (chyba)...

Cytat..."W trybach, w których TOP jest definiowany przez rejestr, taki jak OCR1A, służy on do regulacji CZĘSTOTLIWOŚCI PWM. W innych trybach (stałe wartości TOP) częstotliwość jest stała, ale można użyć dwóch kanałów wyjściowych i ustawić dwa cykle pracy na kanałach A i B. Ale w trybie, w którym OCR1A jest na górze, kanał A nie jest już używany jako PWM wyjście. Jedynym zastosowaniem OCR1A jest regulacja częstotliwości. "

WGM0x.thumb.jpg.15f42e23c5dbbbdd99e1543223281702.jpgzobacz sobie na bity...zwlaszcza na WGM02...

Reansumujac wpisz tam zero i powinno zadzialac..

Link do komentarza
Share on other sites

(edytowany)

Drodzy Koledzy, udało mi się dojść do rozwiązania problemu. Zarówno w trybie 3 i 7 PWM problem wyglądał podobnie. Rozwiązaniem problemu okazał się sposób ustawiania bitów. W pierwszym sposobie nie ustawiłem wyjścia nr 6, bo dałem za małą liczbę.... Bardzo głupi błąd.

Było:

    DDRD  = 0b111111;
...
  
ADMUX	=	0b01000000;
	ADMUX	|=	adcx;

Jest:

    DDRD |= (1<<DDD5)|(1<<DDD6);
...
  	//wybor pinu wejscia
	ADMUX	|=	(1<<REFS0) | (0<<MUX0);
	ADMUX	|=	adcx;

 

Dziękuję wszystkim za chęć pomocy, pozdrawiam. 🙂

Edytowano przez choco_amore
Link do komentarza
Share on other sites

Ustawiając jakiekolwiek bity polecam używać przesunięć bitowych, zamiast 0b01101101 czy 0x7D. Łatwo o pomyłkę, a i czytelność kodu jest mniejsza. Wiadomo, jakbyś chciał na caly rejestr wystawić jedynki to szybciej będzie napisać 0xFF, ale przy pojedynczych lepiej to robić czytelniej. 

A w twoim pierwszym kodzie jest cały mix 🙃 nawet znalazło się makro _BV

Nie jest to jakiś błąd, wszystko ma prawo działać, tylko osobiście myślę że styl programowania powinien być w miarę uporządkowany. 

Edytowano przez Krawi92
  • Lubię! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

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