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:
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
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):
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
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
Und hier das Video, das Servo läuft schön regelmässig:
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
Lesezeichen