PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PPM Signal mit AVR erzeugen



Razer
01.09.2006, 16:02
Hallo an alle

Ich hab da ein Problem. Also als Aufgabe habe ich ein PPM Signal zu
erstellen.

Für alle die das PPM Protokoll nicht kennen, hier ein Link wie das
Protokoll: http://www.aerodesign.de/peter/2000/PCM/frame_ppm.gif
Es gibt Pulse von 1 - 2ms, dann imer eine Pause von 0,3ms. Nach 8
Pulsen kommt ein längerer Startpuls. Die 1,024ms Bandbreite hab ich in
8 Bit geteilt. Damit hab 8 Bit Genauigkeit am Ausgangssignal. Die
Zeitwerte für die Potis sample ich met den Adc Kanälen. Da ich den MEga
168 im DIP Gehäuse benutze (Ich weiß der ist ein bisschen oversized,
aber ich hab grad keinen anderen rumliegen...) hab ich nur 6 ADC Kanäle
zu Verfügung. Den restlichen 2 Kanälen gebe ich einen Fixwert, da ich
sie eh nicht nutze....

So jetzt zum eigentlichen Problem:

Der ADC läuft jetzt im Free Running Modus. Und sobald eine Messung
fertig ist, wird in der ISR der Wert gesichert und auf den nächste
Kanal geschaltet.

Die ISR macht mir immer noch zu schaffen. Derzeit dauert die ISR im
Worst Case 84 Takte. (Minimal 54 Takte) Je nach dem was gerade in der
ISR zu machen ist.



ISR(TIMER0_COMPA_vect) //4µsec
{
if(--time == 0 && GLOB_STAT == 0x00)
{
time = NACHLADEWERT;
GLOB_STAT = 0x02;
}
else
{
if(time == 0)
{
PWM_PORT ^= (1 << PWM_PIN); //Wenn Zeit abgelaufen toggle PWM Pin

if(GLOB_STAT == 0x02) //Wenn gerade eine High Phase (keine Pause) war Pause aktiv
{
time = PAUSE;
GLOB_STAT = 0x01;
}
else //Sonst ird das aktuelle Servo in das time Register geladen
{
if(++servozaehler < 8) //Wenn das 8. Servo erreicht ist, wieder auf 0 stellen
time = servo[servozaehler];
else
{
servozaehler = 0;
time = longpulse;
}
GLOB_STAT = 0x00;
}
}
}
}


Wie kann ich das besser lösen??

Ich hoffe es kann mir helfen

Gruß Robert

SprinterSB
01.09.2006, 16:28
Es funktioniert, und es soll "nur" schneller gehen?

In dem Falle versuch mal, von time ne lokale Kopie zu machen und sonst nur mit _time zu arbeiten:


ISR...
{
int _time = time;
...
time = _time;
}

Evtl auch für die anderen elementaren Typen (GLOB_STAT, servozaehler).

servozaehler sieht was seltsam aus. Du hast nur 7 Servos? Evtl ist es besser mit &= 7 zu arbeiten.

Razer
01.09.2006, 17:22
Eigentlich funktioniert es grundsätzlich. Ein paar änderungen muss ich noch machen, da lonpulse eine 16 Bit Variable ist. Leider....

Die lokalen Variablen werden automatisch in einem Maschinenregister abgelegt?? Oder muss ich zusätzlich mit register deklarieren?

Servos hab ich 8. Eben Servo 0 - 7.

Gruß Robert

SprinterSB
01.09.2006, 22:42
Nein, "register" ist IMHO wirkungslos. Optimiere mit -Os und das Zeug wird in GPRs gehalten, falls der Code einfach genug ist (ist hier der Fall). Falls der Code komplexer ist und Variablen im Frame leben anstat in GPRs, hilft dir "register" auch nicht.

So ganz sehe ich auch nicht, warum du time überhaupt brauchst... du könntest doch genauso die IRQ-Dauer von Timer0 anpassen? Oder brauchst Timer0 noch für was anderes?

Razer
06.09.2006, 20:46
Den Timer0 brauch ich sonst nicht.

Wie willst du das ohne die Variable time machen??

Die Dauer ist nach jedem Puls eine andere Zeit.

Gruß Robert

SprinterSB
07.09.2006, 09:34
äh...stimmt :oops: Timer0 hat ja kein einstellbaren OCR-Wert.