Hi!
Ich bin ganz neu in der Materie und habe ein Problem: Ein Servo soll per Sinus angesteuert werden. Es ist ein Futaba s9253 (mit das schnellste was es gibt) angeschlossen am RN-Control v1.4.
Das ganze soll später eine Art Schlagflugroboter ansteuern, dessen Aerodynamik dann vermessen wird. Deswegen ist präzision hier einigermaßen wichtig.
Hier erstmal der Quellcode der nicht richtig funktioniert:
Der timer_irq schlägt mit 31 Hz zu und erhöht eine Variable X immer ein bischen, dann wird sinus X ausgerechnet und an das Servo gesendet. Dabei passiert aber folgendes (Video):Code:$regfile = "m32def.dat" $framesize = 32 $swstack = 32 $hwstack = 32 $crystal = 16000000 $baud = 9600 Config Servos = 1 , Servo1 = Portb.3 , Reload = 10 Config Portb = Output Config Timer1 = Timer , Prescale = 8 On Timer1 Timer_irq Enable Interrupts Enable Timer1 Dim I As Integer Dim J As Single Dim X As Single Dim Sinx As Single Dim Erst As Single Dim Zweit As Single Dim Dritt As Integer Dim Vorerst As Single Const Pi = 3.14159265358979 Const 2pi = 6.28318530717958 For I = 500 To 300 Step -10 'sound PORTD.7 , Länge , Frequenz Sound Portd.7 , 10 , I Next I Waitms 180 For I = 500 To 300 Step -10 Sound Portd.7 , 10 , I Next I For I = 300 To 500 Step 5 Sound Portd.7 , 12 , I Next I J = 0.02 * Pi Do Sinx = Sin(x) 'X wird im Timer_irq immer um "J" erhöht Vorerst = Sinx + 1 'die variable "Vorerst" schwankt sinusförmig zwischen o und 2 Erst = Vorerst * 50 'Hochskalieren der Werte, so dass sie zw. 60 und 160 sinusförmig schwanken Zweit = Erst + 60 Dritt = Round(zweit) 'und nochmal runden, man weiss ja nie... Servo(1) = Dritt 'servo 1 und servo 2 stellen 'Print Servo(1) 'Delay 'ins terminal schreiben welche werte die Servos haben Loop Timer_irq: 'hat eine Frequenz von 31Hz Timer1 = 1020 If X < 2pi Then 'x wird um J erhöht solange x kleiner als 2 Pi, ansonsten x = 0 X = X + J Else X = 0 End If Return
http://www.youtube.com/watch?v=yEjPdcdpZC4
DSas servo folgt zwar prinzipiell dem Sinus, zuckelt aber öfters mal auf irgendwelche undefinierten positionen und macht dann wieder weiter. Das sieht man auch im Terminal wenn man Servo(1) printed. Zwischendurch stehen da mal ganz wilde Zeichenkombinationen oder falsche zahlen.
Folgender Code funktioniert. dort wird die Variable X einfach im Main-Loop erhöht, danach gibts immer 2ms pause damit das ganze nicht zu schnell läuft.
Im Schlagflugroboter muss das servo aber am ende mit einer bestimmten frequenz laufen. Außerdem bewegt es sich dann nicht mehr per einfacher sinusfunktion sondern bewegt sich etwas komplizierter. Und wenn ich das ohne Timer1 mache, dann habe ich doch keine garantie mehr dafür dass das servo mit der richtigen geschwindigkeit läuft? Bzw. wann das Servo wie schnell läuft hängt dann davon ab wie schnell der AtMega32 die funktionen berechnen kann, oder?
Also hier der funktionierende Code ohne timer1_irq
Und hier das Video, das Servo läuft schön regelmässig:Code:$regfile = "m32def.dat" $framesize = 32 $swstack = 32 $hwstack = 32 $crystal = 16000000 $baud = 9600 Config Servos = 1 , Servo1 = Portb.3 , Reload = 10 Config Portb = Output 'Config Timer1 = Timer , Prescale = 8 'On Timer1 Timer_irq Enable Interrupts 'Enable Timer1 Dim I As Integer Dim J As Single Dim X As Single Dim Sinx As Single Dim Erst As Single Dim Zweit As Single Dim Dritt As Integer Dim Vorerst As Single Const Pi = 3.14159265358979 Const 2pi = 6.28318530717958 For I = 500 To 300 Step -10 'sound PORTD.7 , Länge , Frequenz Sound Portd.7 , 10 , I Next I Waitms 180 For I = 500 To 300 Step -10 Sound Portd.7 , 10 , I Next I For I = 300 To 500 Step 5 Sound Portd.7 , 12 , I Next I J = 0.002 * Pi Do Sinx = Sin(x) 'X wird im Timer_irq immer um "J" erhöht Vorerst = Sinx + 1 'die variable "Vorerst" schwankt sinusförmig zwischen o und 2 Erst = Vorerst * 50 'Hochskalieren der Werte, so dass sie zw. 60 und 160 sinusförmig schwanken Zweit = Erst + 60 Dritt = Round(zweit) 'und nochmal runden, man weiss ja nie... Servo(1) = Dritt 'servo 1 und servo 2 stellen 'Print Servo(1) 'Delay 'ins terminal schreiben welche werte die Servos haben If X < 2pi Then 'x wird um J erhöht solange x kleiner als 2 Pi, ansonsten x = 0 X = X + J Else X = 0 End If Waitms 2 Loop
http://www.youtube.com/watch?v=Wcj16WOxGcg
Meine Frage daher: Was kann ich machen damit im timer_irq quasi die "Zeitvariable" hochzählt und im Hauptprogramm mit dieser Variablen eine Funktion ausgerechnet wird? Und diese Funktion sollte ein Servo ansteuern OHNE dass das so komisch durch die Gegend zuckelt.... Für eure Hilfe wäre ich sehr dankbar!
Viele Grüße,
William







Zitieren

Lesezeichen