Skocz do zawartości

Arduino i timery - problem ze zrozumieniem preskalerów


farmaceuta

Pomocna odpowiedź

1 minutę temu, _LM_ napisał:

Wynikiem powinno być na przemian wartość o 1 większa lub mniejsza od OCR inaczej nie miałoby to szans na działanie 

i czaly czas wlasnie o to mi chodzilo...tego nie rozumialem jakie wartosci ma ten TCNT a raczej na jakiej zasadzie jest to obslugiwane ze raz jest mniejszy a raz wiekszy...

 

8 minut temu, _LM_ napisał:

Jeśli chcesz programowo przejąć i odczytać wartość TCNT to najlepiej zrobić to za pomocą dodatkowej zmiennej ze spscyfikatorem register następnie do niej wpisać wartość TCNT a dopiero w pętli głównej wysłać na serial. Przykładu już nie podam bo kompa wyłączyłem. Ale z grubsza powinno to wyglądać tak:


register uint8_t tcntx;

 

o widzisz...nawet nie wiedzialem ze cos takiego jest...ponowne dzieki😉

Dobra...dzis Cie juz psychicznie wykonczylem (i siebie tez) za to sorki😁 dzieki wielkie za pomoc😁

Link do komentarza
Share on other sites

Nie chodzi o to w którą stronę liczy. Chodzi o wartość bezwzględną, pisałem trochę wcześniej żebyś zobaczył do noty tam jest pokazane że w całym procesie pośredniczy dodatkowy moduł - komparator cyfrowy. Tu niema żadnej magii. Cały ten proces dzieje się w tle na poziomie sprzętowym 

 

Link do komentarza
Share on other sites

1 minutę temu, farmaceuta napisał:

Dobra...dzis Cie juz psychicznie wykonczylem (i siebie tez) za to sorki😁 dzieki wielkie za pomoc😁

Spoko ja i tak do rana muszę być na chodzie także luz. Przeczytaj sobie to co pisałem o działaniu tego systemu (ja wiem że pokrętnie i na skróty) prześpij się z tym i jutro już będziesz miał odpowiedzi

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

16 minut temu, farmaceuta napisał:

czaly czas wlasnie o to mi chodzilo...tego nie rozumialem jakie wartosci ma ten TCNT a raczej na jakiej zasadzie jest to obslugiwane ze raz jest mniejszy a raz wiekszy...

W sumie to dostałeś odpowiedź jakiej oczekiwałeś a niekoniecznie zgodnej z prawdą 😓 faktycznie dzisiaj już za późno na takie dysputy. Postaram się jutro bardziej przygotować i odpowiedzieć rzetelnie 

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

(edytowany)

teraz mam ciekawy problem...nie moge zmienic OCRx wiecej ni raz...

ISR(TIMER2_COMPA_vect){


if(OCR2A > TCNT2){
    PORTB|=(1<<PB5);
      Serial.println(TCNT2);
  }else{
    PORTB&=~(1<<PB5); 
    Serial.println(TCNT2);

  }

OCR2A = OCR2A + 1;

  }

ostatnia linijka wykona sie tylko raz....

void loop() {
  // put your main code here, to run repeatedly:
OCR2A += 5;
delay(1000);

}

i tutaj tez tylko raz....

ale jaja...a to ponizej wogole sie nie wykona..

if (millis() - last > 1000UL)  {
  last = millis();
  OCR2A += 5;
Serial.println("ddd");

}

 

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

a millis nie korzysta czasem z timera2? co do wcześniejszych przykładów z delay to niemam pojęcia czemu nie działa. Sprawdź jeszcze ten kod gdzie zmiana następuje w przerwaniu. Ja go testowałem i było OK. Aha i wywal te printy z obsługi przerwań

Edytowano przez _LM_
Link do komentarza
Share on other sites

Przed chwilą, _LM_ napisał:

a millis nie korzysta czasem z timera2? co do wcześniejszych przykładów z delay to niemam pojęcia czemu nie działa. Sprawdź jeszcze ten kod gdzie zmiana następuje w przerwaniu. Ja go testowałem i było OK

z tego co mi wiadomo to delaje i inne to timer0...zreszta z wczesniejszych bojow w tym watku z timerami robilem sobie pseudo pwm w trybie CTC i wszystko dzialalo...delaje/seriale.

sprawdzalem w przerwaniu i dodanie o 1 wystapi tylko raz...pozniej jest pomijane...widac to i na serialu i na diodzie (stala jasnosc)...

Link do komentarza
Share on other sites

jezeli mozesz sprawdz  u siebie czy jasnosc diody bedzie sie zmieniac

#include <avr/io.h>
#include <avr/interrupt.h>
long last = 0;

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
DDRB|=(1<<PB5);

//TCCR2A |=(1<<WGM21); // CTC
TCCR2A |=(1<<WGM22)|(1<<WGM20);
TCCR2B |=(1 << CS20)|(1<<CS21);//|(1<<CS22); // Prescaler 1024
TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A)|(1<<TOIE2); // przerwania

OCR2A = 1; // co ile?



sei();

}

void loop() {

}


ISR(TIMER2_COMPA_vect){


if(OCR2A > TCNT2){
    PORTB|=(1<<PB5);
     // Serial.println(TCNT2);
  }else{
    PORTB&=~(1<<PB5); 
  //  Serial.println(TCNT2);

  }

OCR2A = OCR2A + 1;

  }

 

Link do komentarza
Share on other sites

(edytowany)
10 minut temu, _LM_ napisał:

No faktycznie to nie działa dla tego rejestru, muszę w pdf doczytać dlaczego

No widzisz jakie jaja?...malo tego jesli w loop() bede chcial inkrementowac to uda sie to ale tylko wtedy jesli nie bedzie zadnych delaji itp...lub jesli delay nie bedzie za dlugi...np. delay(1) zdazy doliczyc do?....18? I tyle....a micros(100) doliczy do okolo 160....nic nie kapuje...a na zrozumienie dokumentacji to za cienki jestem...🤕

void loop() {
OCR2A = OCR2A + 1;
 delay(1);   ///ocr = 18
 delayMicroseconds(100);   ///ocr = 160
}

 

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

Tj na pewno był błąd przy ustawianiu bitów WGM ponieważ WGM20 i 21 leżą w rejestrze TCCR2A natomiast WGM22 leży w rejestrze B. Taki urok AVRów. Jednak poprawki nie dają spodziewanych efektów 😕

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

Dobra, mam. Kluczem było przestawienie trybu pwm. Wypróbuj ten kod.

TCCR2A |=(1<<WGM20);
TCCR2B |=(1 << CS20)|(1<<CS21);//|(1<<CS22); // Prescaler 1024
TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A)|(1<<TOIE2); // przerwania

for(;;){
	_delay_ms(20);


	OCR2A++;
//	OCR2B++;
}
}

ISR(TIMER2_COMPA_vect){


if(OCR2A > TCNT2){
    PORTB|=(1<<PB5);
     // Serial.println(TCNT2);
  }else{
    PORTB&=~(1<<PB5);
  //  Serial.println(TCNT2);

  }
}

ISR(TIMER2_OVF_vect) {

}

Druga rzecz: jeśli w 

TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A)|(1<<TOIE2); // przerwania

jest odblokowane przerwanie od przepełnienia to musi być napisana jego obsługa choćby w postaci pustej funkcji

  • Pomogłeś! 1
Link do komentarza
Share on other sites

10 minut temu, _LM_ napisał:

 Kluczem było przestawienie trybu pwm

Juz miedzy czasie sprawdzilem bez efektu...

 

11 minut temu, _LM_ napisał:

 

jest odblokowane przerwanie od przepełnienia to musi być napisana jego obsługa choćby w postaci pustej funkcji

juz nawet calkiem je wywalilem..

kod ktory podales nie dziala u mnie...

#include <avr/io.h>
#include <avr/interrupt.h>
long last = 0;

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
DDRB|=(1<<PB5);
TCCR2A = 0;
TCCR2B = 0;
TCCR2A |=(1<<WGM20);
TCCR2B |=(1 << CS20)|(1<<CS21);//|(1<<CS22); // Prescaler 1024
TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A); // przerwania


OCR2A = 1; // co ile?



sei();

}

void loop() {
OCR2A = OCR2A + 1;
delay(20);
  //  PORTB^=(1<<PB5);

}

ISR(TIMER2_COMPA_vect){


if(OCR2A > TCNT2){
    PORTB|=(1<<PB5);
      Serial.println(TCNT2);
  }else{
    PORTB&=~(1<<PB5);
    Serial.println(TCNT2);

  }
}

 

Link do komentarza
Share on other sites

15 minut temu, _LM_ napisał:

 

Druga rzecz: jeśli w 


TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A)|(1<<TOIE2); // przerwania

jest odblokowane przerwanie od przepełnienia to musi być napisana jego obsługa choćby w postaci pustej funkcji

.....dziala!!..jak napisales o tych przerwaniach to usunalem jeszcze OCIE2B z rejestru i zaczelo hulac....

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

Noooo właśnie miałem to pisać, tylko jest pewna ciekawostka: Jak masz uruchomione oba pwmy to działają wolniej ale czemu to już nie wiem. Sprawdź jeszcze takie coś:

volatile uint8_t tcntVal;
volatile uint8_t tcntFlag;

for(;;){
	_delay_ms(20);
	OCR2A++;
	if(tcntFlag){
		 Serial.println(tcntVal);
		 tcntFlag = 0;
	}
	}
}

ISR(TIMER2_COMPA_vect){
if(OCR2A > TCNT2){
    PORTB|=(1<<PB5);
     tcntVal = TCNT2;
}else{
    PORTB&=~(1<<PB5);
     tcntVal = TCNT2;
  }
tcntFlag = 1;
}

EDIT: tcntVal można też aktualizować poza ifami

Edytowano przez _LM_
  • Pomogłeś! 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.