Skocz do zawartości

[C] Oprogramowanie PWM - dioda IR 36kHz


wert

Pomocna odpowiedź

Witam.

Od jakiegoś czasu bawię się uC ATMega16. Ostatnio nawet udało mi się uruchomić L293D z PWM. Teraz męczę się z TSOPem. Dowiedziałem się co to są przerwania i na nich oparłem obsługę TSOPa - działa. Gdy naciskam cokolwiek na pilocie, uC zaświeca diodę.

Teraz chciałbym generować przez PWM sygnał na diodę IR, aby TSOP mógł ją zobaczyć po odbiciu od 'przeszkody'.

Dioda IR mruga, ale TSOP niczego nie 'widzi'.

Lubię sam rozwiązywać problemy, dlatego buszuję po forach, kursach, książkach, ale nie umiem sobie już poradzić. Proszę mi podpowiedzieć co robię źle lub czego nie rozumiem.

Rozpiska podłączeń:

PD7 - Dioda IR

PD2 - TSOP

PB1 - Dioda sygnalizująca

Kod programu (w komentarzach mój tok myślenia):

SIGNAL(SIG_INTERRUPT0) { // przerwania dla TSOPa - wlacza diode LED
PORTB |= (1<<PB1);
_delay_ms(100);
PORTB &= ~(1<<PB1);
}

int main(void)
{

DDRD &= (1<<PD2);
PORTD |= (1<<PD2); // TSOP Out

DDRB |= (1<<PB1); // Dioda LED - sygnalizujaca reakcje TSOPa

DDRD |= (1<<PD7); // Dioda IR + R=120Ohm

// Timer2, Fast PWM, preskaler 1
// przy Fckl = 16.000.000Hz daje Fpwm = 62.500Hz,
// czyli aby uzyskac 36kHz musze OCR2 ustawiac na 147
TCCR2 |= (1<<WGM20) | (1<<WGM21) | (1<<COM21) | (1<<CS20);
OCR2 = 0;

// ustawienie przerwania na zbocze opadajace, uruchomienie przerwan
MCUCR &= ~ISC00;
MCUCR |= ISC01;
GICR = (1<<INT0);

_delay_ms(1000);

sei();


while (1) {

	OCR2 = 147;		// uzyskanie 36kHz
	_delay_ms(25);	// wysylanie sygnalu
	OCR2 = 0;		// zakonczenie sygnalu

	_delay_ms(500); // odczekanie do nastepnej iteracji

}	
}

Z góry dziękuję za wszelką pomoc i wskazówki 🙂

Link do komentarza
Share on other sites

Witam.

Przy częstotliwości 62,5 kHz

musiałbyś użyć nie PWM a przerwanie od przepełnienia.

Wtedy co przerwanie to następuje negacja stanu diody.

Link do komentarza
Share on other sites

Po kolei:

"DDRD &= (1<

Jeśli używasz Timer2 (8 bit) to użyj trybu CTC, nie ma innego sposobu na wygenerowanie na nim przebiegu o tej częstotliwości. Ew. korzystać z przerwania, ale to jest kiepski sposób, bo co 222 cykle zegara musiałbyś wywoływać przerwanie.

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

Próbuję zrobić mrugającą diodę wykorzystując CTC Timer1. Oczywiście TSOP dalej nie reaguje. Próbowałem zrobić CTC dla Timera 2, ale też nie wychodziło, dlatego postanowiłem zmienić na 1.

Dioda cały czas świeci (tzn. wg. oka człowieka), więc pewnie mruga, ale nie jest to częstotliwość 36kHz.

Czy dobrze wyliczam OCR1A? (1/36000)/(1/16000000) = 444,444..?

Korzystam z tego kursu: http://www.wkretak.pl/readarticle.php?article_id=3

Oto aktualny kod:

DDRD |= (1<<PD7);

TCCR1B |= (1 << WGM12); // Ustawia timer w tryb CTC
OCR1A = 444; // Ustawia wartość pożądaną na 36Hz dla preskalera 1: (1/36000)/(1/16000000) = 444,444..
TCCR1B |= (1 << CS10); // Ustawia timer z preskalerem Fcpu/1

while (1) {

	if (TIFR & (1 << OCF1A)) {
		PORTD ^= (1 << PD7); // Zmień stan diody LED
		TIFR = (1 << OCF1A); // Wyzerowanie flagi CTC poprzez wpisanie do niej jedynki
	}
}

Co robię źle?

Link do komentarza
Share on other sites

Źle wyliczasz. Wzory masz zdaje sie poprawne w datasheecie. Błędy:

- najpierw uzywasz Timera 2, potem Timera 1, zdecyduj się

- jeśli uzywasz Timera 16b możesz wykorzystać tryb PWM, do wyboru: Fast albo Phase Correct, potrzebne wzory masz w dokumentacji, możesz regulować wypełnienie

- jeśli używasz CTC, musisz użyć trybu w którym przełączasz stan nóżki na zrównaniu, aby wygenerować przebieg 36kHz musisz przełączać 72kHz

Link do komentarza
Share on other sites

Ja to robiłem w BASCOM. Właściwie całość można zwalić na odpowiednio skonfigurowany Timer.

Przynajmniej 90% roboty. 😃 zrobi za nas.

Ja wykorzystywałem 8-bitowy Timer skonfigurowany tak że był generatorem częstotliwości na wyjście OC0A. Tylko pytanie co chcesz nadawać kod np. RC5, czy tylko jakieś paczki impulsów ? No ale w obu przypadkach generowanie jest takie same. Timer się włącza, i/lub wyłącza na odpowiedni czas 2 procedurkami T0_one i T0_zero. W ten sposób uzyskuje się modulacje/kodowanie sygnału.

Fragmencik. Stałe konfiguracji Timera0. Mogę wstawić cały kod z BASCOM do pilota RC5, jak by ci pomogło. Tylko ze program był robiony na Tiny25 taktowany 1,6MHz. Wycinek niżej jest przeliczony dla Megi48/88/168.

Plik definicji stałych systemowych 

'Stałe dla generatora częstotliwosci nośnych 
'Dla preskalera = 0, FCPU = 2MHz 
Const 33k_2m = 30             '33,333Khz 
Const 36k_2m = 28             '35,714Khz 
Const 36k7_2m = 27            '37,037Khz 
Const 38k_2m = 26             '38,461Khz 
Const 40k_2m = 25             '40,000Khz 
Const 56k_2m = 18             '55,555Khz 
'Dla preskaler = 0, FCPU = 4MHz 
Const 33k_4m = 60             '33,333Khz 
Const 36k_4m = 55             '36,363Khz 
Const 36k7_4m = 54            '37,037Khz 
Const 38k_4m = 53             '37,735Khz 
Const 40k_4m = 50             '40,00Khz 
Const 56k_4m = 36             '55,555Khz 
'Dla prescaler = 0, FCPU = 8MHz 
Const 33k_8m = 121            '33,057Khz 
Const 36k_8m = 111            '36,036KHz 
Const 36k7_8m = 109           '36,697Khz 
Const 38k_8m = 105            '38,095Khz 
Const 40k_8m = 100            '40,000Khz 
Const 56k_8m = 71             '56,338Khz 
Link do komentarza
Share on other sites

Postanowiłem na chwilę zmienić na timer1, ponieważ dopiero się uczę, a dla timera1 jest więcej przykładów (np. w kursie, o którym wspomniałem). W późniejszym czasie (czyt. jak będzie poprawnie działało) chcę używać do tego timera2.

Dzięki podpowiedziom udało mi się zrobić coś takiego:


SIGNAL(SIG_INTERRUPT0) { // przerwania dla TSOPa - wypisuje 'H' na LCD
LCD_WriteText("H");
}

ISR(TIMER1_COMPA_vect) {
	PORTD ^= (1 << PD7); // zmiana stanu diody Led
}

int main(void)
{

PORTD |= (1<<PD2); // TSOP Out

PORTD |= (1<<PD0);  // Przycisk czyszczacy LCD

DDRD |= (1<<PD7); // Dioda IR


TCCR1B |= (1 << WGM12);// Ustawia timer w tryb CTC
OCR1A = 222; 			// Ustawia wartość pożądaną na 36Hz dla preskalera 1:
						// (1/36000)/(1/16000000) = 444,444.. / 2 = 222
TCCR1B |= (1 << CS10); // Ustawia timer z preskalerem Fcpu/1
TIMSK |= (1 << OCIE1A);// Obsluga przerwan dla timera


// ustawienie przerwania na zbocze opadajace, uruchomienie przerwan
MCUCR &= ~ISC00;
MCUCR |= ISC01;
GICR = (1<<INT0);

// LCD
LCD_Initalize();
LCD_Clear();

_delay_ms(1000);
sei();


while (1) {

	if (!(PIND & (1<<PD0))) { // button czyszczacy LCD
		LCD_Clear();
	}

	TIMSK |= (1 << OCIE1A); 	// wlacz przerwanie IR
	_delay_us(800);				// DEL1 - pusc sygnal IR 36kHz
	TIMSK &= ~(1 << OCIE1A);	// wylacz przerwanie IR
	_delay_us(10000); 			// DEL2 - odczekaj do nastepnego sygnalu

}

}

TSOP rozpoznaje wiązki od diody IR, ale wydaje mi się, że powinno to działać jakoś inaczej/lepiej. Próbowałem dobrać DEL1 i DEL2 doświadczalnie i na razie to są najmniejsze wartości jakie działają. Może jakiś inny sposób?

Zależy mi zrobić wysyłanie wiązki co jakiś odstęp czasu. Wszystko na potrzeby sprawdzenia czy jest przeszkoda. Nie zależy mi na dekodowaniu RC5.

Link do komentarza
Share on other sites

Tzn. zauważ że nie generujesz dokładnie 36KHz, a TSOP ma pewną tolerancję +/- od tej częstotliwości, ale jeżeli sygnał ma jakąś odchyłkę od tych 36KHz, to jeszcze reaguje, ale jego czułość jest też mniejsza. No i są zasadniczo na rynku 2 typy diod nadawczych IR (chyba 880nm i 940nm ale nie pamiętam dokładnie), o różnych długościach fali nadawanej co też będzie miało pewne znaczenie, bo TSOP tez ma pewną określoną długość fali dla której ma max. czułość.

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