PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Servoposition herausfinden?



jagdfalke
16.06.2005, 21:47
Hallo,
das Ziel für mein Programm sieht so aus:
Ich will ein Sub programmieren, dem ich die Servonummer und die Endposition geben kann und es dann den Servo in die Position bringt. Allerdings soll das langsam und nicht so ruckartig passieren wie wenn ich
Print #2 , "#s" ; Chr(1) ; Chr(100)
schreiben würde. Ich will also die For-Next-Schleife nur so oft durchlaufen wie die Differenz zwischen Sollposition und Istposition beträgt. Also muss ich zum einen die Istposition irgendwie auslesen und dann noch den Betrag der Differenz ausrechnen.
Und hier fehlts mir an Kenntnis über sowohl AVR als auch die Sprache Bascom. Kann jemand helfen?

mfg
jagdfalke

recycle
16.06.2005, 22:04
Ein Servo ist kein Schrittmotor der Schritte verlieren kann.
Deswegen kannst du bei einem Servo eigentlich davon ausgehen, dass er sich genau in der Position befindet die du angesteuert hast (natürlich mit ein paar ms Zeitverzögerung) und brauchst normalerweise keine Rückmeldung.
Ausnahme ist, wenn der Servo irgendwie mechanisch dran gehindert wird die Position die du ansteuerst einzunehmen. Davon gehen normale Servos aber ziemlich schnell kaputt, deshalb solltest du das besser vermeiden.

jagdfalke
16.06.2005, 22:18
Ja schon klar, aber ich will ja nicht dass sie sich so schnell bewegen wie sie können sondern langsamer. Dafür brauche ich eine For-Next-Schleife.

Bsp:

LOOP:
Call Rnb_servo(1, 100)
wait 2
Call Rnb_servo(1, 150)
Goto LOOP
Sub Rnb_servo(byval Servonummer As Byte , Byval Position As Byte)
Print "#s" ; Chr(servonummer) ; Chr(position)
End Sub

In diesem Beispiel würder er sich so schnell wie möglich zu 100 dann nach 2 Sekunden zu 150 bewegen.
Nächstes Beispiel:

LOOP:
Call Rnb_servo(1, 100)
wait 2
Call Rnb_servo(1, 150)
Goto LOOP
Sub Rnb_servo(byval Servonummer As Byte , Byval Position As Byte)
For I = 0 to Position
Print "#s" ; Chr(servonummer) ; Chr(position)
waitms 10
Next I
End Sub

Nach dem ersten Call-Befehl würde alles so klappen wie es soll, vorrausgesetzt der Servo befindet sich auf Position 0. Danach ist er auf Position 100. Beim zweiten Call-Befehl würde er plötzlich auf Position 0 springen und von da aus langsam auf 150.

Was ich will ist den plötzlichen Sprung auf 0 zu vermeiden.

mfg
jagdfalke

uwegw
16.06.2005, 22:29
du müsstest dir imemr merken auf welche position du debn servo beim lezten mal gestzt hast und dann dort weitermachen...

jagdfalke
16.06.2005, 22:39
man kann die position also nicht irgendwie vom servo auslesen. also isses ein Programmierproblem.
wenn ich jetzt ein sub schreibe sind da variablen die im Main-Teil deklariert wurden nicht verfügbar. Kann man in Bascom so eine Art Globale Variable deklarieren?

16.06.2005, 23:04
Alle Variablen sind in Bascom global. Aber vielleicht solltets du erst mal etwas mehr in einem Bascom Buch blättern, erspart die viele Fragen

jagdfalke
16.06.2005, 23:21
wo finde ich das denn?

recycle
16.06.2005, 23:54
man kann die position also nicht irgendwie vom servo auslesen. also isses ein Programmierproblem.

Ja. Aber ich würde es nicht unbedingt als Problem, sondern eher als grosse Vereinfachung ansehen



wenn ich jetzt ein sub schreibe sind da variablen die im Main-Teil deklariert wurden nicht verfügbar.

Bei allen Programmiersprachen die ich kenne sind Variablen die ausserhalb irgendwelcher Routinen direkt im Hauptblock des Programms definiert werden innerhalb aller Subroutinen und Funktionen verfügbar.



Kann man in Bascom so eine Art Globale Variable deklarieren?

Braucht man nicht. Man kann aber umgekehrt eine Variable innerhalb einer Funktion oder Routine als "local" deklarieren.



wo finde ich das denn?

Mit ein bischen suchen sicherlich irgendwo in der Online-Hilfe. Einfach mal ausprobieren, kann aber eigentlich auch nicht länger als 3 Minuten dauern, wenn er eine Variable nicht kennt wird der Compiler es dir schon sagen.

PicNick
17.06.2005, 10:19
Ich finde es schon gut, wenn ein Servokontroller ein bißchen Feedback liefert. Aber die effektive Position des Servos kennt der ohne Zugriff auf das Poti ja schließlich auch nicht. Was soll er mir also erzählen ? Die Position, wo ich das Servo gern hätte, hat er ja eh von mir, und das eine Byte bring' ich allemal unter, oft brauch ich es ja ohnehin für andere Entscheidungen. da werd' ich es mir nicht immer extra holen.
Wenn ich eine SPeed-parameter mitgeben kann, DANN ist es schon praktisch, wenn ich eine (aktive) Meldung bekomme, daß das Servo nun tatsächlich dort ist. Aber das erfordert ein Kommunikations-Protokoll.

BasCom:
definierst du mit
DIM Name as Type
dann ist das global
in einer SUb oder Function kannst du nach dem function-header genauso schreiben
LOCAL Name as Type
Dann gilt das nur in der Sub (Function), braucht also nicht unique zu sein.

"Help"-->Index--> LOCAL

jagdfalke
17.06.2005, 14:13
Also erstmal danke für eure Antworten. Ich hab jetzt schon einen Teil des Programs geschrieben, komm aber nicht weiter (wieder durch unzulängliche Kenntnis der Sprache Bascom):

Im folgenden Quellcode wird ein Servo (Servotreiber im Copozessor) von verschiedenen Positionen zu nächsten in langsamen Schritten bewegt:



$regfile = "m32def.dat"

Declare Sub Rnb_servo(byval Servonummer As Byte , Byval Go_to_pos As Byte)

$crystal = 8000000 'Quarzfrequenz
$baud = 9600

Dim Curr_pos As Byte
Dim Go_to_pos As Byte
Dim Servo_counter As Byte
Dim Steps_to_go As Byte

Call Rnb_servo(1 , 0)
Curr_pos = 0
Wait 5
'################################################# ##############################


Hauptschleife:

Call Rnb_servo(1 , 100)
Wait 3

Call Rnb_servo(1 , 150)
Wait 3

Call Rnb_servo(1 , 50)
Wait 3

Goto Hauptschleife



Sub Rnb_servo(byval Servonummer As Byte , Byval Go_to_pos As Byte)

If Go_to_pos > Curr_pos Then

For Servo_counter = Curr_pos To Go_to_pos
Print "#s" ; Chr(servonummer) ; Chr(servo_counter)
Waitms 10
Next Servo_counter

Elseif Go_to_pos < Curr_pos Then
Steps_to_go = Abs(curr_pos - Go_to_pos)
For Servo_counter = 0 To Steps_to_go
Print "#s" ; Chr(servonummer) ; Chr(curr_pos - Servo_counter)
Waitms 10
Next Servo_counter

End If

Curr_pos = Go_to_pos

End Sub

End


Die Bewegung von 0 nach 100, als auch die von 100 nach 150 funktionieren, weil jeweils die momentane Position kleiner als die zu erreichende Position ist (curr_pos < go_to_pos).
Beim Schritte von Position 150 nach 50 sollte also der zweite Teil der If-Abfrage in der Subroutine ausgeführt werden. Das Problem liegt jetzt in der Zeile "Print "#s" ; Chr(servonummer) ; Chr(curr_pos - Servo_counter)". Als Fehler wird "Error 31 : Invalid Data Type" angezeigt.

Ich kapier nicht, wie der Fehler zustande kommt. Kann jemand helfen?
mfg
jagdfalke

PicNick
17.06.2005, 14:33
Diese Rechnungen in der Klammer chr(curr_pos - servo_counter) mag er nicht. das mußt du vorher in einer Variablen ausrechnen.
ABER
mach es nicht so kompliziert:


dim curr_pos as byte
curr_pos = 127 ' mittelposition am anfang

hauptschleife
...


Sub Rnb_servo(byval Servonummer As Byte , Byval Go_to_pos As Byte)
local schritt as integer
if curr_pos < go_to_pos then
schritt = 1
else
schritt = -1
end if

For curr_pos = Curr_pos To Go_to_pos step schritt
Print "#s" ; Chr(servonummer) ; Chr(curr_pos)
Waitms 10
Next


Je nachdem schritt + oder - ist, geht's rauf oder runter

jagdfalke
17.06.2005, 15:22
ahhhh !! cool !
Ich hab mich schon gewundert, dass man die for schleife nicht rückwärts zählen lassen kann. anscheinend ist er automatisch auf STEP 1 gestellt. lol
naja danke jedenfalls

PicNick
17.06.2005, 15:28
Fein, wenn ich dir helfen konnte.
ABER
Man sollte keine Statements hinschreiben, bevor man den "help" -text dazu nicht auswendig singen kann. :D

jagdfalke
19.06.2005, 21:12
Hi hab scho wieder a Problem mit dem Code:


Sub Rnb_servo(byval Servonummer As Byte , Byval Go_to_pos As Byte)
Local Schritt As Integer
Local Repeat_counter As Integer

If Curr_pos < Go_to_pos Then
Schritt = 1
Else
Schritt = -1
End If



For Curr_pos = Curr_pos To Go_to_pos Step Schritt
Open "comd.7:9600,8,n,1" For Output As #2
Print #2 , "#s" ; Chr(servonummer) ; Chr(curr_pos)
Close #2
Print Curr_pos
Waitms 10
Next

End Sub


Ich kann für die Variable Go_to_pos nur werte zwischen 1 und 254 eingeben. Is da irgendwo a Denkfehler drin, den ich net find? Man, ich auch gar nix richtig :(

avrflo
19.06.2005, 22:50
Hallo,
ja da ist ein Denkfehler drin:
du hast deine Variable Go_to_pos als Byte definiert, ein Byte hat nur 8 bit, also kann es 2^8=256 verschiedene Zahlen darstellen. Schau mal in der Bascom Hilfe unter "Language Fundamentals", dort steht wie groß die einzelnen Variablen sind.
Gruß
Florian

jagdfalke
19.06.2005, 22:55
Was? Go_to_pos soll doch auch nur von 0 bis 255 gehen. Sie gibt die gewünschte Position des Servos an und die kann ja auch nur zwischen 0 und 255 sein. Kapier ich net.