Witam,
Coś ostatnio mało ludzi odpowiada mi na pytania w Bascomie, więc postarałem się napisać swój program w C. Liczę więc na pomoc specjalistów od GCC
chciałbym zrobić pilot IR do mojego aparatu fotograficznego Olympus. Ze stronki lirc sprawdziłem sobie co i jak ma być dla pilota RM-1. Powiem nawet że chyba rok temu zrobiłem to w assemblerze i działało, a teraz robię to (najpierw w Bascomie) w GCC i pomimo to, że na oscylu widać niby ładny przebieg to aparat ani drgnie.
oto dane z lirca:
oto mój schemat pilocika na ATTiny2313:
a poniżej moje jedne z pierwszych poważniejszych (jak dla mnie wypocin w C):
założenie mojego programu jest takie:
1. Timer0 - generuje mi nośną 38kHz (działa b.ładnie)
2. Timer1 - przerwanie od COMPARE1A ma kluczować nośną
bitów do wysłania mamy łącznie 64, bo jest ich 16 pre_data oraz 16 polecenie.
W związku z tym po wystartowaniu Timera1 po wciśnięciu klawisza1 , najpierw ładuję do OCR1A wartość przepełnienia dla otrzymania czasu _header1 (8853us) (wartości dla _header1, _header2, _state, _high, _low są ślicznie poobliczane)
gdy nastąpi przepełnienie to mamy przerwanko i musi ono wystąpić 66 razy, ponieważ jest do wysłania: 1 impuls _header2, 64 impulsy dla bitów pre_data i danych, 1 impuls ptrail.
jak widać w przerwaniu licznik impulsów ir_count jest zmniejszany i w zależności od jego wartości w przerwaniu następuje załadowanie odpowiedniej wartości do rejestru COMPARE1A aby regulować odpowiednie czasy.
i tak po wejściu w przerwanie (wyemitowanie nośnej w czasie _header1) najpierw przy wartosci ir_count = 66 nastąpi wyłączenie nośnej i odczekanie czasu _header2
potem w kolejnych krokach lecą nam bity 0 lub 1. Każdy bit najpierw włącza nośną na czas umownie nazwany _state (559us) a następnie w kolejnym przerwaniu wyłącza nośną na czas _high gdy bit = 1 lub na czas _low gdy bit = 0
poniżej obrazek z oscyla - widać wręcz ślicznie bity z tablicy pre_data, _header2 itp:
a tu już sobie dokładnie liczyłem bo mi się w oczach mieszało:
.... no i na koniec, czy chciało by się komuś jakoś to przeanalizować co narobiłem i może jakiś pomysł podsunąć gdzie coś mogę robić źle? albo może jak zoptymalizować kod - bo chyba tak troszkę na zywca ze składni Bascoma to przeniosłem i podejrzewam, że można to poskracać jakoś.
Może przerwanie za długo się wykonuje, ale z drugiej strony Timer1 cały czas tyka i podejrzewam, że najdłuższa operacja w przerwaniu robi się krócej niż czas potrzebny do kolejnego przeładowania po zaktualizowaniu OCR1A ...
Dodano po 16 [minuty]:
aha - dodam, że sprawdzałem też przebieg na wyjściu odbiornika podczerwieni TSOP żeby sprawdzić czy dobrze filtruje nośną - i na oscylu jest także ładny przebieg tyle że odwrócony (tak jak powinno być)
hmmm jaki więc błąd mogę popełniać - widzi może ktoś? coś?
Coś ostatnio mało ludzi odpowiada mi na pytania w Bascomie, więc postarałem się napisać swój program w C. Liczę więc na pomoc specjalistów od GCC

chciałbym zrobić pilot IR do mojego aparatu fotograficznego Olympus. Ze stronki lirc sprawdziłem sobie co i jak ma być dla pilota RM-1. Powiem nawet że chyba rok temu zrobiłem to w assemblerze i działało, a teraz robię to (najpierw w Bascomie) w GCC i pomimo to, że na oscylu widać niby ładny przebieg to aparat ani drgnie.
oto dane z lirca:
Quote:name Olympus_RM-1
bits 16
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100
header 8853 4489
one 559 1670
zero 559 555
ptrail 559
repeat 8853 2259
pre_data_bits 16
pre_data 0x61DC
gap 107013
toggle_bit 0
begin codes
capture 0x000000000000807F
w 0x00000000000040BF
t 0x000000000000C03F
- 0x00000000000020DF
+ 0x000000000000A05F
end codes
oto mój schemat pilocika na ATTiny2313:
![[AVR][C] - pilot IR Olympus [AVR][C] - pilot IR Olympus](https://obrazki.elektroda.pl/70_1223543347_thumb.jpg)
a poniżej moje jedne z pierwszych poważniejszych (jak dla mnie wypocin w C):
Code:
#include <avr/io.h>
#include <avr\interrupt.h>
#include <inttypes.h>
#include <util/delay.h>
#include "makra.h"
#define led_off PORTB |= (1<<0);
#define led_on PORTB &= ~(1<<0);
#define _header1 35413
#define _header2 17956
#define _state 2234
#define _high 6679
#define _low 2218
#define _repeat = 9028
void delayms(uint16_t del)
{
uint16_t i;
for(i=0; i<del; i++) _delay_ms(1);
}
void timer1_start()
{
TCNT1 = 0;
TCCR1B |= (1<<CS10);
}
void timer1_stop()
{
TCCR1B &= ~(1<<CS10);
}
void nosna_on()
{
TCNT0 = 0;
TCCR0A |= (1<<COM0A0);
TCCR0B |= (1<<CS00);
}
void nosna_off()
{
TCCR0A &= ~(1<<COM0A0);
TCCR0B &= ~(1<<CS00);
}
// tablica danych dla polecenia CAPTURE (0x807F)
// łącznie z bitami poprzedzającymi pre_data (0x61DC)
uint8_t pre_data[32] = {
0 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 0 ,
1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1
};
// tu zmienne zdeklarowałem jako volatile bo używane są w przerwaniu
volatile uint8_t ir_count;
volatile uint8_t nr;
volatile uint8_t tab_cnt;
int main(void)
{
// ustawienie PORTB.0 i PORTB.2 jako wyjścia
DDRB |= (1<<0|1<<2);
PORTB |= (1<<0|1<<2);
// ustawienie PORTD.2 , 3 , 4 i 5 jako wejścia
DDRD &= ~(1<<2|1<<3|1<<4|1<<5);
// podciągnięcie wejść do 1
PORTD |= (1<<2|1<<3|1<<4|1<<5);
// ustawienia dla Timer0 (tryb CTC)
OCR0A = 104; // prametr dla uzyskania częstotliwości nośnej 38kHz
TCCR0A &= ~(1<<WGM00);
TCCR0A |= (1<<WGM01);
TCCR0B &= ~(1<<WGM02);
// ustawienia dla Timer1 (tryb CTC)
TCCR1A &= ~(1<<WGM10|1<<WGM11);
TCCR1B |= (1<<WGM12);
TCCR1B &= ~(1<<WGM13);
// zezwolenie na przerwania od Compare1A
TIMSK |= (1<<OCIE1A);
// globalne zezwolenie na przerwania
sei();
while (1)
{
// KLAWISZ 1
if ((PIND&0b00000100) == 0)
{
delayms(100);
if ((PIND&0b00000100) == 0)
{
ir_count = 66;
tab_cnt = 0;
nr = 0;
OCR1A = _header1;
TCNT1 = 0;
nosna_on();
timer1_start();
}
}
// KLAWISZ 2
if ((PIND&0b00001000) == 0)
{
delayms(100);
if ((PIND&0b00001000) == 0)
{
led_on;
}
}
// KLAWISZ 3
if ((PIND&0b00010000) == 0)
{
delayms(100);
if ((PIND&0b00010000) == 0)
{
led_off;
}
}
}
return 0;
}
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
volatile uint8_t mbyte;
if (ir_count == 0)
{
nosna_off();
timer1_stop();
}
else if (ir_count == 66)
{
nosna_off();
OCR1A = _header2;
}
else if (ir_count > 1)
{
if (nr == 0)
{
nosna_on();
OCR1A = _state;
}
else
{
nosna_off();
mbyte = pre_data[tab_cnt];
tab_cnt++;
if (mbyte == 1)
{
OCR1A = _high;
}
else
{
OCR1A = _low;
}
}
nr++;
if (nr > 1) {nr = 0;}
}
else if (ir_count == 1)
{
nosna_on();
OCR1A = _state;
}
ir_count--;
}
założenie mojego programu jest takie:
1. Timer0 - generuje mi nośną 38kHz (działa b.ładnie)
2. Timer1 - przerwanie od COMPARE1A ma kluczować nośną
bitów do wysłania mamy łącznie 64, bo jest ich 16 pre_data oraz 16 polecenie.
W związku z tym po wystartowaniu Timera1 po wciśnięciu klawisza1 , najpierw ładuję do OCR1A wartość przepełnienia dla otrzymania czasu _header1 (8853us) (wartości dla _header1, _header2, _state, _high, _low są ślicznie poobliczane)
gdy nastąpi przepełnienie to mamy przerwanko i musi ono wystąpić 66 razy, ponieważ jest do wysłania: 1 impuls _header2, 64 impulsy dla bitów pre_data i danych, 1 impuls ptrail.
jak widać w przerwaniu licznik impulsów ir_count jest zmniejszany i w zależności od jego wartości w przerwaniu następuje załadowanie odpowiedniej wartości do rejestru COMPARE1A aby regulować odpowiednie czasy.
i tak po wejściu w przerwanie (wyemitowanie nośnej w czasie _header1) najpierw przy wartosci ir_count = 66 nastąpi wyłączenie nośnej i odczekanie czasu _header2
potem w kolejnych krokach lecą nam bity 0 lub 1. Każdy bit najpierw włącza nośną na czas umownie nazwany _state (559us) a następnie w kolejnym przerwaniu wyłącza nośną na czas _high gdy bit = 1 lub na czas _low gdy bit = 0
poniżej obrazek z oscyla - widać wręcz ślicznie bity z tablicy pre_data, _header2 itp:
![[AVR][C] - pilot IR Olympus [AVR][C] - pilot IR Olympus](https://obrazki.elektroda.pl/86_1223546116_thumb.jpg)
a tu już sobie dokładnie liczyłem bo mi się w oczach mieszało:
![[AVR][C] - pilot IR Olympus [AVR][C] - pilot IR Olympus](https://obrazki.elektroda.pl/16_1223546183_thumb.jpg)
.... no i na koniec, czy chciało by się komuś jakoś to przeanalizować co narobiłem i może jakiś pomysł podsunąć gdzie coś mogę robić źle? albo może jak zoptymalizować kod - bo chyba tak troszkę na zywca ze składni Bascoma to przeniosłem i podejrzewam, że można to poskracać jakoś.
Może przerwanie za długo się wykonuje, ale z drugiej strony Timer1 cały czas tyka i podejrzewam, że najdłuższa operacja w przerwaniu robi się krócej niż czas potrzebny do kolejnego przeładowania po zaktualizowaniu OCR1A ...
Dodano po 16 [minuty]:
aha - dodam, że sprawdzałem też przebieg na wyjściu odbiornika podczerwieni TSOP żeby sprawdzić czy dobrze filtruje nośną - i na oscylu jest także ładny przebieg tyle że odwrócony (tak jak powinno być)
hmmm jaki więc błąd mogę popełniać - widzi może ktoś? coś?