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








Zitieren

Lesezeichen