Witaj,
Czytając temat postanowiłem pomóc, jakiś czas temu poskładałem mały migacz LED do drona/samolotu, na własne potrzeby.
Pomiaru impulsu PWM z kanału odbiornika dokonuje w przerwaniu. Pomiar bardzo dokładny. Instrukcje w pętli głównej nie wpływają na odczytane wartości.
Różnice pomiaru długości miałem rzędu 1-3 taktów zegara. Co w zupełności było wystarczające do moich potrzeb.
W twoim programie marnujesz dużo czasu na dokonanie pomiarów. Dokładając dodatkowe funkcje/instrukcje w pętli głównej prawdopodobnie pominiesz zmianę wartości kanału długości impulsu PWM.
Poniżej wstawka moich skromnych poczynań - nie jestem zawodowym programistą, więc może lepiej można by to napisać.
Ustawienia rejestrów EICRA itp. są dla płytki Arduino Nano v3 z procesorem ATMega328
Program był pisany w środowisku: WinAvr, później Atmel Studio 7.0 - w obu działało tak jak powinno
Wzorując się na poniższym kodzie dasz radę "przetłumaczyć" to na Arduino
Życzę powodzenia
Kod: Zaznacz cały
// nadanie nazw prostych do funkcji np zatrzymanie timera, zmiana zbocza niskie/wysokie
// Definicja zbocz dla przerwania INT0
#define INT0_zbocze_narastajace EICRA = 0x03 //(1 << ISC00 |1 << ISC01)
#define INT0_zbocze_opadajace EICRA = 0x02 //(1 << ISC01)
#define INT0_stan_niski EICRA = 0x00
#define INT0_enable EIMSK = 1
#define INT0_disable EIMSK = 0
#define TIMER1_start TCCR1B = 3 //fcpu 1/1; 2/8; 3/64; 4/256; 5/1024
#define TIMER1_stop TCCR1B = 0
volatile uint8_t zbocze_INT = 0, wartosc_PWM = 0;
volatile uint8_t flaga_przerwania = 0; //0 - zbocze narastajace, 1 - zbocze opadajace, 2 - wylaczenie
volatile uint16_t dlugosc_impulsu = 0;
volatile uint8_t offset_do_tabeli = 0, pwm_petla = 0, pwm_timer = 0, max_pwm_timer = 0;
#define komp_3_6_pozycje 0 // 0 - kompilacja dla 3 pozycji, 1 kompilacja dla 6 pozycji
// W pętli głównej porównuje długość impulsu z kanału PWM z tym co jest poniżej i wykonywałem jakąś akcje
#if komp_3_6_pozycje == 0 // tutaj sa zmierzone granice dla przelacznika 3 pozycyjnego
// 247 375 503
#define pos_1 247
#define pos_2 375
#define pos_3 503
#define dead_band 30
#endif
#if komp_3_6_pozycje == 1 // tutaj dla 6-cio pozycyjnego
#define pos_1 248
#define pos_2 298
#define pos_3 348
#define pos_4 400
#define pos_5 452
#define pos_6 503
#define dead_band 8
#endif
/*
0 - 248
1 - 298
2 - 348
3 - 400
4 - 452
5 - 503
*/
// Timer 0 - 8bit, generuje sygnal pwm na zadanych pinach
// Timer 1 - 16bit, zlicza dlugosc impulsu
// Timer 2 - 8bit, szybkosc zmiany odczytu z tabelek
// INT0 - reaguje na narastajace zbocze, wlacza timer 1, zmiana na opadajace zbocze, wylacza timer 1, zmiana na wysokie zbocze
// Obsluga przerwania na ktorym wisi kanal RC
// najpierw pojawienie stanu narastajacego zwieksza flaga przerwania na 1
// jesli flaga = 1 -> startuje timer do pomiaru dlugosci impulsu
// zmiana reakcji na opadajace zbocze
// kolejne wejscie zwieksza flage
// jesli flaga = 2, wtedy zatrzymujemy timer, przepisujemy wartosc licznika - dl. impulsu
// zerujemy licznik timera
// zmieniam czulosc na zbocze narastaace
ISR(INT0_vect)
{
flaga_przerwania++;
if(flaga_przerwania == 1)
{ TIMER1_start; INT0_zbocze_opadajace;}// start TIMER1 aby zliczał takty zegarowe, zmiana na jakie zbocze ma reagowac przerwanie
if(flaga_przerwania == 2)
{ TIMER1_stop; // zatrzymanie zliczania dlugosci impulsu
flaga_przerwania = 0; // wyzerowanie zmiennej pomocniczej
dlugosc_impulsu = TCNT1; // przepisanie ilosci zliczonych taktow zegara do zmiennej
TCNT1 = 0; // wyzerowanie licznika impulsow
INT0_zbocze_narastajace; // zmiana reakcji przerwania na zbocze narastajace
// uart_dec(dlugosc_impulsu,1); // tutaj wysylalem do portu szerogowego to co sie zliczylo
}
}
// konfiguracja timera i przerwania zewnętrznego
// Ustawienie przerwania INT0
// wywolanie przerwania steruje praca timera 1ktory odczytuje dl impulsu
EIMSK |= 1 << INT0; // Włączenie przerwania na pinie INT0
INT0_zbocze_narastajace; // reakcja na zbocze narastajace
//PORTD |= 1 << 2;
// Ustawienie timera1 - 16bit
// uzywany do odczytu dlugosci impulsu z kanalu rc
TCCR1A = 0; // Wyjscia OCx jako normalne porty a nie wyjscia PWM
TCCR1B = 0; // Chwilowo wyłączony timer1