-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: RC Summensignal erzeugen

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.01.2009
    Ort
    Dortmund
    Alter
    23
    Beiträge
    114

    RC Summensignal erzeugen

    Anzeige

    Hi Leute,

    Ich muss aus mehreren einzelnen PPM Signalen ein Summensignal erstellen.

    So ein Summensignal sieht so aus :


    Ein komplettes PPM-Frame hat eine Länge von 22,5 ms. Es besteht aus einer überlangen Startinformation und 8 Kanalinformationen. Auf jeden Impuls folgt eine Stoppinformation mit 0,3 ms Länge. Die Länge eines Kanalimpulses beträgt 0,7 ms bis 1,7 ms und entspricht der Knüppelposition. Somit stammt die Abbildung von einem Sender mit Kanal 1 auf Vollausschlag rechts, Kanal 2 auf Vollausschlag links, Kanal 3 auf Mitte, .. Der Startimpuls ergänzt die 8 Kanalimpulse, so dass sich die Gesamtlänge von 22,5 ms ergibt.

    Die Gesammtlänge von 22,5ms ist allerdings nciht so entscheident, das Signal kann ca. 18 bis 30ms lang sein..


    So, ich habe schon viel Hirnschmalz hineininterpretiert, aber ich habe keine Idee wie ich so ein Signal aus einzelnen PPM signalen erzeugen kann..


    Kann mir da jemand weiterhelfen??????

    Danke im Vorraus

    Mfg Yannik[/i]
    Wer Rechtschreibfehler findet, darf sie behalten!

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Der erste und eigentlich schwierigere Schritt ist, die einzelnen Impulslängen der ankommenden Kanäle zu messen.

    Das mach ich üblicherweise mit flankengetriggerten Interrupts, bei denen Ich dann das sensing umschalte -> Einmal steigende Flanke, Dann wieder fallende Flanke.

    Da Du anscheinend gleich 8 von diesen Impulslängen messen willst, brauchst Du einen Controller der 8 geeignete Interuptquellen hat.
    Da dürften sich Controller eignen, die Pin Change Interrupts unterstützen.

    Die Signalausgabe ist am einfachsten über Comparematch Interrups an einem 16Bit Timer zu lösen.
    Du lässt einen Zähler mitlaufen, der die aktuelle Kanalposition darstellt.
    Bei einem Comparematch Interrupt wird zum aktuellen Zählerstand die Counts bis zum nächsten gewünschten Ereignis addiert.
    Dieser Wert wird dann im Comparematch Register des Timers abgespeichert.
    Das machst Du so lange, bis alle Impulse + Pause Übertragen wurden, dann stellst Du diesen Framecounter wieder auf 0 und es beginnt alles wieder von Vorne.

    Beispiel !!!
    Startbedingung, Kanal 1 wird übertragen:
    Comparematch Interupt tritt auf.
    Der Impulsausgang wird auf 1 geschaltet.
    Der TCNT wird ausgelesen, es werden die Counts bis zum nächsten Comparematch Interrupt ( sagen wir mal 1,8ms ) zu diesem Wert dazu gezählt.
    Dieser Wert wird ins Comparemach Register eingespeichert.
    Die Comparematch Interrupt routine wird verlassen.

    Der nächste Comparematch Interupt tritt nach 1,8ms auf.
    Der Impulsausgang wird auf 0 gesteuert.
    Das TCNT Register wird ausgelesen.
    Dazu werden die Counts bis zum nächsten gewünschten Interrupt dazu addiert - In Deinem Fall wären das 0,2ms.
    Dieser Wert wird im Comparematch Register des Counters abgespeichert.
    Der Impulszähler wird Inkrementiert.
    Die Comparematch Interrupt routine wird verlassen.

    Beim nächsten Comparematch Interrupt also nach 1,8+0,2ms gehts dann so weiter bis alle Impulse + Startpause übertragen wurden.
    Dann wird einfach der Framecounter auf 0 gesetzt und das Spielchen beginnt von vorne.

    Das funktioniert sehr gut und läuft praktisch im Hintergrund, weil die komplette Impulsausgabe im Comparematch Interrupt stattfindet.

    Der gleiche 16 Bit Timer kann dann auch gleich für die Impulslängenmessung der eingehenden Impulse verwendet werden, weil das TCNT Register ja nicht verändert, sondern nur gelesen wird.

    Die Impulsausgabe Funktion läuft auch problemlos über die 0 Stellung des Counters drüber. Also ein Null Stellen des TCNT Registers ist absolut nicht nötig und sogar kontraproduktiv, auch wenn es für das Verständnis einfacher wäre am anfang jedes Frames das Register zu Nullen!

    Nachtrag!
    Wenn Du den Controller mit 8MHz laufen lässt, einen 16Bit Timer mit Prescaler 8 nimmst, dann entsprechen 1000 Counts genau einer ms.
    Also ein Count ist dann 1µs lang.
    Die Servoauflösung entspricht dabei ca. 1000 Schritten, was die meisten Servos ohnehin nicht mehr auflösen können.

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.01.2009
    Ort
    Dortmund
    Alter
    23
    Beiträge
    114
    Zitat Zitat von wkrug
    Da Du anscheinend gleich 8 von diesen Impulslängen messen willst, brauchst Du einen Controller der 8 geeignete Interuptquellen hat.
    Da dürften sich Controller eignen, die Pin Change Interrupts unterstützen.
    Also genauergesagt muss ich nur 2 PPM Signale messen, die dann nachher auf Kanal 5 und 6 erscheinen sollen..

    Zitat Zitat von wkrug
    Beispiel !!!
    Startbedingung, Kanal 1 wird übertragen:
    Comparematch Interupt tritt auf.
    Der Impulsausgang wird auf 1 geschaltet.
    Der TCNT wird ausgelesen, es werden die Counts bis zum nächsten Comparematch Interrupt ( sagen wir mal 1,8ms ) zu diesem Wert dazu gezählt.
    Dieser Wert wird ins Comparemach Register eingespeichert.
    Die Comparematch Interrupt routine wird verlassen.

    Der nächste Comparematch Interupt tritt nach 1,8ms auf.
    Der Impulsausgang wird auf 0 gesteuert.
    Das TCNT Register wird ausgelesen.
    Dazu werden die Counts bis zum nächsten gewünschten Interrupt dazu addiert - In Deinem Fall wären das 0,2ms.
    Dieser Wert wird im Comparematch Register des Counters abgespeichert.
    Der Impulszähler wird Inkrementiert.
    Die Comparematch Interrupt routine wird verlassen.

    Beim nächsten Comparematch Interrupt also nach 1,8+0,2ms gehts dann so weiter bis alle Impulse + Startpause übertragen wurden.
    Dann wird einfach der Framecounter auf 0 gesetzt und das Spielchen beginnt von vorne.
    Ähm, ja, ich mag auch Toastbrot.

    So ganz check ich das noch nicht


    Zitat Zitat von wkrug
    Das funktioniert sehr gut und läuft praktisch im Hintergrund, weil die komplette Impulsausgabe im Comparematch Interrupt stattfindet.
    Daraus schließe ich mal, das du irgendwo schonmal sonen Code verwendet hast, könntest du den mal posten?


    Also einen Code um an die RC Werte zu kommen habe ich bereits (Den habe ich vorher schonmal verwendet.. Allerdings kam es da nciht auf die Auflösung an, die hier nur ca. 70Schritte beträgt. .Aber das könnt man ja durch verwendung eines 16Bit Timers ändern.. :



    Code:
    $regfile = "m16def.dat"
    $crystal = 4000000
    
    Config Portd.2 = Input
    
    Dim Lesen1 As Bit
    Dim Gyro_gier As Byte
    
    Lesen1 = 0
    
    Config Timer0 = Timer , Prescale = 64
    Enable Timer0
    Stop Timer0
    
    Config Int0 = Change
    On Int0 Messen1
    Enable Interrupts
    Enable Int0
    
    Do
    
    Loop
    
    End
    
    Messen1:
    
       If Lesen1 = 0 Then
          Start Timer0
          Lesen1 = 1
       Else
          Stop Timer0
          Gyro_gier = Timer0
          Timer0 = 0
          Lesen1 = 0
       End If
    
    Return
    Wer Rechtschreibfehler findet, darf sie behalten!

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Den kann Ich Dir schon schicken, der ist aber in "C", das wird Dir bei Bascom nicht viel nützen.

    Ähm, ja, ich mag auch Toastbrot.
    Kurz gesagt du bringst den Controller dazu, bei jedem gewünschten Pegelwechsel am Summenimpulsausgang eine Comparematch Interrupt zu erzeugen.

    Also einen Code um an die RC Werte zu kommen habe ich bereits (Den habe ich vorher schonmal verwendet.. Allerdings kam es da nciht auf die Auflösung an, die hier nur ca. 70Schritte beträgt. .Aber das könnt man ja durch verwendung eines 16Bit Timers ändern.. :
    ... und zwar drastisch. Auch hier kommst Du auf 1000 Schritte!

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.01.2009
    Ort
    Dortmund
    Alter
    23
    Beiträge
    114
    Hm ne, dann lass es lieber, mit C kann ich garnix anfangen =/
    Wer Rechtschreibfehler findet, darf sie behalten!

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Ich versuchs trotzdem mal mit Code!
    Das ist nur der Code für den Comparematch Interrupt.
    Die Timer Initialisierung und die Initialisierung der Variablen, sowie die Interruptfreigabe müssen natürlich auch gemacht werden.

    Code:
    Comparematch Interrupt Routine
    if(pinb.0==0)     // Hier werden die Pulslängen erzeugt
    {
    portb.0=1;
    OCR1A=TCNT1+Pulselengh[channel]-200;
    }
    else
    {
    // Hier werden die Pausen zwischen den Impulsen erzeugt
    portb.0=0;
    OCR1A=TCNT1+200;
    channel++;
    if(channel>8){channel=0;};
    };
    Die indizierte Variable Pulslengh hat dabei 9 Integer ( 16Bit ) Speicherplätze.
    Im Speicherplatz 0 ist die Länge der Pause drin, im rest die gewünschten Impulslängen.

    Mehr ist das nicht.
    Ich hab den Code jetzt mal kurz aus dem Kopf aufgeschrieben und hoffentlich nichts vergessen.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.01.2009
    Ort
    Dortmund
    Alter
    23
    Beiträge
    114
    Mal als grundlegende Frage.. Was sind Comparematch Interrupts ??? Hab dazu irgendwie nix geunden... Ich nehme mal an "TCNT Register" erklärt sich damit dann auch?!
    Wer Rechtschreibfehler findet, darf sie behalten!

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Oh je, da müssen wir ja ganz von vorne anfangen.
    Guck mal ins Datenblatt eines ATMEGA Controllers wie dem ATMEGA 8.
    Der hier interessante Teil beginnt auf Seite 74.
    Das TCNT1 Register ist ein Zähler der im Timer1 eingebaut ist.

    Diesem Register ist ein sogenannter Prescaler vorgeschaltet, der einen ankommenden Takt teilt und mit diesem geteilten Takt dieses TCNT1 Register hochzählt.
    Ebenfalls in diesem Timer enthalten sind 2 Comparematchunits.
    Das OCR1A Register gehört zur Comparematchunit A.
    Das OCR1B gehört zur Comparematchunit B.

    Für Dich ist vorerst nur mal die Comparematchunit A interessant.

    Mit deinen Bascom Befehlen musst Du den Timer Initialisieren und den Comparematch Interrupt A freigeben.
    Als weiteres müssen natürlich die Interrups grundsätzlich freigegeben werden.
    War das nicht in Bascom ENABLE Interrupts ?

    Erreicht das TCNT1 Register den Wert, der im OCR1A Register abgelegt ist, wird der Comparematch A Interrupt getriggert und die dazugehörige Routine ausgeführt.

    Das wars mal so weit es Dich jetzt konkret betrifft.

    Dieser Timer 1 ist sehr umfangreich.
    Die komplette Beschreibung dieses Timers kannst Du im Datenblatt von Seite 74 bis 101 nachlesen!

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.01.2009
    Ort
    Dortmund
    Alter
    23
    Beiträge
    114
    Zitat Zitat von wkrug
    Das TCNT1 Register ist ein Zähler der im Timer1 eingebaut ist.
    Also ist das einfach der Wert, den der Timer momentan hatt?!?

    Zitat Zitat von wkrug
    Diesem Register ist ein sogenannter Prescaler vorgeschaltet, der einen ankommenden Takt teilt und mit diesem geteilten Takt dieses TCNT1 Register hochzählt.
    Das mit dem Prescaler ist mir klar..

    Zitat Zitat von wkrug
    Ebenfalls in diesem Timer enthalten sind 2 Comparematchunits.
    Das OCR1A Register gehört zur Comparematchunit A.
    Das OCR1B gehört zur Comparematchunit B.

    Für Dich ist vorerst nur mal die Comparematchunit A interessant.

    Mit deinen Bascom Befehlen musst Du den Timer Initialisieren und den Comparematch Interrupt A freigeben.
    Als weiteres müssen natürlich die Interrups grundsätzlich freigegeben werden.
    War das nicht in Bascom ENABLE Interrupts ?

    Erreicht das TCNT1 Register den Wert, der im OCR1A Register abgelegt ist, wird der Comparematch A Interrupt getriggert und die dazugehörige Routine ausgeführt.
    Also wird einfach eine Interrupt Routine (vom Interrupt COMPARE1A) gestartet, sobald Timer1 den Wert von OCR1A erreicht!?!

    Hmm okay, soweit glaub ich ist das klar..


    So, ich glaube mit den Vorraussetzungen komm ich schon etwas weiter..

    Aber jetzt zurück zum eig. Summensignal.. Das hab ich noch nicht so gaz verstanden.. So im groen und ganzen weiß ich was dein Code usw. bewirken soll, aber so ganz kann ich noch nix damit anfangen..

    Also mal Schritt für Schritt..

    Als erstes konfiguriere ich Timer1 :

    Code:
    Config Timer1 = Timer , Prescale = 8
    Enable Timer1
    Dann konfiguriere ich den interrupt :

    Code:
    Enable OC1A
    On OC1A Comp_ISR
    So und hier liegt jetzt langsam mein Problem...

    Da check ich langsam das alles nicht mehr so ganz...

    Also wie gesagt so im groben ist mir klar was passieren soll :

    OC1A wird ausgelöst, wenn der Summensignal Ausgang auf Low ist, wird er auf High geschaltet und dann wird OC1A = Timer1 + Pulslenge festgelegt und die ISR beendet. Sobald dann die Pulslenge erreicht ist, wird die ISR erneut gestartet, aber da der Summensignal Ausgang auf High ist, wird OC1A = Timer1 + 300 festgelegt um die 0,3ms pause festzulegen.

    Und das ganze dann immer durch...

    Jetzt weiß ich nur nciht so ganz genau wie ich das im Endeffekt umsetzen soll...

    Und eins noch : Die Lenge des "Start-High-Pegels" muss sich ja verändern, damit die Gesammtlenge des Summensignals immer gleich bleibt, die kann man das lösen???

    EDIT : Timer1 ist ja dadurch schon belegt, wie kann ich dann die Eingangsimpulse mit einer anständigen Auflösung messen??
    Wer Rechtschreibfehler findet, darf sie behalten!

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    OC1A wird ausgelöst, wenn der Summensignal Ausgang auf Low ist.
    Fast richtig. Der OC1A wird bei jeder gewünschten Änderung des Ausgangssignales aufgerufen.
    Also bei L->H Wechsel ebenso wie beim H->L Wechsel.
    Das Kriterium welcher Teil der Interruptroutine aufgerufen wird, wird aus dem PINB.0 gewonnen. Man könnte hier ebenso den PORTB.0 abfragen.

    ...wird er auf High geschaltet und dann wird OC1A = Timer1 + Pulslenge festgelegt...
    minus der Länge die die kurze Pause zwischen 2 Impulsen haben soll!


    Sobald dann die neue Pulslenge erreicht ist, wird die ISR erneut gestartet, aber da der Summensignal Ausgang auf High ist, wird OC1A = Timer1 + 300 festgelegt um die 0,3ms pause festzulegen.
    Im nächsten OC1A Interrupt wird dann die Pause abgearbeitet.
    Es wird hier nicht auf irgendein Ereignis gewartet, sonst gibts Probleme.
    Auf irgendein Ereignis in einer Interruptroutine zu warten ist ein absolutes NO GO!!!

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •