- LiFePO4 Speicher Test         
Seite 1 von 8 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 75

Thema: Mehrere RC Signale einlesen und mehrere Servos ausgeben

  1. #1

    Mehrere RC Signale einlesen und mehrere Servos ausgeben

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen,

    ich möchte mehrere RC Signale einlesen und auf mehrere Servos ausgeben. Leider ist es mir das nach 2 Wochen noch immer nicht gelungen.
    Das ganze ist für eine Bagger Steuerung. Das fertige Programm soll 3 RC-Eingänge und 2 Poti-Eingänge einlesen, sowie 4 Servoausgänge ausgeben.

    Ein RC-Eingang fragt den Betriebsmode (Fahrbetrieb/Baggerbetrieb) ab.
    Zwei weitere RC-Eingänge bekommen die Signale von den Knüppelstellungen der Fernbedienung.
    Die Potis dienen der Servowegbegrenzung (vergleichbar mit DualRate).
    2 Servos gehen zum Baggerarm (je nach Betriebsmode aktiv).
    2 Servos zum Kettenanrieb (je nach Betriebsmode aktiv).

    Eine funktionierende ISR für die Servoausgabe habe ich bereits realisieren können, doch leider verträgt sich diese nicht mit dem Pulsein Befehl (die „romanartigen“ Kommentare im Programm sind nur für mich Voll-NOP, damit ich immer nachlesen kann, was das Programm gerade macht).
    Im folgenden Programm ist die Routine für 4 Servos ersichtlich. Zu Testzwecken wollte ich nur mal ein RC-Signal einlesen und ein Servo damit speisen. Ein weiteres Servo wurde ebenfalls angeschlossen und mit einem Festwert (hier 1500 für Mittelstellung) gespeist. Die ISR wird dabei offensichtlich korrekt abgearbeitet (erkennbar an dem Servo, welches nur die Mittelstellung halten soll). Allerdings zuckt das andere Servo erheblich hin und her. Es reagiert zwar auf die Eingaben am RC-Eingang (Servo folgt „grob“ dem RC-Signal), ist aber ansonsten nicht zu gebrauchen. Ich „vermute“, das die Springerei in die ISR den Pulsein Befehl stört, dadurch falsche Werte eingelesen werden und in folge davon das Servo zuckt. Schade, denn die Funktion dieses Programms hätte ich ausnahmsweise mal nachvollziehen können.

    Code:
    '===============================================================================
    'Baggersteuerung (ACHTUNG FUNKTIONIERT NICHT, SERVO RUCKELT EXTREM)
    
    'RC Empfangskanal 1 an Pin 6 (PA7)
    'RC Empfangskanal 2 an Pin 7 (PA6)
    'RC Empfangskanal 3 (Mode-Schalter) an Pin 5 (PB2)
    
    'Werte zwischen 100 und 200 entsprechen dem kompletten Knüppelweg
    'Der Wert 150 entspricht dabei ca. Mittelstellung, der Wert 200 ca. Vollausschlag
    
    'Poti Eingang 1 Pin 9 (PA4)
    'Poti Eingang 1 Pin 8 (PA5)
    
    'Servoausgang 1 Pin13 (PA0)
    'Servoausgang 2 Pin12 (PA1)
    'Servoausgang 3 Pin11 (PA2)
    'Servoausgang 4 Pin10 (PA3)
    
    'Made by Robert (www.roberts-r2d2-bau.de)
    '===============================================================================
    
    
    $regfile = "attiny24.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    
    $hwstack = 32
    $swstack = 20
    $framesize = 40
    
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    
    Dim Empfangskanal(3) As Word
    Dim Servo1_signal As Word
    
    Dim Kanal As Byte
    Dim Servo(4) As Word
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00001111                                           'PA0, PA1, PA2 und PA3 werden Ausgänge, der restliche Port A bleibt Eingang
    Ddrb = &B00000000                                           'PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer und Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8                        'Timer für Servos, läuft mit 1MHz, ergibt 1000 Schritte Auflösung pro ms
    Enable Timer1                                               'schaltet den Timer1 Overflow-interrupt ein
    
    On Timer1 Servoausgabe                                      'Sprigt bei Timer1 Überlauf in die ISR
    Enable Interrupts                                           ' Interrupts zulassen
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------------------
    
    Kanal = 1
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Hauptprogramm starten
    '-------------------------------------------------------------------------------------------------------------
    
    Do
    
       Pulsein Empfangskanal(1) , Pinb , 2 , 1                  'Zählung läuft, solange der Empfänger Pegel auf 1 ist
    '   Pulsein Empfangskanal(2) , Pina , 7 , 1
    '   Pulsein Empfangskanal(3) , Pina , 6 , 1
    
    
    Servo1_signal = Empfangskanal(1) * 10
    
    
    Servo(1) = Servo1_signal
    Servo(2) = 1500
    Servo(3) = 1500
    Servo(4) = 1500
    
    
    Loop
    
    End
    
    
    
    
    Servoausgabe:
    
    
    '(
    
    Info
    Bei jedem Timer1 Überlauf wird in die ISR(Interrupt Service Routine) gesprungen und
    eine EINZIGE If -Bedingung erfüllt und abgearbeitet.
    Ablauf:
    Pin des ersten Servoausgangs einschalten. Gleichzeitig wird der Timer1 so vorgeladen,
    dass es nach einer bestimmten Zeit(Wert der Variable "Servo(1)") erneut zu einem
    Überlauf kommt. Da sonst keine weitere If -Bedingung erfüllt wird , gehts gleich wieder
    zurück ins Hauptprogramm.
    Beim folgenden Überlauf ist der erste Servoausgang bereits eingeschaltet , sodass
    nun die Else -Bedingung greift und der Ausgang wieder ausgeschaltet wird (somit ist das
    erste Servosignal (je nach Variablenwert 1ms -2ms) gesendet. Gleichzeitig
    wird die Variable "Kanal" um eins erhöht.
    Nun trifft die If -Bedingung für den zweiten Servoausgang zu (da die Variable "Kanal"
    ja nun auf 2 steht) und dieser wird eingeschaltet.
    Das Spiel wiederholt sich so lange , bis alle Kanäle durch sind. Die letzte If -Bedingung
    in dieser ISR füllt dann nur noch die verbleibende Zeit auf, um auf eine
    Wiederholungsfrequenz von ca 20ms zu kommen.
    
    ')
    
    If Kanal = 1 Then
       If Porta.0 = 0 Then                                      'wenn der Ausgangspin aus ist
          Load Timer1 , Servo(1)                                'wird der Timer1 mit dem Wert der Variable "Servo(1)" vorgeladen
          Porta.0 = 1                                           'und der Ausgangspin eingeschaltet
       Else                                                     'erst beim nächsten Timer1 Überlauf landen wir hier
          Porta.0 = 0                                           'Ausgangspin wird wieder ausgeschaltet
          Incr Kanal                                            'und der nächsten Kanal bearbeitet
       End If
    End If
    
    
    If Kanal = 2 Then
       If Porta.1 = 0 Then
          Load Timer1 , Servo(2)
          Porta.1 = 1
       Else
          Porta.1 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 3 Then
       If Porta.2 = 0 Then
          Load Timer1 , Servo(3)
          Porta.2 = 1
       Else
          Porta.2 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 4 Then
       If Porta.3 = 0 Then
          Load Timer1 , Servo(4)
          Porta.3 = 1
       Else
          Porta.3 = 0
          Incr Kanal
       End If
    End If
    
    '(
    
    Pausenauffüllung
    Jeder der oben angesteuerten Kanälen benötigt zwischen 1 -2ms. Die verbleibende Zeit
    wird nun hier eingegeben, um auf eine durchschnittliche Periodendauer von ca. 20ms
    zu kommen. Der eingegebene Zahlenwert entspricht dabei us,
    z.b. 13000 entspricht 13 ms.
    
    ')
    
    If Kanal = 5 Then
      Load Timer1 , 13000                                       'der Zahlenwert entspricht us
      Kanal = 1
    End If
    
    Return

    Eine weitere Möglichkeit wäre Hardware-PWM. Allerdings habe ich da noch praktisch keine Erfahrung. Hier im Forum fand ich ein Programm mit HW-PWM, verstehe aber nicht wirklich, was bestimmte einzelne Zeilen bewirken. Ich war ehrlich gesagt überrascht, dass es nach nur wenigen Änderungen auf meinem Attiny24 lauffähig war. Ich habe zwar Erklärungen dieser Abkürzungen in Datenblätter und einigen Seiten im www gefunden, aber zwischen lesen und verstehen ist leider ein erheblicher Unterschied.

    Code:
    '===============================================================================
    'Servo an Pin 7 (PA6, OC1A)
    'RC Empfangskanal an Pin 5 (PB2)
    '===============================================================================
    
    
    $regfile = "attiny24.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    
    $hwstack = 32
    $swstack = 20
    $framesize = 40
    
    
    Ddra.6 = 1                                                  'PA6 (Ausgang vom OC1A) wird Ausgang
    Ddrb = &B00000000                                           'PortB bleibt Eingang
    
    Tccr1a = &B10000000
    Tccr1b = &B00010001
    
    Icr1h = &B11111111
    Icr1l = &B11111111
    
    
    Dim Empfangskanal As Word
    
    
    Do
    
    Pulsein Empfangskanal , Pinb , 2 , 1
    
    Empfangskanal = Empfangskanal * 40
    
    Ocr1ah = High(empfangskanal)
    Ocr1al = Low(empfangskanal)
    
    Loop
    Kann mir jemand erklären, was genau die folgenden Zeilen im Detail machen (bin noch Anfänger mit begrenzten Englischkenntnissen ohne Abi/ Studium, daher bitte nicht zu viel Fachwissen voraussetzen).

    Code:
    Tccr1a = &B10000000
    Tccr1b = &B00010001
    
    Icr1h = &B11111111
    Icr1l = &B11111111
    Gibt es dafür auch andere Schreibweisen in Bascom (wie z.B. Config Timer1 = PWM etc), die ich eher nachvollziehen kann?

    Ich bin auch für andere Ideen offen (solange sie in irgendeiner Weise nachvollziehbar bleiben). Im ersten Schritt geht es mir zunächst „nur“ um eine ruckelfreie Ausgabe der Servoimpulse bei gleichzeitigem Einlesen von 3 RC-Signalen.


    Mit freundlichen Grüßen
    Robert

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Timer für Servos, läuft mit 1MHz, ergibt 1000 Schritte Auflösung pro ms
    Welche Auflösung benötigst du wirklich für deine Anwendung?
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #3
    hallo radbruch,

    ehrlich gesagt weiß ich nicht genau, bis zu welche Auflösung man runter gehen kann. Hängt mit Sicherheit auch von den verwendeteten Servos (Modellflug) oder Drehzahlreglern ab. Da ich die Routinen evt auch in Flugmodellen benutzen werde, müssen sie eben "einigermaßen" flüssig und ruckelfrei laufen.
    Bei meinen verwendetet Werten hatte ich den Vorteil, dass ich nicht lange umrechnen muss, da 1000 einer ms entspricht (Anschlag auf der einen Seite) und 2000 zwei ms (Anschlag auf der anderen Seite) .

    mfg
    Robert

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    ... weiß ich nicht genau, bis zu welche Auflösung man runter gehen kann ...
    Bei wenigen verschiedenen Servos hatte ich Auflösung im Bereich rund 4 µs festgestellt, wobei ich die Servos in Schritten von 0,4 µs angesteuert hatte, siehe hier für nen schlechten Billigservo und hier für nen billigen Guten. Das macht dann aber wirklich nur Sinn, wenn Du das irgendwie nutzen kannst - ich habe es so ausgelegt, damit ich kleinste, zusätzlich auch langsam(st)e Bewegungen fahren kann.

    Wie das in Basic geht, kann ich aber nicht sagen.
    Ciao sagt der JoeamBerg

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Ungetestet:

    Code:
    '===============================================================================
    'Baggersteuerung (ACHTUNG FUNKTIONIERT NICHT, SERVO RUCKELT EXTREM)
    
    'RC Empfangskanal 1 an Pin 6 (PA7)
    'RC Empfangskanal 2 an Pin 7 (PA6)
    'RC Empfangskanal 3 (Mode-Schalter) an Pin 5 (PB2)
    
    'Werte zwischen 100 und 200 entsprechen dem kompletten Knüppelweg
    'Der Wert 150 entspricht dabei ca. Mittelstellung, der Wert 200 ca. Vollausschlag
    
    'Poti Eingang 1 Pin 9 (PA4)
    'Poti Eingang 1 Pin 8 (PA5)
    
    'Servoausgang 1 Pin13 (PA0)
    'Servoausgang 2 Pin12 (PA1)
    'Servoausgang 3 Pin11 (PA2)
    'Servoausgang 4 Pin10 (PA3)
    
    'Made by Robert (www.roberts-r2d2-bau.de)
    
    'Angepasst von radbruch 21.12.2013
    'https://www.roboternetz.de/community/threads/63750-Mehrere-RC-Signale-einlesen-und-mehrere-Servos-ausgeben?
    '===============================================================================
    
    
    $regfile = "attiny24.dat"
    $crystal = 8000000                      'FuseBit CKDIV8 deaktivieren
    
    
    $hwstack = 32
    $swstack = 20
    $framesize = 40
    
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    
    Dim Empfangskanal(3) As Word
    Dim Empfangskanal_temp_ein(3) As Word
    Dim Empfangskanal_temp_aus(3) As Word
    
    Dim Kanal As Byte
    Dim Servo(4) As Word
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00001111                       'PA0, PA1, PA2 und PA3 werden Ausgänge, der restliche Port A bleibt Eingang
    Ddrb = &B00000000                       'PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer und Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8    'Timer für Servos, läuft mit 1MHz, ergibt 1000 Schritte Auflösung pro ms
    Compare1a = 1000                        ' Nach 1ms wird die ISR initialisiert
    Timer1 = 1
    Enable Compare1a                        'schaltet den Timer1 Compare1a Match-Interrupt ein
    
    On Compare1a Servoausgabe               'Springt bei Timer1 Compare1a Match in die ISR
    Enable Interrupts                       ' Interrupts zulassen
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------------------
    
    Kanal = 0                               ' Kanal startet jetzt bei 0 wegen porta.kanal in der ISR!
    
    Servo(1) = 1500
    Servo(2) = 1500
    Servo(3) = 1500
    Servo(4) = 1500
    Empfangskanal(1) = 0
    Empfangskanal(2) = 0
    Empfangskanal(3) = 0
    Empfangskanal_temp_ein(1) = 0
    Empfangskanal_temp_ein(2) = 0
    Empfangskanal_temp_ein(3) = 0
    Empfangskanal_temp_aus(1) = 0
    Empfangskanal_temp_aus(2) = 0
    Empfangskanal_temp_aus(3) = 0
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Hauptprogramm starten
    '-------------------------------------------------------------------------------------------------------------
    
    Do
    
    If Pina.7 = 1 And Empfangskanal_temp_ein(1) = 0 Then
       Empfangskanal_temp_ein(1) = Timer1
    End If
    
    If Pina.7 = 0 And Empfangskanal_temp_ein(1) <> 0 Then
          Empfangskanal_temp_aus(1) = Timer1
          If Empfangskanal_temp_aus(1) < Empfangskanal_temp_ein(1) Then
             Empfangskanal_temp_aus(1) = Empfangskanal_temp_aus(1) + 20000
          End If
          Empfangskanal(1) = Empfangskanal_temp_aus(1) - Empfangskanal_temp_ein(1)
          Empfangskanal_temp_ein(1) = 0
    End If
    
    If Pina.6 = 1 And Empfangskanal_temp_ein(2) = 0 Then
       Empfangskanal_temp_ein(2) = Timer1
    End If
    
    If Pina.6 = 0 And Empfangskanal_temp_ein(2) <> 0 Then
          Empfangskanal_temp_aus(2) = Timer1
          If Empfangskanal_temp_aus(2) < Empfangskanal_temp_ein(2) Then
             Empfangskanal_temp_aus(2) = Empfangskanal_temp_aus(2) + 20000
          End If
          Empfangskanal(2) = Empfangskanal_temp_aus(2) - Empfangskanal_temp_ein(2)
          Empfangskanal_temp_ein(2) = 0
    End If
    
    If Empfangskanal(1) <> 0 Then Servo(1) = Empfangskanal(1) End If
    If Empfangskanal(2) <> 0 Then Servo(2) = Empfangskanal(2) End If
    
    Loop
    
    End
    
    '(
    
    Der Timer startet beim ersten Servo mit dem Zählwert 1, Das Compare-Register wird auf den Wert
    für die Impulslänge des ersten Servo gesetzt.In der Compere-ISR (wenn der Zählwert den Wert im
    Compareregister erreicht hat) wird dann ausgehend vom aktuelen Timerwert der Vergleichswert für
    die Impulslänge des nächsten Servo berechnet und gesetzt. Nach dem letzten Servo wird 20000 für
    die Wiederholfrequenz des Signals gesetzt
    
    ')
    
    Servoausgabe:
    
    Porta.0 = 0                             'alle Servosignale ausschalten
    Porta.1 = 0
    Porta.2 = 0
    Porta.3 = 0
    
    If Kanal < 4 Then                       ' Zeitpunkt für nächstes Servo setzen
       If Kanal = 0 Then
          Timer1 = 1                        ' beim ersten Servo Timer Zähler zurücksetzen
       End If
       Compare1a = Timer1 + Servo(kanal + 1)       ' aktueller Timerwert + Servo Impulslänge
       Porta.kanal = 1                      ' Impuls ausgeben
       Incr Kanal                           ' nächstes Servo vormerken
    Else
       Compare1a = 20000                    ' 50Hz Wiederholfrequenz setzen
       Kanal = 0
    End If
    
    Return
    Geändert von radbruch (21.12.2013 um 09:35 Uhr) Grund: Enable Compare1a
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #6
    Hallo radbruch,

    habe Deinen Vorschlag mal gestestet, funktioniert ähnlich gut wie der Code, den ich in der Zwischenzeit mit Hilfe eines weiteren Forummitglieds gestrickt habe. Mit "ähnlich gut" meine ich, dass ein geringes, aber deutlich sichtbares Servozucken an den Servos vorhanden ist, welche mit den eingelesenen RC-Signalen versorgt werden. Servos, denen ich im Programm einen Festwert zuweise, zucken nicht. Daraus schliese ich, dass die Servoausgabe ISR korrekt und zuverlässig arbeitet, aber sich die Interrupts der RC Einleserei in die Quere kommen. Der folgende Code liest 3 RC-Signale ein und gibt 2 davon an 2 Servos weiter, während die anderen beiden Servos einen Festwert zugewiesen bekommen haben. Ich benutze TIMER1 für das Einlesen (tolle Auflösung) und TIMER0 für die Ausgabe (leider nur noch sehr bescheidene Auflösung).

    Inzwischen ist die Auswertung der Poti's auch eingebaut und getestet (hier aber nicht gepostet, da es den Code nur unnötig unübersichtlich macht). Allerdings habe ich die Speicherkapazität des Attiny24 mittlerweile geprengt und warte nun auf die bestellten Attiny84.

    Mein momentanes Problem ist das nicht ganz saubere Einlesen der RC Signale. Ich habe auch versucht, immer nur einen der drei Interrupts zuzulassen (z.B. mit "disable INT0" in der entsprechenden ISR) und die RC Signale hintereinander einzulesen, führte aber zu keiner Verbesserung.

    mfg
    Robert

    Code:
    '===============================================================================
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)
    'RC Eingang 2 an Pin 7 (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 = "attiny24.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 32
    $swstack = 20
    $framesize = 40
    
    
    '-------------------------------------------------------------------------------------------------
    '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
    
    
    '-------------------------------------------------------------------------------------------------------------
    '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 Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    
    
    '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
    
    '-------------------------------------------------------------------------------------------------------------
    '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
    
    
    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
    
    
    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
    
    Enable Interrupts
    
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
    
    'Umrechnung erstes RC Signal auf 8-Bit
    Berechnung_1 = Impulslaenge_1 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_1 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_1 = 255
    End If
    
    If Berechnung_1 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_1 = 120
    End If
    
    
    'Umrechnung zweites RC Signal auf 8-Bit
    Berechnung_2 = Impulslaenge_2 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_2 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_2 = 255
    End If
    
    If Berechnung_2 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_2 = 120
    End If
    
    
    
    Servoausgabe_1 = Berechnung_1
    Servoausgabe_2 = Berechnung_2
    Servoausgabe_3 = 190
    Servoausgabe_4 = 190
    
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    
    Rc_eingang_1:
       If Pinb.1 = 1 Then
       Rc_signal_1_start = Timer1
       Else
       Impulslaenge_1 = Timer1 - Rc_signal_1_start
       End If
    Return
    
    
    Rc_eingang_2:
       If Pina.7 = 1 Then
       Rc_signal_2_start = Timer1
       Else
       Impulslaenge_2 = Timer1 - Rc_signal_2_start
       End If
    Return
    
    
    Rc_eingang_3:
       If Pinb.2 = 1 Then
       Rc_signal_3_start = Timer1
       Else
       Impulslaenge_3 = Timer1 - Rc_signal_3_start
       End If
    Return
    
    
    
    
    Servoausgabe:
    
    If Kanal = 1 Then
       If Porta.0 = 0 Then                                      'wenn der Ausgangspin aus ist
          Load Timer0 , Servoausgabe_1                          'wird der Timer0 mit dem Wert der Variable "Servoausgabe_1" vorgeladen
          Porta.0 = 1                                           'und der Ausgangspin eingeschaltet
       Else                                                     'erst beim nächsten Timer0 Überlauf landen wir hier
          Porta.0 = 0                                           'Ausgangspin wird wieder ausgeschaltet
          Incr Kanal                                            'und der nächsten Kanal bearbeitet
       End If
    End If
    
    
    If Kanal = 2 Then
       If Porta.1 = 0 Then
          Load Timer0 , Servoausgabe_2
          Porta.1 = 1
       Else
          Porta.1 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 3 Then
       If Porta.2 = 0 Then
          Load Timer0 , Servoausgabe_3
          Porta.2 = 1
       Else
          Porta.2 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 4 Then
       If Porta.3 = 0 Then
          Load Timer0 , Servoausgabe_4
          Porta.3 = 1
       Else
          Porta.3 = 0
          Incr Kanal
       End If
    End If
    
    
    
    'Pausenauffüllung
    
    
    If Kanal = 5 Then
      Timer0 = 0                                                '8-Bit Timer auf 0, Überlauf alle 2,048ms
      If Pausen_variable < 7 Then                               '2,048ms * 6 = 12,288ms Pausenfüllzeit
      Incr Pausen_variable
      Else
      Pausen_variable = 0
      Kanal = 1
      End If
    End If
    
    
    Return

  7. #7
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Hallo!

    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    Mein momentanes Problem ist das nicht ganz saubere Einlesen der RC Signale. Ich habe auch versucht, immer nur einen der drei Interrupts zuzulassen (z.B. mit "disable INT0" in der entsprechenden ISR) und die RC Signale hintereinander einzulesen, führte aber zu keiner Verbesserung.
    Eben, warum (fast) alle alles mit nur einem µC realisieren versuchen (Billiger ? ).
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    Ich habe auch versucht, immer nur einen der drei Interrupts zuzulassen (z.B. mit "disable INT0" in der entsprechenden ISR) und die RC Signale hintereinander einzulesen, führte aber zu keiner Verbesserung.
    Hallo Robert,
    wenn die RC Signale wie üblich nacheinander ankommen, dann kannst du das ganze doch mit dem Timer1 alleine hinkriegen. Erst die drei Kanäle einlesen, dann die beiden Potis auswerten und schließlich alles nacheinander an die Servos ausgeben.
    3 x RC dauert max 6ms, Potis einlesen < 1ms und die Ausgabe an 4 Servos dauert maximal 8ms, also zusammen keine 15ms. Wenn dem so ist, wäre dies definitiv mein Weg, wie ich vorgehen würde. Und wenn du dann noch alle 3 RC Kanäle auf einen Eingang - vorzugsweise den ICP (PA.7) - legen kannst, ist das Einlesen auch eine saubere, weil in Hardware realisierte Lösung.
    Alles würde dann synchronisiert durch den ersten RC Eingang. Genauer bekommst du die Intervalle sonst auf keinen Fall realisiert und du hättest wieder 1000 Schritte bei den Servos und nicht wie jetzt nur 125.
    Solange du nicht synchron arbeitest, wird es dir immer wieder passieren, dass gerade eine ISR abgearbeitet wird, wenn ein RC Signal beginnt oder endet.
    Und wenn du die Arbeit auf zwei Controller verteilst, müssen die eingelesenen Werte übertragen werden, was dann zu ähnlichen Problemen führt.

  9. #9
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Zitat Zitat von for_ro Beitrag anzeigen
    Und wenn du die Arbeit auf zwei Controller verteilst, müssen die eingelesenen Werte übertragen werden, was dann zu ähnlichen Problemen führt.
    Vielleicht geht es mit mehr als zwei µC einfacher.
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  10. #10
    Hallo zusammen,

    mit "hintereinander Einlesen" meinte ich in meinem letzten Posting das Einlesen von 3 RC Signalen, und zwar unabhängig davon, WANN sie der Empfänger sendet (wir reden nicht von einem Summensignal, sondern von 3 getrennten Anschlüssen am Empfänger).
    Es gibt Empänger, die ein Signal zu Ende senden, dann mit dem nächsten beginnen (am nächsten Ausgang des Empfängers) usw bis alle 4, 6 oder 8 Kanäle durch sind. Andere Empänger setzen die Kanäle nahezu zeitgleich auf 1 und wieder andere beginnen den nächsten Kanal nach einer vordefinierten Zeit. Manche käufliche V-Mischer hatten dann das Problem, dass sie nicht mehr funktionierten, wenn man die Reihenfolge der RC Kanäle veränderte.

    Ich möchte meinen Code so gestalten, dass es egal ist, welchen Empfänger ich dran hänge. Wenn ich also vom Fall ausgehe, dass die einzelnen RC Signale nahezu gleichzeitig beginnen auf 1 (high) zu gehen, und ich sie dann HINTEREINANDER einlese, so dauert das Einlesen 3 x 20ms. Das kann ich nicht während der Pause der Servoausgabe einbauen, da diese ja spätestens nach 20ms wieder bedient werden möchten (müssen).

    @ PICture
    Das Problem liegt daran, das ich mehr als 1 Servosignal einlesen muss. Genauergesagt mindestens 2. Eines ist der Betriebsmode (also Baggerbetrieb oder Fahrbetrieb) und das zweite die eigentliche Steuereingabe. Deshalb versuche ich alles auf einen Chip zu bekommen.
    Alternativ ginge es mit 3 Chips: Einer wertet nur den Betriebsmode aus und setzt einen Ausgang auf high oder low, die anderen steuern die Servos und werten nur den Ausgang des "Betriebsmode-Chips" aus.
    Mal sehen, wie es weitergeht

    mfg
    Robert

    mfg
    Robert

Seite 1 von 8 123 ... 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
  •  

LiTime Speicher und Akkus