Skocz do zawartości

Generator PPM


Pomocna odpowiedź

Mi się wydaje że 8-bitowy timer skonfigurowany i odpowiednio sterowany w trybie CTC powinien to spokojnie uciągnąć. Tylko trzeba generować sygnał w przerwaniach od timera.

I dlaczego nie można stosować zmiennych w tych funkcjach ?

Ze względu na sposób definiowania tego makro, które odmierzając konkretny odcinek czasu musi zostać najpierw dokładnie policzone, a to może trwać różnie zależnie jaką zmienną chciałbyś podstawić.

Hmm to jak zrobić to inaczej ?

1. albo opracować własną procedurę opóźnienia,
2. albo zdefiniować kilka funkcji które mają określone opóźnienie zdefiniowane za pomocą delay ze stałą a nie zmienną.

3. używać timera z przerwaniem jak radzi kol. BlackJack

... i pewnie jeszcze jakieś inne sposoby.

od biedy możesz włożyć delaya o jakiejś stałej wartości w pętle i dać warunek wyjścia z tej pętli zależny od zmiennej. Ale jeżeli masz jakieś wolne timery zawsze lepiej ich używać do tego celu a takie kombinacje sobie zostawić na przypadki kiedy każdy timer jest już zajęty do czego innego.

Mógłby ktoś zerknąć i powiedzieć co źle zrobiłem ? 🙂

Wykresy nie wychodzą takie jak powinny.

#include <avr/io.h>
#include <util/delay.h>  
#include <stdio.h>
#include <avr/interrupt.h> 

#define SetBit(x,y)	x |= (1<<y)
#define ClrBit(x,y) x &= ~(1<<y)
#define NegBit(x,y) x ^= (1<<y)

volatile int S1,S2,S3,S4,S5,S6,S7,S8,S9,S10, t=0, ser=1;   // Zmienna w mikro sekundach, Serwa 1,2,3,...        

void ppm()
{
if(ser==5)
{
	SetBit(PORTC,1);
	_delay_us(300);
	ClrBit(PORTC,1);
	OCR2=((S5-300)/16) - 2;
	SetBit(TIMSK,OCIE2);
}

if(ser==4)
{
	SetBit(PORTC,1);
	_delay_us(300);
	ClrBit(PORTC,1);
	OCR2=((S4-300)/16) - 2;
	SetBit(TIMSK,OCIE2);
}

if(ser==3)
{
	SetBit(PORTC,1);
	_delay_us(300);
	ClrBit(PORTC,1);
	OCR2=((S3-300)/16) - 2;
	SetBit(TIMSK,OCIE2);
}


if(ser==2)
{
	SetBit(PORTC,1);
	_delay_us(300);
	ClrBit(PORTC,1);
	OCR2=((S2-300)/16) - 2;
	SetBit(TIMSK,OCIE2);
}

if(ser==1)
{
	SetBit(PORTC,1);
	_delay_us(300);
	ClrBit(PORTC,1);
	OCR2=((S1-300)/16) - 2;
	SetBit(TIMSK,OCIE2);		
}

if(ser==0)
{
	ser=1;
	SetBit(PORTC,1);
	_delay_us(300);
	ClrBit(PORTC,1);
}

}

ISR(TIMER1_COMPA_vect)	// Rozpoczyna wysył danych co 20ms
{
ppm();
NegBit(PORTC,2);
}

ISR(TIMER2_COMP_vect)
{
if(ser<5)
{
	ser++;
}
else
{
	ser=0;
}
ClrBit(TIMSK,OCIE2);
ppm();
}



int main(void)
{ 
DDRC	=	0b11111111;		// PORTC jako wyjście
PORTC	=	0b00000000;

//Timer 1
TCCR1A= (1<<FOC1A);
TCCR1B= (1<<CS11) | (1<<CS10) | (1<<WGM21);

//Timer 2
TCCR2= (1<<FOC2) | (1<<WGM21) | (1<<CS22) | (1<<CS21);

OCR2=0;

OCR1A=4998;
TIMSK = (1<<OCIE1A);

sei();

S1=1000;
S2=1500;
S3=2000;
S4=1000;
S5=2000;
S6=1500;
S7=1500;
S8=1500;
S9=1500;
S10=1500;

 while(1)
 {   

 }
}

A wyjście PORTC,1 wygląda tak:

Czemu tak się męczysz? Wpisz w google sterownik 16 serw atmega i pierwszy link. Program jest o wiele prostszy a sam go uruchomiłem i działa bez problemów.

Chodzi o to, że muszę to zrobić w taki sposób. Ponieważ tylko tak mogę komunikować się z nadajnikiem który to on dopiero wysyła sygnał do odbiornika który steruje serwami które są hen daleko od mojego układu.

Jak narazie to nie widzę żadnej komunikacji. Poza tym bez problemu można przerobić kod z drugiego listingu wywalając co niepotrzebne i masz sterowanie serwami. Oczywiście mówię o tym projekcie.

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