- 3D-Druck Einstieg und Tipps         
Seite 4 von 8 ErsteErste ... 23456 ... LetzteLetzte
Ergebnis 31 bis 40 von 75

Thema: Mehrere RC Signale einlesen und mehrere Servos ausgeben

  1. #31
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Anzeige

    Praxistest und DIY Projekte
    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    Nur noch ganz selten hörbare und fühlbare Zuckungen, sichtbare Zuckungen waren praktisch nicht vorhanden. Werde morgen nochmal ausgiebig testen und den Code anschließend in mein Programm aufnehmen.
    Hört sich schon gut an, aber leider noch nicht semiperfekt.

    Zitat Zitat von for_ro
    Das ist gar nicht so wild.

    • Du setzt den Bandgap auf 1, dann brauchst du keinen externen positiven Eingang mehr.
    • Du stoppst den ADC und schaltest den Multiplexer auf den negativen Input.
    • Du verbindest den AC mit dem ICP von Timer1
    • Du selektierst den gewünschten Flankenwechsel des AC und auch für den Input Capture
    Das reizt mich, aber bevor ich/wir daran gehen noch eine Symptombehandlung. Jitterunterdrückung per SW-Hysterese nach diesem Muster zum Testen.

    Hab in der Hauptschleife nun eine SW-Hysterese untergebracht. Die Hysterese kann über die Konstante "Jitterausgleich" in Vielfachen von von 8µs eingestellt werden. Testweise auch kleinere Stufen, aber ich glaube, daß dann das Servo "weglaufen" könnte. Müßte man mal testen.

    Gruß
    Searcher

    Code:
    '===============================================================================
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)
    'RC Eingang 2 an Pin 6 (PA7, PCINT7)
    'RC Eingang 3 an Pin 5 (PB2, INT0)
    'Servo 1 an Pin 13 (PA0)
    'Servo 2 an Pin 12 (PA1)
    'Servo 3 an Pin 11 (PA2)
    'Servo 4 an Pin 10 (PA3)
    '===============================================================================
    
    $regfile = "attiny84.dat"
    $crystal = 8000000                      'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 50
    $swstack = 50
    $framesize = 50
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer und konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8    'Timer für Einlesen RC Signale
    Start Timer1
    
    Config Timer0 = Timer , Prescale = 64   'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms
    Enable Timer0
    On Timer0 Servoausgabe Nosave           'Register werden manuell in der ISR gesichert
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren / Konstanten
    '-------------------------------------------------------------------------------------------------------------
    
    Const Jitterausgleich = 8               'Wert in µs um den sich gemessene Impulslaenge aendern darf/muss, bevor Servo gestellt wird
                                            'Nur in Vielfachen von 8 veraendern (8, 16, 32, ..)
    'Variablen fürs RC Einlesen
    Dim Rc_signal_1_start As Word
    Dim Rc_signal_2_start As Word
    Dim Rc_signal_3_start As Word
    
    Dim Rc_signal_1_stop As Word
    Dim Rc_signal_2_stop As Word
    Dim Rc_signal_3_stop As Word
    
    Dim Rc_signal_1_stop_flag As Byte
    Dim Rc_signal_2_stop_flag As Byte
    Dim Rc_signal_3_stop_flag As Byte
    
    
    Dim Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    Dim Impulslaenge_1_alt As Word
    Dim Impulslaenge_2_alt As Word
    Dim Impulslaenge_3_alt As Word
    Dim Impulslaengenaenderung As Integer   'wird nur einmal gebraucht, da nur Hilfswariable
    
    
    'Variablen für Berechnungen
    Dim Berechnung_1 As Word
    Dim Berechnung_2 As Word
    
    
    
    'Variablen für Servoausgabe
    Dim Kanal As Byte
    Dim Servoausgabe_1 As Byte
    Dim Servoausgabe_2 As Byte
    Dim Servoausgabe_3 As Byte
    Dim Servoausgabe_4 As Byte
    'Dim Pausen_variable As Byte
    
    
    '-------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------
    
    Kanal = 1
    'Pausen_variable = 0
    
    Impulslaenge_1_alt = 1500               'mit Servomittelstellung initialisieren (nicht essentiell)
    Impulslaenge_2_alt = 1500               'mit Servomittelstellung initialisieren (nicht essentiell)
    Impulslaenge_3_alt = 1500               'mit Servomittelstellung initialisieren (nicht essentiell)
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein - Und Ausgang Festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00001111                       'PA0 - PA3 werden Ausgänge
    Ddrb = &B00000000                       'PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    'Info:
    'Alle Porta Pinchangeinterrupts sind in Bascom "PCINT0" zugeordnet.
    'Alle Portb Pinchangeinterrupts sind in Bascom "PCINT1" zugeordnet.
    
    
    Pcmsk1.pcint9 = 1                       'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen
    Enable Pcint1                           'Pinchangeinterrupt1 (1 weil auf PortB) zulassen
    On Pcint1 Rc_eingang_1 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Pcmsk0.pcint7 = 1                       'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen
    Enable Pcint0                           'Pinchangeinterrupt0 (0 weil auf PortA) zulassen
    On Pcint0 Rc_eingang_2 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Config Int0 = Change                    'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen
    Enable Int0
    On Int0 Rc_eingang_3 Nosave             'Register werden manuel in der ISR gesichert
    
    Enable Interrupts
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
      If Rc_signal_1_stop_flag = 1 Then     'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Pcint1                    'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_1 = Rc_signal_1_stop - Rc_signal_1_start
          Enable Pcint1
          Rc_signal_1_stop_flag = 0
    
          Impulslaengenaenderung = Impulslaenge_1_alt - Impulslaenge_1       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
              Impulslaenge_1_alt = Impulslaenge_1
    
              Berechnung_1 = Impulslaenge_1
              Shift Berechnung_1 , Right , 3       'Division von Berechnung_1 durch 8
              If Berechnung_1 > 255 Then Berechnung_1 = 255       'zu hohe Werte abfangen
              If Berechnung_1 < 120 Then Berechnung_1 = 120       'zu kleine Werte abfangen
              Servoausgabe_1 = 256 - Berechnung_1       'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
          End If
      End If
    
    
      If Rc_signal_2_stop_flag = 1 Then     'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Pcint0                    'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_2 = Rc_signal_2_stop - Rc_signal_2_start
          Enable Pcint0
          Rc_signal_2_stop_flag = 0
    
          Impulslaengenaenderung = Impulslaenge_2_alt - Impulslaenge_2       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
              Impulslaenge_2_alt = Impulslaenge_2
    
              Berechnung_2 = Impulslaenge_2
              Shift Berechnung_2 , Right , 3       'Division von Berechnung_1 durch 8
              If Berechnung_2 > 255 Then Berechnung_2 = 255       'zu hohe Werte abfangen
              If Berechnung_2 < 120 Then Berechnung_2 = 120       'zu kleine Werte abfangen
              Servoausgabe_2 = 256 - Berechnung_2       'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
          End If
      End If
    
      Servoausgabe_3 = 190
      Servoausgabe_4 = 190
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    Rc_eingang_1:
     $asm
       push r17                             'Register auf Stack sichern
       sbis pinb , 1                        'Skip next Instr if PINBx = 1
       rjmp Puls_ende1                      'Springe Puls_ende
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17        'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende1                           'Springe zum Ende
      Puls_ende1:
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_1_stop} , r17         'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_1_stop} + 1 , r17     'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_1_stop_flag} , r17    'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende1:
       pop r17                              'Register vom Stack zurückholen
     $end Asm
    Return
    
    Rc_eingang_2:
     $asm
       push r17                             'Register auf Stack sichern
       sbis pinA , 7                        'Skip next Instr if PINBx = 1
       rjmp Puls_ende2                      'Springe Puls_ende
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_2_start} , r17        'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_2_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende2                           'Springe zum Ende
      Puls_ende2:
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_2_stop} , r17         'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_2_stop} + 1 , r17     'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_2_stop_flag} , r17    'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende2:
       pop r17                              'Register vom Stack zurückholen
     $end Asm
    Return
    
    Rc_eingang_3:
     $asm
       push r17                             'Register auf Stack sichern
       sbis pinB , 2                        'Skip next Instr if PINBx = 1
       rjmp Puls_ende3                      'Springe Puls_ende
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_3_start} , r17        'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_3_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende3                           'Springe zum Ende
      Puls_ende3:
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_3_stop} , r17         'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_3_stop} + 1 , r17     'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_3_stop_flag} , r17    'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende3:
       pop r17                              'Register vom Stack zurückholen
     $end Asm
    Return
    
    
    
    Servoausgabe:
    
     $asm
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       lds r17 , {kanal}                    'hole Kanalnummer
    
       cpi r17 , 1                          'check Kanal und ...
       brne LABEL_KANAL_2                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 0                       'Skip next instr. wenn PORTA.0 = 0 ist
       rjmp label_1                         'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                    'Sichere Kanalnummer
       lds r17 , {Servoausgabe_1}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 0                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_1:
       cbi porta , 0                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
    
    
      Label_kanal_2:                        'Bearbeitung von Kanal 2
       cpi r17 , 2                          'check Kanal und ...
       brne LABEL_KANAL_3                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 1                       'Skip next instr. wenn PORTA.1 = 0 ist
       rjmp label_2                         'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                    'Sichere Kanalnummer
       lds r17 , {Servoausgabe_2}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 1                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_2:
       cbi porta , 1                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
    
    
      Label_kanal_3:                        'Bearbeitung von Kanal 3
       cpi r17 , 3                          'check Kanal und ...
       brne LABEL_KANAL_4                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 2                       'Skip next instr. wenn PORTA.2 = 0 ist
       rjmp label_3                         'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                    'Sichere Kanalnummer
       lds r17 , {Servoausgabe_3}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 2                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_3:
       cbi porta , 2                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
    
    
      Label_kanal_4:                        'Bearbeitung von Kanal 4 mit anschließendem Pausenanfang
       cpi r17 , 4                          'check Kanal und ...
       brne LABEL_KANAL_5                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 3                       'Skip next instr. wenn PORTA.3 = 0 ist
       rjmp label_4                         'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                    'Sichere Kanalnummer
       lds r17 , {Servoausgabe_4}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 3                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_4:
       cbi porta , 3                        'Setze Servosignal nach LOW
    
    'Pausenauffüllung
    
       'Pausenanfang
       inc r17
       sts {kanal} , r17                    'Sichere Kanalnummer
       ldi r17 , &B00000101                 'CS00 und CS02 für prescaler 1024 in Timer0 vorbereiten
       Out Tccr0b , R17                     'Timer0 läuft mit 128µs Auflösung
       ldi r17 , 162                        'Wert für ca 12ms bis zum nächsten OVF (162=256-94) bei prescaler 1024
       Out Tcnt0 , R17
       rjmp Ende_isr                        'Springe zum Ende der ISR
    
      'Pausenende
      Label_kanal_5:                        'Bearbeitung von Kanal 5 (Pausenende)
       ldi r17 , &B00000011                 'CS00 und CS01 für prescaler 64 in Timer0 vorbereiten
       Out Tccr0b , R17                     'Timer0 läuft wieder mit 8µs Auflösung
       ldi r17 , 1                          'Kanalnummer auf 1 setzen
       sts {kanal} , r17                    'Sichere Kanalnummer
      Ende_isr:
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
     $end Asm
    Return



    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  2. #32
    Zitat Zitat von Searcher Beitrag anzeigen
    Müßte man mal testen.
    Na dafür bin ich ja da

    Ich hab den Code mal eingespielt, leider kam es zu Errors.

    Die Zeilen...
    Code:
    If Abs(impulslaengenaenderung) >= Jitterausgleich Then
    ...mag mein Bascom (1.11.9.8.) gar nicht.
    Keine Ahnung, ob's an meiner Version liegt.


    Habe den Code dann geändert in...
    Code:
    Dim A As Word 
    .
    .
    .
    A = Abs(impulslaengenaenderung)
          If A >= Jitterausgleich Then
    ... und schon klappte es.

    Die Servos würde ich nun als "jitterfrei" bezeichnen. Ich habe allerdings nicht die Möglichkeit, die tatsächlichen Werte zu betrachten (z.B. Oszi usw). Als Servos habe ich die billigsten HXT500 vom bösen Chinamann, sowie HS-82MG und HS-85MG dranhängen (Digitalservos hab ich keine zum Testen).

    Die Konstante "Jitterausgleich" habe ich auch mal auf 4 verkleinert, konnte aber keine Veränderung feststellen.

    mfg
    Robert

  3. #33
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    Die Zeilen...
    Code:
    If Abs(impulslaengenaenderung) >= Jitterausgleich Then
    ...mag mein Bascom (1.11.9.8.) gar nicht.
    Keine Ahnung, ob's an meiner Version liegt.
    Ja, liegt an der Bascom Version. Ich nutze die 2.0.7.5 Demo Version und es gibt, glaub ich schon eine neuere.

    Die Servos würde ich nun als "jitterfrei" bezeichnen. Ich habe allerdings nicht die Möglichkeit, die tatsächlichen Werte zu betrachten (z.B. Oszi usw).
    Nichts mehr zu hören? Nein? Super! Das würd mir erstmal reichen! Werd aber sicher nochmal die MUX Methode versuchen. Bedeutet dann aber auch eine Änderung der HW, da die drei RC Eingänge auf ADC Eingänge gelegt werden müßten.
    Die Konstante "Jitterausgleich" habe ich auch mal auf 4 verkleinert, konnte aber keine Veränderung feststellen.
    Ich verlier da so langsam den Überblick und man müßte das Ganze mal am Simulator oder händisch mit verschiedenen nah beieinander liegenden Impulslaengen durchspielen. Dadurch, daß der Timer0 ja nur eine Auflösung von 8µs hat und der Wert für Timer0 durch eine Division durch 8 (mit implizitem Abschneiden der Nachkommastellen durch Nichtverwendung von Fließkommazahlen) entsteht, sollten kleinere Werte als 8 keine oder negative Auswirkungen haben. Wenn 8 funktioniert würd ich zunächst 8 drinlassen.

    Dann weiter frohes Testen
    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  4. #34
    Ich habe Deine ISRs nun in mein Programm mit eingebaut, Servozucken scheint nun kein Problem mehr zu sein. Leider hänge ich an einer anderen Stelle noch fest.

    Die Steuerung ist ja wie gesagt für einen Bagger.


    Folgende Funktionalitäten klappen einwandfrei:

    - Die Baggerarmservos bewegen sich nur, wenn der Knüppel aus der Mittelstellung genommen wird.
    - Wird der Knüppel losgelassen, verbleiben die Servos an der eben erreichten Stelle.
    - Sie fahren nur bis zu einer festgelegten Position (per Potis und SW festgelegter Endanschlag).


    Folgendes Feature funktioniert nur bedingt:

    -Die Servogeschwindigkeit hängt von der Größe des Steuerknüppelauschlags ab.


    Je weiter ich den Knüppel also aus der Mittelstellung auslenke, umso schneller fährt das Servo. Hier der Codeschnipsel, der das bewerkstelligt (die Variable Berechnung_1a wird am Programmende dann "Servoausgabe_1 = 256 - Berechnung_1a") :

    Code:
    'Erstes Baggerarmservo
    If Berechnung_1 < 182 Then                                  'Info: Todband (Mittelstellung) liegt zwischen 182 und 193
       Servospeed = Berechnung_1 - 120                          'ergibt Werte zwischen 0 (schnell) und 61 (langsam)
       Servospeed = Servospeed * 100                            'Werte hochscalieren (Faktor 30 bis 100, höherer Faktor = langsamerer minimal Speed)
       For I = 1 To Servospeed                                  'Werte von 0 (schnell) bis max 6100 (langsam) sinnvoll
       Next I
       Decr Berechnung_1a
    End If
    
    If Berechnung_1 > 193 Then
       Servospeed = 255 - Berechnung_1
       Servospeed = Servospeed * 100
       For I = 1 To Servospeed
       Next I
       Incr Berechnung_1a
    End If

    Leider tritt bei meinem Code folgendes Phänomen auf: Wenn ich den Knüppel aus der Todzone bewege (das Servo fährt langsam in die entsprechende Richtung) und dann schlagartig Vollausschlag mache, fährt das Servo manchmal nur mit reduzierter Geschwindigkeit weiter.

    Meine Vermutung ist nun folgende: Wenn das Servo langsam losfährt, ist die Variable "Servospeed" in der For-Next Schleife sehr groß. Auch wenn ich den Knüppel nun schlagartig auf Endandanschlag bringe, findet ja keine neue Berechnung der Variable "Servospeed" statt. Wenn also Servospeed sehr groß ist und ich den Knüppel nicht wieder in Mittelstellung bringe (um aus der ganzen IF Bedingung raus zu kommen), fährt das Servo nur mit Minimalgeschwindigkeit bis zum Anschlag.

    Das Programm besteht eigenlich nur aus einer großen If-Bedingung: Wenn Bertriebsmode "Fahrbetrieb", dann läuft es über den Deltamischer, ansonsten ist Betriebsmode "Baggerbetrieb". Der Teil mit dem Deltamischer funktioniert anstandslos, egal wie schnell ich die Knüppel vergewaltige. Daher gehe ich davon aus, dass "nur" der Teil mit der Servogeschwindigkeit während des Baggerbetriebs noch Veränderungen braucht.

    Hier das ganze Programm.

    Code:
    '===============================================================================
    'BAGGER Steuerung
    '
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)  Stick 1 (Aileron)
    'RC Eingang 2 an Pin 6 (PA7, PCINT7)  Stick 2 (Elevator)
    'RC Eingang 3 an Pin 5 (PB2, INT0)    Betriebsmode
    'Poti 1a an Pin 10 (PA3, ADC3)
    'Poti 1b an Pin 9 (PA4, ADC4)
    'Poti 2a an Pin 8 (PA5, ADC5)
    'Poti 2b an Pin 7 (PA6, ADC6)
    'Servo 1 an Pin 2 (PB0)  Baggerarmservo
    'Servo 2 an Pin 13 (PA0) Baggerarmservo
    'Servo 3 an Pin 12 (PA1) Kettenantrieb
    'Servo 4 an Pin 11 (PA2) Kettenantrieb
    '
    '===============================================================================
    
    $regfile = "attiny84.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 50
    $swstack = 50
    $framesize = 50
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8                        'Timer für Einlesen RC Signale
    Start Timer1
    
    Config Timer0 = Timer , Prescale = 64                       'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms
    Enable Timer0
    On Timer0 Servoausgabe
    
    
    '-------------------------------------------------------------------------------------------------
    'Poti-Eingänge konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Adc = Single , Prescaler = Auto
    Start Adc
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    Const Jitterausgleich = 8                                   'Wert in µs um den sich gemessene Impulslaenge aendern darf/muss, bevor Servo gestellt wird
                                                                 'Nur in Vielfachen von 8 veraendern (8, 16, 32, ..)
    
    
    'Variablen fürs RC Einlesen
    Dim Rc_signal_1_start As Word
    Dim Rc_signal_2_start As Word
    Dim Rc_signal_3_start As Word
    
    Dim Rc_signal_1_stop As Word
    Dim Rc_signal_2_stop As Word
    Dim Rc_signal_3_stop As Word
    
    Dim Rc_signal_1_stop_flag As Byte
    Dim Rc_signal_2_stop_flag As Byte
    Dim Rc_signal_3_stop_flag As Byte
    
    Dim Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    Dim Impulslaenge_1_alt As Word
    Dim Impulslaenge_2_alt As Word
    Dim Impulslaenge_3_alt As Word
    Dim Impulslaengenaenderung As Integer                       'wird nur einmal gebraucht, da nur Hilfswariable
    
    
    'Variablen für Servowegsbegrenzung
    Dim Poti_1a As Word
    Dim Poti_1b As Word
    Dim Poti_2a As Word
    Dim Poti_2b As Word
    
    Dim Limit_1a As Byte
    Dim Limit_1b As Byte
    Dim Limit_2a As Byte
    Dim Limit_2b As Byte
    
    
    'Variablen für Berechnungen
    Dim Berechnung_1 As Word
    Dim Berechnung_2 As Word
    Dim Berechnung_3 As Word
    Dim Berechnung_4 As Word
    
    Dim Berechnung_1a As Word
    Dim Berechnung_2a As Word
    Dim Berechnung_3a As Word
    Dim Berechnung_4a As Word
    
    Dim I As Word
    Dim Servospeed As Word
    
    'Variable für Deltamischer
    Dim A1 As Integer
    Dim A2 As Integer
    Dim B1 As Integer
    Dim B2 As Integer
    
    'Variablen für Servoausgabe
    Dim Kanal As Byte
    Dim Servoausgabe_1 As Byte
    Dim Servoausgabe_2 As Byte
    Dim Servoausgabe_3 As Byte
    Dim Servoausgabe_4 As Byte
    
    
    '-------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------
    
    Kanal = 1
    
    Berechnung_1a = 187                                         'alle Servos erst mal auf Mittelstellung
    Berechnung_2a = 187
    Berechnung_3a = 187
    Berechnung_4a = 187
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00000111                                           'PA0 - PA2 werden Ausgänge, restlicher PortA bleibt Eingang
    Ddrb = &B00000001                                           'PB0 wird Ausgang, restlicher PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    'Info:
    'Alle Porta Pinchangeinterrupts sind "PCINT0" zugeordnet.
    'Alle Portb Pinchangeinterrupts sind "PCINT1" zugeordnet.
    
    
    Pcmsk1.pcint9 = 1                                           'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen
    Enable Pcint1                                               'Pinchangeinterrupt1 (1 weil auf PortB) zulassen
    On Pcint1 Rc_eingang_1 Nosave                               'Register werden manuel in der ISR gesichert
    
    
    Pcmsk0.pcint7 = 1                                           'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen
    Enable Pcint0                                               'Pinchangeinterrupt0 (0 weil auf PortA) zulassen
    On Pcint0 Rc_eingang_2 Nosave                               'Register werden manuel in der ISR gesichert
    
    
    Config Int0 = Change                                        'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen
    Enable Int0
    On Int0 Rc_eingang_3 Nosave                                 'Register werden manuel in der ISR gesichert
    
    Enable Interrupts
    
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
    
    
    'RC Impulslänge berechnen, auf 8-Bit umrechnen und Grenzwerte festlegen
    
      If Rc_signal_1_stop_flag = 1 Then                         'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Pcint1                                        'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_1 = Rc_signal_1_stop - Rc_signal_1_start
          Enable Pcint1
          Rc_signal_1_stop_flag = 0
    
          Impulslaengenaenderung = Impulslaenge_1_alt - Impulslaenge_1       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
             Impulslaenge_1_alt = Impulslaenge_1
    
             Berechnung_1 = Impulslaenge_1
             Shift Berechnung_1 , Right , 3                     'Division von Berechnung_1 durch 8
             If Berechnung_1 > 255 Then Berechnung_1 = 255
             If Berechnung_1 < 120 Then Berechnung_1 = 120
          End If
      End If
    
    
      If Rc_signal_2_stop_flag = 1 Then                         'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Pcint0                                        'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_2 = Rc_signal_2_stop - Rc_signal_2_start
          Enable Pcint0
          Rc_signal_2_stop_flag = 0
    
          Impulslaengenaenderung = Impulslaenge_2_alt - Impulslaenge_2       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
             Impulslaenge_2_alt = Impulslaenge_2
    
             Berechnung_2 = Impulslaenge_2
             Shift Berechnung_2 , Right , 3                     'Division von Berechnung_1 durch 8
             If Berechnung_2 > 255 Then Berechnung_2 = 255
             If Berechnung_2 < 120 Then Berechnung_2 = 120
          End If
      End If
    
    
      If Rc_signal_3_stop_flag = 1 Then                         'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Int0                                          'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_3 = Rc_signal_3_stop - Rc_signal_3_start
          Enable Int0
          Rc_signal_3_stop_flag = 0
          Impulslaengenaenderung = Impulslaenge_3_alt - Impulslaenge_3       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
             Impulslaenge_3_alt = Impulslaenge_3
    
             Berechnung_3 = Impulslaenge_3
             Shift Berechnung_3 , Right , 3                     'Division von Berechnung_1 durch 8
             If Berechnung_3 > 255 Then Berechnung_3 = 255
             If Berechnung_3 < 120 Then Berechnung_3 = 120
          End If
      End If
    
    
    
    
    
    '--------------------------------------------------
    'Start der größten IF Bedingung (Betriebsmodewahl)
    'FAHRBETRIEB
    '--------------------------------------------------
    
    If Berechnung_3 < 187 Then                                  'falls der Betriebswahlkanal unter Mittelstellung ist, ist Fahrbetrieb
    '(
    'Hier wird durchgeschleift, NUR für Testzwecke!
    Berechnung_3a = Berechnung_1                                'Werte vom ersten RC Kanal gehen zu Fahrservo 1
    Berechnung_4a = Berechnung_2                                'Werte vom zweiten RC Kanal gehen zu Fahrservo 2
    'Ende durchschleifen
    ')
    
    'Hier wird gemischt (Deltamischer)
    A1 = Berechnung_1 - 187                                     ' Mittelstellung nun bei 0, Auschläge von -67 bis +67
    A2 = Berechnung_2 - 187
    
    A1 = A1 / 2                                                 ' Werte halbieren (Mischanteile)
    'A2 = A2 / 2
    
    B1 = A1 + A2
    B2 = A1 - A2
    
    B1 = 185 + B1                                               ' Unterschiedliche Ausgangswerte wegen Nullpunktjustierung!
    B2 = 188 + B2
    
    Berechnung_3a = B1
    Berechnung_4a = B2
    
    'Ende der Mischer Berechnung
    
    
    If Berechnung_3a < 120 Then                                 'Werte begrenzen
    Berechnung_3a = 120
    End If
    If Berechnung_3a > 255 Then
    Berechnung_3a = 255
    End If
    
    If Berechnung_4a < 120 Then
    Berechnung_4a = 120
    End If
    If Berechnung_4a > 255 Then
    Berechnung_4a = 255
    End If
    
    
    
    '--------------------------------------------------
    'BAGGERETRIEB
    '--------------------------------------------------
    
    Else                                                        'falls Betriebswahlschalter über Mittelstellung ist, ist Baggerbetrieb
    
    Berechnung_3a = 187                                         ' Fahrservos in Mittelstellung
    Berechnung_4a = 187                                         ' Fahrservos in Mittelstellung
    
    
    'Berechnung der Servogeschwindigkeit und Servostellung
    
    'Erstes Baggerarmservo
    If Berechnung_1 < 182 Then                                  'Info: Todband (Mittelstellung) liegt zwischen 182 und 193
       Servospeed = Berechnung_1 - 120                          'ergibt Werte zwischen 0 (schnell) und 61 (langsam)
       Servospeed = Servospeed * 100                            'Werte hochscalieren (Faktor 30 bis 100, höherer Faktor = langsamere minimal Speed)
       For I = 1 To Servospeed                                  'Werte von 0 (schnell) bis max 6100 (langsam) sinnvoll
       Next I
       Decr Berechnung_1a
    End If
    
    If Berechnung_1 > 193 Then
       Servospeed = 255 - Berechnung_1
       Servospeed = Servospeed * 100
       For I = 1 To Servospeed
       Next I
       Incr Berechnung_1a
    End If
    
    'Zweites Baggerarmservo
    If Berechnung_2 < 182 Then                                  'Info: Todband (Mittelstellung) liegt zwischen 182 und 193
       Servospeed = Berechnung_2 - 120                          'ergibt Werte zwischen 0 (schnell) und 61 (langsam)
       Servospeed = Servospeed * 100                            'Werte hochscalieren (Faktor 30 bis 100, höherer Faktor = langsamere minimal Speed)
       For I = 1 To Servospeed                                  'Werte von 0 (schnell) bis max 6100 (langsam) sinnvoll
       Next I
       Decr Berechnung_2a
    End If
    
    If Berechnung_2 > 193 Then
       Servospeed = 255 - Berechnung_2
       Servospeed = Servospeed * 100
       For I = 1 To Servospeed
       Next I
       Incr Berechnung_2a
    End If
    
    
    'Potis abfragen und Werte für Servolimits berechnen
    
    Poti_1a = Getadc(3)
    Poti_1a = Poti_1a / 16                                      '1024 / 16 = 62,5 ergibt ca 25% Wegbegrenzung
    Limit_1a = 255 - Poti_1a
    
    Poti_1b = Getadc(4)
    Poti_1b = Poti_1b / 16
    Limit_1b = 120 + Poti_1b
    
    Poti_2a = Getadc(5)
    Poti_2a = Poti_2a / 16
    Limit_2a = 255 - Poti_2a
    
    Poti_2b = Getadc(6)
    Poti_2b = Poti_2b / 16
    Limit_2b = 120 + Poti_2b
    
    
    'RC Signal auf Limitwerte begrenzen (nur Baggerarmservos)
    
    If Berechnung_1a > Limit_1a Then                            'zu hohe Werte abfangen
       Berechnung_1a = Limit_1a
    End If
    If Berechnung_1a < Limit_1b Then                            'zu kleine Werte abfangen
       Berechnung_1a = Limit_1b
    End If
    
    
    If Berechnung_2a > Limit_2a Then
       Berechnung_2a = Limit_2a
    End If
    If Berechnung_2a < Limit_2b Then
       Berechnung_2a = Limit_2b
    End If
    
    
    ' Ende der größten IF Bedingung
    End If
    
    'Finale Berechnungen an Servoausgabe übergeben, Servoausgabe_x zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
    
    Servoausgabe_1 = 256 - Berechnung_1a                        'Baggerarmservo 1,
    Servoausgabe_2 = 256 - Berechnung_2a                        'Baggerarmservo 2
    Servoausgabe_3 = 256 - Berechnung_3a                        'Fahrservo oder ESC 1
    Servoausgabe_4 = 256 - Berechnung_4a                        'Fahrservo oder ESC 2
    
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    
    Rc_eingang_1:
     $asm
       push r17                                                 'Register auf Stack sichern
       sbis pinb , 1                                            'Skip next Instr if PINBx = 1
       rjmp Puls_ende1                                          'Springe Puls_ende
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende1                                               'Springe zum Ende
      Puls_ende1:
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_1_stop} , r17                             'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_1_stop} + 1 , r17                         'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_1_stop_flag} , r17                        'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende1:
       pop r17                                                  'Register vom Stack zurückholen
     $end Asm
    Return
    
    Rc_eingang_2:
     $asm
       push r17                                                 'Register auf Stack sichern
       sbis pinA , 7                                            'Skip next Instr if PINBx = 1
       rjmp Puls_ende2                                          'Springe Puls_ende
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_2_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_2_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende2                                               'Springe zum Ende
      Puls_ende2:
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_2_stop} , r17                             'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_2_stop} + 1 , r17                         'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_2_stop_flag} , r17                        'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende2:
       pop r17                                                  'Register vom Stack zurückholen
     $end Asm
    Return
    
    Rc_eingang_3:
     $asm
       push r17                                                 'Register auf Stack sichern
       sbis pinB , 2                                            'Skip next Instr if PINBx = 1
       rjmp Puls_ende3                                          'Springe Puls_ende
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_3_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_3_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende3                                               'Springe zum Ende
      Puls_ende3:
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_3_stop} , r17                             'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_3_stop} + 1 , r17                         'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_3_stop_flag} , r17                        'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende3:
       pop r17                                                  'Register vom Stack zurückholen
     $end Asm
    Return
    
    
    
    
    Servoausgabe:
    
     $asm
       push r16                                                 'Register auf Stack sichern
       in r16,sreg                                              'Statusregister holen und halten
       push r17                                                 'Register auf Stack sichern
       lds r17 , {kanal}                                        'hole Kanalnummer
    
       cpi r17 , 1                                              'check Kanal und ...
       brne LABEL_KANAL_2                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic portB , 0                                           'Skip next instr. wenn PORTA.0 = 0 ist
       rjmp label_1                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_1}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi portB , 0                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_1:
       cbi portB , 0                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    
      Label_kanal_2:                                            'Bearbeitung von Kanal 2
       cpi r17 , 2                                              'check Kanal und ...
       brne LABEL_KANAL_3                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 0                                           'Skip next instr. wenn PORTA.1 = 0 ist
       rjmp label_2                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_2}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi porta , 0                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_2:
       cbi porta , 0                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    
      Label_kanal_3:                                            'Bearbeitung von Kanal 3
       cpi r17 , 3                                              'check Kanal und ...
       brne LABEL_KANAL_4                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 1                                           'Skip next instr. wenn PORTA.2 = 0 ist
       rjmp label_3                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_3}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi porta , 1                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_3:
       cbi porta , 1                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    
      Label_kanal_4:                                            'Bearbeitung von Kanal 4
       cpi r17 , 4                                              'check Kanal und ...
       brne LABEL_KANAL_5                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 2                                           'Skip next instr. wenn PORTA.3 = 0 ist
       rjmp label_4                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_4}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi porta , 2                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_4:
       cbi porta , 2                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    'Pausenauffüllung
    
       'Pausenanfang
       inc r17
       sts {kanal} , r17                                        'Sichere Kanalnummer
       ldi r17 , &B00000101                                     'CS00 und CS02 für prescaler 1024 in Timer0 vorbereiten
       Out Tccr0b , R17                                         'Timer0 läuft mit 128µs Auflösung
       ldi r17 , 162                                            'Wert für ca 12ms bis zum nächsten OVF (162=256-94) bei prescaler 1024
       Out Tcnt0 , R17
       rjmp Ende_isr                                            'Springe zum Ende der ISR
    
      'Pausenende
      Label_kanal_5:                                            'Bearbeitung von Kanal 5 (Pausenende)
       ldi r17 , &B00000011                                     'CS00 und CS01 für prescaler 64 in Timer0 vorbereiten
       Out Tccr0b , R17                                         'Timer0 läuft wieder mit 8µs Auflösung
       ldi r17 , 1                                              'Kanalnummer auf 1 setzen
       sts {kanal} , r17                                        'Sichere Kanalnummer
      Ende_isr:
       pop r17                                                  'Register vom Stack zurückholen
       Out Sreg , R16                                           'Statusregister zurückspeichern
       pop r16                                                  'Register vom Stack zurückholen
     $end Asm
    
    Return

    Ich experimentier dann auch mal weiter.

    mfg
    Robert

  5. #35
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    Meine Vermutung ist nun folgende: Wenn das Servo langsam losfährt, ist die Variable "Servospeed" in der For-Next Schleife sehr groß. Auch wenn ich den Knüppel nun schlagartig auf Endandanschlag bringe, findet ja keine neue Berechnung der Variable "Servospeed" statt. Wenn also Servospeed sehr groß ist und ich den Knüppel nicht wieder in Mittelstellung bringe (um aus der ganzen IF Bedingung raus zu kommen), fährt das Servo nur mit Minimalgeschwindigkeit bis zum Anschlag.
    Ich habe leider keine rechte Vorstellung, wie der Bagger reagiert, vielleicht auch weil ich selbst keine Modellbaufernbedienung habe.
    Auf jeden Fall darf die Zeit zwischen den Abfragen der Rc_signal_stop_flags nicht länger sein als der Abstand zweier Impulse an dem Eingang. Anders: die Laufzeit einer Runde in der Hauptschleife darf nicht länger sein als der Abstand zweier Impulse, da es sonst zu Fehlmessungen kommen kann (Flag wird nicht zurückgesetzt und Rc_signal_start wird neu gesetzt und Rc_signal_stop noch nicht. Dazwischen bis zu 2ms Zeit Fehler zu produzieren. Gefahr könnte man auf die Schnelle durch Maßnahmen in den ISR vermindern aber nicht ganz ausschließen. Einfacher und besser ist es die Hauptschleife schneller zu machen.

    Die For-Next Schleifen können das Hauptprogramm bis zu 70ms aufhalten - grob im Simulator getestet.

    Das sollte erstmal eliminiert werden. Hoffe mein Vorschlag funktioniert wenigstens ansatzweise.
    Er basiert auf der zusätzlichen Nutzung von Timer1 zur Zeitmessung, so daß das Hauptprogramm nicht aufgehalten wird.

    Sobald Timer1 läuft, werden auch nach spätestens 66ms die OCF1A und OCF1B Comparematch Interruptflags gesetzt und bleiben gesetzt, da ja da kein Interrupt drauf aktiviert ist.

    Die werden in meinem Vorschlag abgefragt, gelöscht, wenn sie gesetzt sind und die OCR1x Register mit Wartezeiten geladen. Damit werden zusätzlich Interrupts zur Zeitmessung vermieden, allerdings sind Wartezeiten etwas abhängig von Programmverzweigungen (kann ich nicht überblicken, sollte aber im Verhältnis kaum ins Gewicht fallen?)

    Die INCR und DECR der "Berechnung_xA" findet sofort ohne Wartezeit statt. Kann man später noch mit Flagsteuerung ändern - möchte nur erstmal wissen ob es im Prinzip so akzeptabel ist (und zuallererst ob es überhaupt funktioniert - wenn vielleicht auch das Knüppelsteuerungsreißproblem noch nicht behoben wird )

    Dies hier also mit dem weiter unten stehenden ersetzten.
    Code:
    'Berechnung der Servogeschwindigkeit und Servostellung
    
    'Erstes Baggerarmservo
    If Berechnung_1 < 182 Then                                  'Info: Todband (Mittelstellung) liegt zwischen 182 und 193
       Servospeed = Berechnung_1 - 120                          'ergibt Werte zwischen 0 (schnell) und 61 (langsam)
       Servospeed = Servospeed * 100                            'Werte hochscalieren (Faktor 30 bis 100, höherer Faktor = langsamere minimal Speed)
       For I = 1 To Servospeed                                  'Werte von 0 (schnell) bis max 6100 (langsam) sinnvoll
       Next I
       Decr Berechnung_1a
    End If
    
    If Berechnung_1 > 193 Then
       Servospeed = 255 - Berechnung_1
       Servospeed = Servospeed * 100
       For I = 1 To Servospeed
       Next I
       Incr Berechnung_1a
    End If
    
    'Zweites Baggerarmservo
    If Berechnung_2 < 182 Then                                  'Info: Todband (Mittelstellung) liegt zwischen 182 und 193
       Servospeed = Berechnung_2 - 120                          'ergibt Werte zwischen 0 (schnell) und 61 (langsam)
       Servospeed = Servospeed * 100                            'Werte hochscalieren (Faktor 30 bis 100, höherer Faktor = langsamere minimal Speed)
       For I = 1 To Servospeed                                  'Werte von 0 (schnell) bis max 6100 (langsam) sinnvoll
       Next I
       Decr Berechnung_2a
    End If
    
    If Berechnung_2 > 193 Then
       Servospeed = 255 - Berechnung_2
       Servospeed = Servospeed * 100
       For I = 1 To Servospeed
       Next I
       Incr Berechnung_2a
    End If


    Hab grob versucht die gleiche Wartzeit hinzukriegen. Original for-next mit servospeed=61*100=6100 -> maximal 35ms. jetzt 61*500 = 30500µs = 30,5ms
    Code:
    If Tifr1.ocf1a = 1 And Berechnung_1 < 182 Then
        Set Tifr1.ocf1a                     'Interruptflag löschen
        Servospeed = Berechnung_1 - 120
        Servospeed = Servospeed * 500       'eine Einheit in Servospeed macht 1µs Wartezeit
        'sicherheitszeit 1000µs damit bei kleinen Werten kein kompletter timer rundlauf bis zum nächsten
        'comparematch abgewartet werden muß. Länger sollte auch eine Runde in der Hauptschleife nicht dauern.
        If Servospeed < 1000 Then Servospeed = 1000       'Sicherheitszeit
        Ocr1a = Tcnt1 + Servospeed          'Setzen von OCR1A damit nach Servospeed ein Compare Match auftritt
        Decr Berechnung_1a
    End If
    
    If Tifr1.ocf1a = 1 And Berechnung_1 > 193 Then
        Set Tifr1.ocf1a
        Servospeed = 255 - Berechnung_1
        Servospeed = Servospeed * 500
        If Servospeed < 1000 Then Servospeed = 1000       'Sicherheitszeit
        Ocr1a = Tcnt1 + Servospeed
        Incr Berechnung_1a
    End If
    
    If Tifr1.ocf1b = 1 And Berechnung_2 < 182 Then
        Set Tifr1.ocf1b
        Servospeed = Berechnung_2 - 120
        Servospeed = Servospeed * 500
        If Servospeed < 1000 Then Servospeed = 1000       'Sicherheitszeit
        Ocr1b = Tcnt1 + Servospeed
        Decr Berechnung_2a
    End If
    
    If Tifr1.ocf1b = 1 And Berechnung_2 > 193 Then
        Set Tifr1.ocf1b
        Servospeed = 255 - Berechnung_2
        Servospeed = Servospeed * 500
        If Servospeed < 1000 Then Servospeed = 1000       'Sicherheitszeit
        Ocr1b = Tcnt1 + Servospeed
        Incr Berechnung_2a
    End If
    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  6. #36
    Hallo zusammen,

    habs gerade probiert, wurde leider noch schlimmer

    Wenn der Knüppel schnell bewegt wird, fährt das Servo oft wieder nur langsam. Wird in dieser Zeit auch noch der andere Küppel für das zweite Servo bewegt, läuft plötzlich das erste Servo schneller. Beeinflussen sich also beide gegenseitig.

    Meine Codeumsetzung war diese (funktioniert aber auch nicht!!!)
    Code:
    'Erstes Baggerarmservo
    If Berechnung_1 < 182 Then                                  'Info: Todband (Mittelstellung) liegt zwischen 182 und 193
       Servospeed = Berechnung_1 - 120                          'ergibt Werte zwischen 0 (schnell) und 61 (langsam)
       Servospeed = Servospeed * 1000                           'Werte hochscalieren 0 (schnell) und 61000 (langsam)
    
       Ocr1a = Timer1 + Servospeed
       Tifr1.ocf1a = 1                                          'OCF1A Flag löschen (set to 1)
       If Tifr1.ocf1a = 0 Then Incr Zeit_1                      'wenn OCF1A erreicht ist (OCF1A Flag = 0), dann Zeit_1 um 1 erhöhen
       If Zeit_1 = 50 Then                                      'zusätzliche Zeitbasis, da Timer1 nur bis 65535 zählen kann
          Decr Berechnung_1a
          Zeit_1 = 0
       End If
    End If
    @Searcher

    Du frägst bei den IF Bedingungen "Tifr1.ocf1a = 1" ab um in die Schleife zu kommen und benutzt dann den Befehl "Set Tifr1.ocf1a". Wird damit nicht das entsprechende Bit (Tifr1.ocf1a) auf 1 gesetzt (welches Du ja bereits vorher zur Bedingung zum Eintritt in die Schleife ohnehin auf 1 gebraucht hast)


    mfg
    Robert

  7. #37
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Hallo,
    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    habs gerade probiert, wurde leider noch schlimmer
    Wenn mein Code zur Verkürzung der Hauptschleife im Prinzip funktioniert, die Auswirkungen aber schlimmer werden, laß ihn drin (bis eindeutig feststeht, daß er weitere Fehler produziert). Die "Sicherheitszeit kann man auch auf 2000 oder 3000 µs erhöhen.

    Muß man also weiter nach Bugs suchen. Bin im Augenblick ratlos

    @Searcher
    Du frägst bei den IF Bedingungen "Tifr1.ocf1a = 1" ab um in die Schleife zu kommen und benutzt dann den Befehl "Set Tifr1.ocf1a". Wird damit nicht das entsprechende Bit (Tifr1.ocf1a) auf 1 gesetzt (welches Du ja bereits vorher zur Bedingung zum Eintritt in die Schleife ohnehin auf 1 gebraucht hast)
    Ja, ist was Besonderes bei den Interruptflags allgemein. Auszug aus Datenblatt:
    "OCF1A is automatically cleared when the Output Compare Match A Interrupt Vector is exe-cuted. Alternatively, OCF1A can be cleared by writing a logic one to its bit location."

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  8. #38
    Hallo Searcher,

    vergiss mein letztes Posting, ich glaube mein Attiny ist jetzt den Flash-Tod gestorben. Ich habs jetzt mit einem anderen probiert, scheint zu funktionieren. Einzig was mir noch auffällt ist, dass die Servos in eine Richtung schneller unterwegs sind, als in die andere. Ich bin grad dabei heraus zu finden, welche Passage im Code die "schnellen" bzw "langsamen" sind.

    Melde mich dann wieder.

    mfg
    Robert

  9. #39
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    @R2D2 Bastler: Ohhh, ich seh gerade, daß bei Dir bei "On Timer0 ..." ganz oben das "nosave" fehlt!

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  10. #40
    Zitat Zitat von Searcher Beitrag anzeigen
    @R2D2 Bastler: Ohhh, ich seh gerade, daß bei Dir bei "On Timer0 ..." ganz oben das "nosave" fehlt!
    Danke, wir sind ja mittlerweile bei Version 23 und unzähligen Experimenten zusätzlich, ist mir durch die Lappen gegangen

    Habe nun weiter getestet.

    Die unterschiedlichen Geschwindigkeiten liegen offensichtlich daran, dass bei Mittelstellung der Knüppel die RC-Signale nicht exakt bei 1,5 ms liegen. Ob das nun von der Fernbedienung, vom Empfänger oder vom Programm "verschludert" wird, kann ich nicht rausmessen. Ist aber kein Problem, dafür gibt es die Funktion "Subtrimm" bei nahezu jeder Funke. Es fehlt ja nur wenige Klicks.

    Des weiteren werde ich wohl die Grenzwerte noch etwas enger stecken müssen, also für den einen Anschlag 125 anstelle von 120, für den anderen Anschlag 250 anstelle von 255. Meine Fernbedienung erreicht sonst teilweise nicht die Werte für die Endanschläge. Ich verliere dabei zwar 10 Schritte der Auflösung, aber die Ausschläge meiner Fernbedienung stehen schon bei 125%, weiter kann ich sie nicht hochstellen.

    Werde dann nochmal berichten,

    mfg
    Robert

    - - - Aktualisiert - - -

    Ich glaub das Ding geht, es geeeeeehhhhhhhhhhht

    Ich hab noch mit einigen Zahlen gespielt, hier und da ein paar kleine Veränderungen vorgenommen und das ganze ausgiebig getestet. Grinse gerade von einem Ohr bis zum anderen

    Dank zahlreicher Hilfe hier im Forum, sowie unzähligen PM, läuft das Teil nun besser als erwartet.

    Das Programm wird auf jeden Fall meine Codegrundlage für weitere RC-Geschichten, bei denen mehrere RC Signale auf einem Chip zeitkritisch ein- bzw ausgegeben werden müssen. Mal sehen, ob und wie sich eine "Mehr-Chip-Variante" entwickelt (bessere Auflösung etc).

    Bastle noch an einer Single-Baggerarm Steuerung (1 Eingang, 1 Ausgang auf einem kleineren Attiny45). Ergebnisse werd ich hier noch nachreichen.

    Hänge den fertigen Code nochmal mit dran.

    mfg
    Robert

    Code:
    '===============================================================================
    'BAGGER Steuerung V23
    '
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)  Stick 1 (Aileron)
    'RC Eingang 2 an Pin 6 (PA7, PCINT7)  Stick 2 (Elevator)
    'RC Eingang 3 an Pin 5 (PB2, INT0)    Betriebsmode
    'Poti 1a an Pin 10 (PA3, ADC3)
    'Poti 1b an Pin 9 (PA4, ADC4)
    'Poti 2a an Pin 8 (PA5, ADC5)
    'Poti 2b an Pin 7 (PA6, ADC6)
    'Servo 1 an Pin 2 (PB0)  Baggerarmservo
    'Servo 2 an Pin 13 (PA0) Baggerarmservo
    'Servo 3 an Pin 12 (PA1) Kettenantrieb
    'Servo 4 an Pin 11 (PA2) Kettenantrieb
    '
    '===============================================================================
    
    $regfile = "attiny84.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 50
    $swstack = 50
    $framesize = 50
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8                        'Timer für Einlesen RC Signale
    Start Timer1
    
    Config Timer0 = Timer , Prescale = 64                       'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms
    Enable Timer0
    On Timer0 Servoausgabe Nosave
    
    
    '-------------------------------------------------------------------------------------------------
    'Poti-Eingänge konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Adc = Single , Prescaler = Auto
    Start Adc
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Konstanten definieren
    '-------------------------------------------------------------------------------------------------------------
    Const Jitterausgleich = 8                                   'Wert in µs um den sich gemessene Impulslaenge aendern darf/muss, bevor Servo gestellt wird
                                                                 'Nur in Vielfachen von 8 veraendern (8, 16, 32, ..)
    Const Rc_min = 122                                          'Minimaler RC-Wert für die Berechnungen (Werte zwischen 120 - 125 sinvoll)
    Const Rc_max = 253                                          'Maximaler RC-Wert für die Berechnungen (Werte zwischen 250 - 255 sinvoll)
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    'Variablen fürs RC Einlesen
    Dim Rc_signal_1_start As Word
    Dim Rc_signal_2_start As Word
    Dim Rc_signal_3_start As Word
    
    Dim Rc_signal_1_stop As Word
    Dim Rc_signal_2_stop As Word
    Dim Rc_signal_3_stop As Word
    
    Dim Rc_signal_1_stop_flag As Byte
    Dim Rc_signal_2_stop_flag As Byte
    Dim Rc_signal_3_stop_flag As Byte
    
    Dim Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    Dim Impulslaenge_1_alt As Word
    Dim Impulslaenge_2_alt As Word
    Dim Impulslaenge_3_alt As Word
    
    Dim Impulslaengenaenderung As Integer                       'wird nur einmal gebraucht, da nur Hilfswariable
    
    
    'Variablen für Servowegsbegrenzung
    Dim Poti_1a As Word
    Dim Poti_1b As Word
    Dim Poti_2a As Word
    Dim Poti_2b As Word
    
    Dim Limit_1a As Byte
    Dim Limit_1b As Byte
    Dim Limit_2a As Byte
    Dim Limit_2b As Byte
    
    
    'Variablen für Berechnungen
    Dim Berechnung_1 As Word
    Dim Berechnung_2 As Word
    Dim Berechnung_3 As Word
    Dim Berechnung_4 As Word
    
    Dim Berechnung_1a As Word
    Dim Berechnung_2a As Word
    Dim Berechnung_3a As Word
    Dim Berechnung_4a As Word
    
    Dim Servospeed As Word
    
    'Variable für Deltamischer
    Dim A1 As Integer
    Dim A2 As Integer
    Dim B1 As Integer
    Dim B2 As Integer
    
    'Variablen für Servoausgabe
    Dim Kanal As Byte
    
    Dim Servoausgabe_1 As Byte
    Dim Servoausgabe_2 As Byte
    Dim Servoausgabe_3 As Byte
    Dim Servoausgabe_4 As Byte
    
    
    '-------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------
    
    Kanal = 1
    
    Berechnung_1a = 187                                         'alle Servos erst mal auf Mittelstellung
    Berechnung_2a = 187
    Berechnung_3a = 187
    Berechnung_4a = 187
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00000111                                           'PA0 - PA2 werden Ausgänge, restlicher PortA bleibt Eingang
    Ddrb = &B00000001                                           'PB0 wird Ausgang, restlicher PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    'Info:
    'Alle Porta Pinchangeinterrupts sind "PCINT0" zugeordnet.
    'Alle Portb Pinchangeinterrupts sind "PCINT1" zugeordnet.
    
    
    Pcmsk1.pcint9 = 1                                           'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen
    Enable Pcint1                                               'Pinchangeinterrupt1 (1 weil auf PortB) zulassen
    On Pcint1 Rc_eingang_1 Nosave                               'Register werden manuel in der ISR gesichert
    
    
    Pcmsk0.pcint7 = 1                                           'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen
    Enable Pcint0                                               'Pinchangeinterrupt0 (0 weil auf PortA) zulassen
    On Pcint0 Rc_eingang_2 Nosave                               'Register werden manuel in der ISR gesichert
    
    
    Config Int0 = Change                                        'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen
    Enable Int0
    On Int0 Rc_eingang_3 Nosave                                 'Register werden manuel in der ISR gesichert
    
    Enable Interrupts
    
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
    
    'RC Impulslänge berechnen, auf 8-Bit umrechnen und Grenzwerte festlegen
    
      If Rc_signal_1_stop_flag = 1 Then                         'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Pcint1                                        'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_1 = Rc_signal_1_stop - Rc_signal_1_start
          Enable Pcint1
          Rc_signal_1_stop_flag = 0
    
          Impulslaengenaenderung = Impulslaenge_1_alt - Impulslaenge_1       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
             Impulslaenge_1_alt = Impulslaenge_1
    
             Berechnung_1 = Impulslaenge_1
             Shift Berechnung_1 , Right , 3                     'Division von Berechnung_1 durch 8
             If Berechnung_1 > Rc_max Then Berechnung_1 = Rc_max
             If Berechnung_1 < Rc_min Then Berechnung_1 = Rc_min
          End If
      End If
    
    
      If Rc_signal_2_stop_flag = 1 Then                         'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Pcint0                                        'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_2 = Rc_signal_2_stop - Rc_signal_2_start
          Enable Pcint0
          Rc_signal_2_stop_flag = 0
    
          Impulslaengenaenderung = Impulslaenge_2_alt - Impulslaenge_2       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
             Impulslaenge_2_alt = Impulslaenge_2
    
             Berechnung_2 = Impulslaenge_2
             Shift Berechnung_2 , Right , 3                     'Division von Berechnung_1 durch 8
             If Berechnung_2 > Rc_max Then Berechnung_2 = Rc_max
             If Berechnung_2 < Rc_min Then Berechnung_2 = Rc_min
          End If
      End If
    
    
      If Rc_signal_3_stop_flag = 1 Then                         'Bearbeitung nur, wenn ISR Pulsende gefunden hat
          Disable Int0                                          'Mögliche Korruption durch ISR vorbeugen
          Impulslaenge_3 = Rc_signal_3_stop - Rc_signal_3_start
          Enable Int0
          Rc_signal_3_stop_flag = 0
          Impulslaengenaenderung = Impulslaenge_3_alt - Impulslaenge_3       'SW-Hysterese
          If Abs(impulslaengenaenderung) >= Jitterausgleich Then
             Impulslaenge_3_alt = Impulslaenge_3
    
             Berechnung_3 = Impulslaenge_3
             Shift Berechnung_3 , Right , 3                     'Division von Berechnung_1 durch 8
             If Berechnung_3 > Rc_max Then Berechnung_3 = Rc_max
             If Berechnung_3 < Rc_min Then Berechnung_3 = Rc_min
          End If
      End If
    
    
    
    
    
    '--------------------------------------------------
    'Start der größten IF Bedingung (Betriebsmodewahl)
    'FAHRBETRIEB
    '--------------------------------------------------
    
    If Berechnung_3 < 187 Then                                  'falls der Betriebswahlkanal unter Mittelstellung ist, ist Fahrbetrieb
    '(
    'Hier wird durchgeschleift, NUR für Testzwecke!
    Berechnung_3a = Berechnung_1                                'Werte vom ersten RC Kanal gehen zu Fahrservo 1
    Berechnung_4a = Berechnung_2                                'Werte vom zweiten RC Kanal gehen zu Fahrservo 2
    'Ende durchschleifen
    ')
    
    'Hier wird gemischt (Deltamischer)
    A1 = Berechnung_1 - 187                                     ' Mittelstellung nun bei 0, Auschläge von -67 bis +67
    A2 = Berechnung_2 - 187
    
    A1 = A1 / 2                                                 ' Werte halbieren (Mischanteile)
    'A2 = A2 / 2
    
    B1 = A1 + A2
    B2 = A1 - A2
    
    B1 = 185 + B1                                               ' Unterschiedliche Ausgangswerte wegen Nullpunktjustierung!
    B2 = 188 + B2
    
    Berechnung_3a = B1
    Berechnung_4a = B2
    
    'Ende der Mischer Berechnung
    
    
    If Berechnung_3a < Rc_min Then                              'Werte begrenzen
    Berechnung_3a = Rc_min
    End If
    If Berechnung_3a > Rc_max Then
    Berechnung_3a = Rc_max
    End If
    
    If Berechnung_4a < Rc_min Then
    Berechnung_4a = Rc_min
    End If
    If Berechnung_4a > Rc_max Then
    Berechnung_4a = Rc_max
    End If
    
    
    
    '--------------------------------------------------
    'BAGGERETRIEB
    '--------------------------------------------------
    
    Else                                                        'falls Betriebswahlschalter über Mittelstellung ist, ist Baggerbetrieb
    
    'Berechnung_3a = 187                                         ' Fahrservos in Mittelstellung
    'Berechnung_4a = 187                                         ' Fahrservos in Mittelstellung
    
    
    'Berechnung der Servogeschwindigkeit und Servostellung
    
    If Tifr1.ocf1a = 1 And Berechnung_1 < 182 Then
        Set Tifr1.ocf1a                                         'Interruptflag löschen
        Servospeed = Berechnung_1 - Rc_min
        Servospeed = Servospeed * 500                           'eine Einheit in Servospeed macht 1µs Wartezeit
        If Servospeed < 1000 Then Servospeed = 1000             'Sicherheitszeit 1000µs damit bei kleinen Werten kein kompletter timer rundlauf bis zum nächsten
                                                                'comparematch abgewartet werden muß. Länger sollte auch eine Runde in der Hauptschleife nicht dauern.
        Ocr1a = Tcnt1 + Servospeed                              'Setzen von OCR1A damit nach Servospeed ein Compare Match auftritt
        Decr Berechnung_1a
    End If
    
    If Tifr1.ocf1a = 1 And Berechnung_1 > 193 Then
        Set Tifr1.ocf1a
        Servospeed = Rc_max - Berechnung_1
        Servospeed = Servospeed * 500
        If Servospeed < 1000 Then Servospeed = 1000             'Sicherheitszeit
        Ocr1a = Tcnt1 + Servospeed
        Incr Berechnung_1a
    End If
    
    If Tifr1.ocf1b = 1 And Berechnung_2 < 182 Then
        Set Tifr1.ocf1b
        Servospeed = Berechnung_2 - Rc_min
        Servospeed = Servospeed * 500
        If Servospeed < 1000 Then Servospeed = 1000             'Sicherheitszeit
        Ocr1b = Tcnt1 + Servospeed
        Decr Berechnung_2a
    End If
    
    If Tifr1.ocf1b = 1 And Berechnung_2 > 193 Then
        Set Tifr1.ocf1b
        Servospeed = Rc_max - Berechnung_2
        Servospeed = Servospeed * 500
        If Servospeed < 1000 Then Servospeed = 1000             'Sicherheitszeit
        Ocr1b = Tcnt1 + Servospeed
        Incr Berechnung_2a
    End If
    
    
    'Potis abfragen und Werte für Servolimits berechnen
    
    Poti_1a = Getadc(3)
    Poti_1a = Poti_1a / 25                                      '1024 / 25 = 41, ergibt ca 30% Wegbegrenzung
    Limit_1a = 255 - Poti_1a
    
    Poti_1b = Getadc(4)
    Poti_1b = Poti_1b / 25
    Limit_1b = 120 + Poti_1b
    
    Poti_2a = Getadc(5)
    Poti_2a = Poti_2a / 25
    Limit_2a = 255 - Poti_2a
    
    Poti_2b = Getadc(6)
    Poti_2b = Poti_2b / 25
    Limit_2b = 120 + Poti_2b
    
    
    'RC Signal auf Limitwerte begrenzen (nur Baggerarmservos)
    
    If Berechnung_1a > Limit_1a Then                            'zu hohe Werte abfangen
       Berechnung_1a = Limit_1a
    End If
    If Berechnung_1a < Limit_1b Then                            'zu kleine Werte abfangen
       Berechnung_1a = Limit_1b
    End If
    
    
    If Berechnung_2a > Limit_2a Then
       Berechnung_2a = Limit_2a
    End If
    If Berechnung_2a < Limit_2b Then
       Berechnung_2a = Limit_2b
    End If
    
    
    ' Ende der größten IF Bedingung
    End If
    
    'Finale Berechnungen an Servoausgabe übergeben, Servoausgabe_x zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
    
    Servoausgabe_1 = 256 - Berechnung_1a                        'Baggerarmservo 1,
    Servoausgabe_2 = 256 - Berechnung_2a                        'Baggerarmservo 2
    Servoausgabe_3 = 256 - Berechnung_3a                        'Fahrservo oder ESC 1
    Servoausgabe_4 = 256 - Berechnung_4a                        'Fahrservo oder ESC 2
    
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    
    Rc_eingang_1:
     $asm
       push r17                                                 'Register auf Stack sichern
       sbis pinb , 1                                            'Skip next Instr if PINBx = 1
       rjmp Puls_ende1                                          'Springe Puls_ende
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende1                                               'Springe zum Ende
      Puls_ende1:
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_1_stop} , r17                             'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_1_stop} + 1 , r17                         'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_1_stop_flag} , r17                        'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende1:
       pop r17                                                  'Register vom Stack zurückholen
     $end Asm
    Return
    
    Rc_eingang_2:
     $asm
       push r17                                                 'Register auf Stack sichern
       sbis pinA , 7                                            'Skip next Instr if PINBx = 1
       rjmp Puls_ende2                                          'Springe Puls_ende
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_2_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_2_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende2                                               'Springe zum Ende
      Puls_ende2:
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_2_stop} , r17                             'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_2_stop} + 1 , r17                         'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_2_stop_flag} , r17                        'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende2:
       pop r17                                                  'Register vom Stack zurückholen
     $end Asm
    Return
    
    Rc_eingang_3:
     $asm
       push r17                                                 'Register auf Stack sichern
       sbis pinB , 2                                            'Skip next Instr if PINBx = 1
       rjmp Puls_ende3                                          'Springe Puls_ende
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_3_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_3_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
       rjmp ende3                                               'Springe zum Ende
      Puls_ende3:
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_3_stop} , r17                             'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_3_stop} + 1 , r17                         'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
       ldi r17 , 1
       sts {Rc_signal_3_stop_flag} , r17                        'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
      Ende3:
       pop r17                                                  'Register vom Stack zurückholen
     $end Asm
    Return
    
    
    
    
    Servoausgabe:
    
     $asm
       push r16                                                 'Register auf Stack sichern
       in r16,sreg                                              'Statusregister holen und halten
       push r17                                                 'Register auf Stack sichern
       lds r17 , {kanal}                                        'hole Kanalnummer
    
       cpi r17 , 1                                              'check Kanal und ...
       brne LABEL_KANAL_2                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic portB , 0                                           'Skip next instr. wenn PORTA.0 = 0 ist
       rjmp label_1                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_1}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi portB , 0                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_1:
       cbi portB , 0                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    
      Label_kanal_2:                                            'Bearbeitung von Kanal 2
       cpi r17 , 2                                              'check Kanal und ...
       brne LABEL_KANAL_3                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 0                                           'Skip next instr. wenn PORTA.1 = 0 ist
       rjmp label_2                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_2}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi porta , 0                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_2:
       cbi porta , 0                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    
      Label_kanal_3:                                            'Bearbeitung von Kanal 3
       cpi r17 , 3                                              'check Kanal und ...
       brne LABEL_KANAL_4                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 1                                           'Skip next instr. wenn PORTA.2 = 0 ist
       rjmp label_3                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_3}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi porta , 1                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_3:
       cbi porta , 1                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    
      Label_kanal_4:                                            'Bearbeitung von Kanal 4
       cpi r17 , 4                                              'check Kanal und ...
       brne LABEL_KANAL_5                                       '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 2                                           'Skip next instr. wenn PORTA.3 = 0 ist
       rjmp label_4                                             'Springe zum LOW-setzen des Servosignals
       sts {kanal} , r17                                        'Sichere Kanalnummer
       lds r17 , {Servoausgabe_4}                               'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R17                                          'Setze Timer0 mit Pulslängenwert
       sbi porta , 2                                            'Setze Servosignal HIGH
       rjmp Ende_isr                                            'Springe zum Ende der ISR
      Label_4:
       cbi porta , 2                                            'Setze Servosignal nach LOW
       inc r17                                                  'Erhöhe Kanalnummer
    
    'Pausenauffüllung
    
       'Pausenanfang
       inc r17
       sts {kanal} , r17                                        'Sichere Kanalnummer
       ldi r17 , &B00000101                                     'CS00 und CS02 für prescaler 1024 in Timer0 vorbereiten
       Out Tccr0b , R17                                         'Timer0 läuft mit 128µs Auflösung
       ldi r17 , 162                                            'Wert für ca 12ms bis zum nächsten OVF (162=256-94) bei prescaler 1024
       Out Tcnt0 , R17
       rjmp Ende_isr                                            'Springe zum Ende der ISR
    
      'Pausenende
      Label_kanal_5:                                            'Bearbeitung von Kanal 5 (Pausenende)
       ldi r17 , &B00000011                                     'CS00 und CS01 für prescaler 64 in Timer0 vorbereiten
       Out Tccr0b , R17                                         'Timer0 läuft wieder mit 8µs Auflösung
       ldi r17 , 1                                              'Kanalnummer auf 1 setzen
       sts {kanal} , r17                                        'Sichere Kanalnummer
      Ende_isr:
       pop r17                                                  'Register vom Stack zurückholen
       Out Sreg , R16                                           'Statusregister zurückspeichern
       pop r16                                                  'Register vom Stack zurückholen
     $end Asm
    
    Return

Seite 4 von 8 ErsteErste ... 23456 ... LetzteLetzte

Ähnliche Themen

  1. Mehrere analoge Werte über ein ADC einlesen möglich?
    Von HeXPloreR im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 07.08.2012, 18:18
  2. Schaltkreis für mehrere Servos
    Von Sebbokalypse im Forum Elektronik
    Antworten: 9
    Letzter Beitrag: 12.11.2009, 19:46
  3. Mehrere Signale umschalten
    Von flexxo im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 25.02.2007, 14:56
  4. Antworten: 9
    Letzter Beitrag: 02.04.2006, 18:53
  5. Mehrere Signale über einen Interrupt erkennen
    Von Minifriese im Forum Elektronik
    Antworten: 22
    Letzter Beitrag: 04.06.2004, 09:31

Berechtigungen

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

12V Akku bauen