PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : For-Next-Schleife läuft nicht so wie gewollt :(



jagdfalke
02.07.2005, 00:25
Hi,
ich habe meinen Roboterarm jetzt schon fast fertig aufgebaut. Es fehlt nur noch der Greifer. Ich wollte jetzt ein bischen mit der Positionierung herumexperimentieren und bin auf ein sicherlich sehr einfach zu lösendes Problem gestoßen, nur komm ich nicht drauf.
Hier mal der Code:



$crystal = 8000000
$baud = 9600

Declare Sub Shoulder_move(byval Shoulder_goto_pos As Byte)

Dim Shoulder_curr_pos As Byte
Shoulder_curr_pos = 127

Hauptschleife:
Wait 2
Call Shoulder_move(255)
Goto Hauptschleife



Sub Shoulder_move(byval Shoulder_goto_pos As Byte)
Local Schritt As Integer

If Shoulder_curr_pos < Shoulder_goto_pos Then
Schritt = 1
Elseif Shoulder_curr_pos > Shoulder_goto_pos Then
Schritt = -1
End If

Open "comd.7:9600,8,n,1" For Output As #2
For Shoulder_curr_pos = Shoulder_curr_pos To Shoulder_goto_pos Step Schritt
Print #2 , "#s" ; Chr(1) ; Chr(shoulder_curr_pos)
Print #2 , "#s" ; Chr(2) ; Chr(shoulder_curr_pos)
Waitms 30
Print " SCHRITT: " ; Schritt ; " CURR_POS: " ; Shoulder_curr_pos ; " GOTO_POS: " ; Shoulder_goto_pos
Next Shoulder_curr_pos
Close #2

Shoulder_curr_pos = Shoulder_goto_pos

End Sub

End


Der kommt gar nicht aus der For-Schleife raus. Die Variable Shoulder_curr_pos geht immer auf 255 und springt dann auf 0. Damit bewegt er sich plötzlich auch 0 und dann gehts wieder weiter zu 255, usw.
Habs mit 255 und 0 für Shoulder_goto_pos probiert. In beiden Fällen passiert das gleiche. An der Variable Schritt liegts nicht. Die ist immer richtig.
Oh man, das ist bestimmt total einfach und ich checks wieder nicht. Naja hoffentlich eine von euch.
mfg
jagdfalke[/code]

recycle
02.07.2005, 02:04
Wenn du dir dein Programm mal in den Bascom-Simulator läst und laufen lässt, wirst du sehen, dass deine Variable "Shoulder_curr_pos" kurz überläuft, dadurch auf 0 zurückspringt und die For-Schleife von vorne losgeht.

Wenn du "Shoulder_curr_pos" als Word anstatt als Byte deklarierst bleibt die For-Schleife bei 255 hängen.

Woher hast du die Syntax für deine For-Schleife?
For Shoulder_curr_pos = Shoulder_curr_pos To Shoulder_goto_pos Step Schritt

For Shoulder_curr_pos = Shoulder_curr_pos macht irgendwie wenig Sinn, da die Bedingung immer erfüllt ist.

PicNick
02.07.2005, 07:39
For Shoulder_curr_pos = Shoulder_curr_pos macht irgendwie wenig Sinn, da die Bedingung immer erfüllt ist.
Um diese Uhrzeit muß man aufpassen, da schreibt man manches Unüberlegtes. Was du bemäkelst ist ja nicht die Bedingung, sondern der Anfangswert.
Bedingung ist "TO"


@Jadfalke: du bringst den BasCom ins Schleudern mit den Vorzeichen und Umwandlungen.
Du mußt .._curr_pos und .. goto_pos auch als integer definieren
Die For Schleife ist sonst genau richtig.

recycle
02.07.2005, 10:40
Um diese Uhrzeit muß man aufpassen, da schreibt man manches Unüberlegtes.

Stimmt ;-) In dem Fall waren es aber mehr Probleme auszudrücken was ich meine.

Mir kommt es etwas seltsam vor die Variable die hochgezählt wird gleich dem Anfangswert zu setzen und den Anfangswert bei jedem Schleifendurchlauf hochzuzählen.
Mag ja sein, dass es funktioniert, aber übersichtlicher macht das die Geschichte irgendwie nicht.

jagdfalke
02.07.2005, 10:51
Hi Jungs,
ich hab die Variablentypen angeglichen und jetzt läufts. Nur leider erschien ein neues Problem:




$crystal = 8000000
$baud = 9600

Declare Sub Servo_move(byval Servo As Integer , Byval Servo_goto_pos As Integer)

$crystal = 8000000 'Quarzfrequenz

Dim Shoulder_curr_pos As Integer
Shoulder_curr_pos = 127

Dim Elbow_curr_pos As Integer
Elbow_curr_pos = 127

Hauptschleife:
Wait 2
Call Servo_move(1 , 255)
Wait 2
Call Servo_move(1 , 0)
Goto Hauptschleife



Sub Servo_move(byval Servo As Integer , Byval Servo_goto_pos As Integer)
Local Schritt As Integer

If Servo = 0 Then 'Schulter bewegen

If Shoulder_curr_pos < Servo_goto_pos Then
Schritt = 1
Elseif Shoulder_curr_pos > Servo_goto_pos Then
Schritt = -1
Elseif Shoulder_curr_pos = Servo_goto_pos Then
Exit Sub
End If

Open "comd.7:9600,8,n,1" For Output As #2
For Shoulder_curr_pos = Shoulder_curr_pos To Servo_goto_pos Step Schritt
Print #2 , "#s" ; Chr(1) ; Chr(shoulder_curr_pos)
Print #2 , "#s" ; Chr(2) ; Chr(shoulder_curr_pos)
Next Shoulder_curr_pos
Close #2

Shoulder_curr_pos = Servo_goto_pos
End If

If Servo = 1 Then 'Ellbogen bewegen

If Elbow_curr_pos < Servo_goto_pos Then
Schritt = 1
Elseif Elbow_curr_pos > Servo_goto_pos Then
Schritt = -1
Elseif Elbow_curr_pos = Servo_goto_pos Then
Exit Sub
End If

Open "comd.7:9600,8,n,1" For Output As #2
For Elbow_curr_pos = Elbow_curr_pos To Servo_goto_pos Step Schritt
Print #2 , "#s" ; Chr(3) ; Chr(elbow_curr_pos)
Print "CURR: " ; Elbow_curr_pos ; " GOTO: " ; Servo_goto_pos
Next Elbow_curr_pos
Close #2

Elbow_curr_pos = Servo_goto_pos

End If

End Sub

End



Der Code für Servo = 1 ist eigenlich 1:1 kopiert aus dem Servo=0-Teil aber er funktionert nicht. Ich hab per Terminal überprüft ob er wirklich in die For-Schleife rein geht und er tut es. Elbow_curr_pos wird vergrößert, definitiv. Anscheinend passiert dann bei
Print #2 , "#s" ; Chr(3) ; Chr(elbow_curr_pos)
gar nichts. Ich hab den Servo 100%ig am 3. Servoanschluss angeschlossen !!! Das komische ist, wenn ich das hier


Open "comd.7:9600,8,n,1" For Output As #2
For I = 127 To 255 Step 1
Print #2 , "#s" ; Chr(3) ; Chr(i)
Next I
Close #2

direkt in die Haupschleife einbaue, dann bewegt er sich wie er soll. Ich bin ratlos.

EDIT: "funktioniert nicht" bedeutet er bewegt sich keinen Millimeter.

mfg
jagdfalke [/shadow]

PicNick
02.07.2005, 12:41
sehe ich direkt keinen Fehler:
Aber falls ihn das chr(xx) von einem Integer stören sollte, probier das mal, um zu sehen


Dim Temp As byte
....
....
Open "comd.7:9600,8,n,1" For Output As #2
For Shoulder_curr_pos = Shoulder_curr_pos To Servo_goto_pos Step Schritt
TEMP = shoulder_curr_pos
Print #2 , "#s" ; Chr(1) ; Chr(TEMP)

Der BasCom hat's nicht so mit verdeckten Typenänderungen
Is'n Versuch, du kannst für alle Servos das gleiche TEMP nehmen.

jagdfalke
02.07.2005, 12:46
Aber komischerweise funktionierts ja auch mit Servo = 0 also der Schulter vom Arm. Hab Temp mal eingeführt und es so gemacht wie oben. Geht aber immernoch nicht. Die Ausgaben für Temp, Goto_pos und Schritt im passen alle (überprüft im Terminal).

Wenn ich aber dern Servo 3 in der schleife von Servo = 0 laufen lass, dann geht er einwandfrei. Ich werd nicht schlau daraus.

PicNick
02.07.2005, 12:58
mmmm.

Ganz was blödes: Wie schaut's mit den Größen von Soft-Stack und Frame aus ?
Ich verwend HW 128 /SW 256 /Fram 32
Auch da kann er spinnen

so , bis morgen !

jagdfalke
02.07.2005, 12:59
was zu geier bedeutet das?

HW 128 /SW 256 /Fram 32

recycle
02.07.2005, 13:07
was zu geier bedeutet das?
Zitat:
HW 128 /SW 256 /Fram 32


Das sind Einstellungen, wie der Bascom-Compiler die internen Resourcen des Controllers nutzt (oder so ähnlich)
Guck in Bascom mal durch die Menüs, dann findest du Dialoge, in denen du das Vorgeben kannst. Vermutlich kann man es auch im Quellcode angeben.

jagdfalke
02.07.2005, 13:19
habs gefunden unter Options->Compiler->Chip

Die Werte sind jetzt:
HW Stack = 128
Soft Stack = 256
Framesize = 32

Dennoch keine Änderung :(

jagdfalke
02.07.2005, 14:33
Ich hab 2 247Ncm Servos direkt angeschlossen um's zu testen. Kann es sein, dass irgendwie durch Überbelastung was kaputt gegangen ist? Obwohl es ja eigentlich nicht so sein dürfte, da wie oben schon gesagt der Servo 3 in der ersten For-Schleife funktioniert. Nur in der 2. nicht.

hier nochmal der komplette Code:



$crystal = 8000000
$baud = 9600

Declare Sub Stepper_move(byval Stepper_goto_pos As Word)
Declare Sub Elbow_move(byval Servo_goto_pos As Integer)
Declare Sub Shoulder_move(byval Servo_goto_pos As Integer)

Const Writepowerport_adr = &H72 'I2C Adr PCF 2
Const Readpowerport_adr = &H73 'I2C Adr PCF 2

Dim I2cdaten As Byte 'Datenbyte aus PCF8574


Dim I As Integer


$crystal = 8000000 'Quarzfrequenz
Config Scl = Portc.0 'Ports fuer IIC-Bus
Config Sda = Portc.1
I2cinit

Config Pind.6 = Output 'Schrittmotoren Ein/Aus
Config Pinc.5 = Output 'Schrittmotor Links Richtung
Config Pinc.3 = Output 'Schrittmotor Links Step

Config Pinc.4 = Output 'Schrittmotor Rechts Richtung
Config Pinc.2 = Output 'Schrittmotor Rechts Step


Portd.6 = 0 'Schrittmotoren einschalten


Dim Stepper_curr_pos As Integer
Stepper_curr_pos = 0

Dim Shoulder_curr_pos As Integer
Shoulder_curr_pos = 127

Dim Elbow_curr_pos As Integer
Elbow_curr_pos = 127

Dim Temp as Byte

Hauptschleife:
'Call Stepper_move(100)
'Wait 2
'Call Stepper_move(0)
'Wait 2
Wait 2
Call Elbow_move(255)
Wait 2
Call Elbow_move(0)
Goto Hauptschleife



Sub Shoulder_move(byval Servo_goto_pos As Integer)
Local Schritt As Integer

If Shoulder_curr_pos < Servo_goto_pos Then
Schritt = 1
Elseif Shoulder_curr_pos > Servo_goto_pos Then
Schritt = -1
Elseif Shoulder_curr_pos = Servo_goto_pos Then
Exit Sub
End If

Open "comd.7:9600,8,n,1" For Output As #2
For Shoulder_curr_pos = Shoulder_curr_pos To Servo_goto_pos Step Schritt
Print #2 , "#s" ; Chr(1) ; Chr(shoulder_curr_pos)
Print #2 , "#s" ; Chr(2) ; Chr(shoulder_curr_pos)
Next Shoulder_curr_pos
Close #2

Shoulder_curr_pos = Servo_goto_pos
End Sub


Sub Elbow_move(byval Servo_goto_pos As Integer)
Local Schritt As Integer

Print "elbow_move called"

If Elbow_curr_pos < Servo_goto_pos Then
Schritt = 1
Elseif Elbow_curr_pos > Servo_goto_pos Then
Schritt = -1
Elseif Shoulder_curr_pos = Servo_goto_pos Then
Exit Sub
End If

Open "comd.7:9600,8,n,1" For Output As #2
For Elbow_curr_pos = Elbow_curr_pos To Servo_goto_pos Step Schritt
Temp = Elbow_curr_pos
Print #2 , "#s" ; Chr(3) ; Chr(temp)
Print "Schritt: " ; Schritt ; " CURR: " ; Temp ; " GOTO: " ; Servo_goto_pos
Next Elbow_curr_pos
Close #2

Elbow_curr_pos = Servo_goto_pos


End Sub




Sub Stepper_move(byval Stepper_goto_pos As Intgeger)

Local Betrag As Integer

If Stepper_goto_pos > Stepper_curr_pos Then

Betrag = Stepper_goto_pos - Stepper_curr_pos

Portc.5 = 0 'Richtung
Portc.3 = 0

For I = 0 To Betrag Step 1
Portc.3 = 0
Waitms 5
Portc.3 = 1
Waitms 20
Next I

Stepper_curr_pos = Stepper_goto_pos
Print Stepper_curr_pos

Elseif Stepper_goto_pos < Stepper_curr_pos Then

Betrag = Stepper_curr_pos - Stepper_goto_pos

Portc.5 = 1 'Richtung
Portc.3 = 0

For I = 0 To Betrag Step 1
Portc.3 = 0
Waitms 5
Portc.3 = 1
Waitms 20
Next I
Stepper_curr_pos = Stepper_goto_pos
Print Stepper_curr_pos

End If


End Sub


End


mfg
jagdfalke

jagdfalke
02.07.2005, 15:00
hab was neues rausgefunden:
wenn ich diesen code als hauptschleife benutze:

Hauptschleife:
Wait 2
Call Elbow_move(255)
Wait 2
Call Shoulder_move(0)
Wait 2
Call Shoulder_move(255)
Wait 2
Call Elbow_move(0)
Goto Hauptschleife

dann macht er die erste Bewegung, also Call Elbow_move(255) NICHT !!!! Call Elbow_move(0) macht er allerdings dann, und wenn er einmal soweit war macht er auch Call Elbow_move(255).
Er macht also alles, lässt aber Call Elbow_move(255) im allerersten Durchlauf aus (eigenlich lässt er ihn nicht aus, es bewegt sich einfach nichts, obwohl das Sub ausgeführt wird).
Vielleicht hilf das !?

mfg
jagdfalke

PicNick
03.07.2005, 08:00
Ich muß erst noch Gartenarbeit machen, dann schau ich mir das gaaanz genau an.
Inzwischen mach auf jeden Fall eins:
Den Open COm#2 EINMAL vor die Hauptschleife und raus aus den Subs, den Close brauchst du garnicht, der nutzt eh nix.

Weil ich es genau testen will: Verwendest du RNS1 oder den RNKC10 vom Kjion ?

jagdfalke
03.07.2005, 16:30
ich benutze den rns1

03.07.2005, 18:41
*hmm* Verwend' ich auch, nie was derartiges erlebt. *grmpf*
Mystisch.
Kannst du mal dein .Bas in der letztversion rein posten ?
ich muß das einfach sehen und 1:1 meinen BasCom rein pusten.
*zumeierlegenseheinfachnix"

Ich glaub ja nicht, daß es daran liegt, aber ich steuere den RNS1 mit der HW-UART. Vielleicht können wir so den Hund einkreisen, das ist ja lächerlich

PicNick
03.07.2005, 18:43
Da hat mich doch das Ferkel unter dem H... ausgeloggt.

Ich bin's, der PicNick !

jagdfalke
03.07.2005, 19:12
Hier mal der Code, der nicht funktioniert:



$crystal = 8000000
$baud = 9600

Declare Sub Stepper_move(byval Stepper_goto_pos As Word)

Declare Sub Shoulder_move(byval Shoulder_goto_pos As Integer)
Declare Sub Elbow_move(byval Elbow_goto_pos As Integer)

Const Writepowerport_adr = &H72 'I2C Adr PCF 2
Const Readpowerport_adr = &H73 'I2C Adr PCF 2

Dim I2cdaten As Byte 'Datenbyte aus PCF8574


Dim I As Integer


$crystal = 8000000 'Quarzfrequenz
Config Scl = Portc.0 'Ports fuer IIC-Bus
Config Sda = Portc.1
I2cinit

Config Pind.6 = Output 'Schrittmotoren Ein/Aus
Config Pinc.5 = Output 'Schrittmotor Links Richtung
Config Pinc.3 = Output 'Schrittmotor Links Step

Config Pinc.4 = Output 'Schrittmotor Rechts Richtung
Config Pinc.2 = Output 'Schrittmotor Rechts Step


Portd.6 = 0 'Schrittmotoren ausschalten


Dim Stepper_curr_pos As Integer
Stepper_curr_pos = 0

Dim Shoulder_curr_pos As Integer
Shoulder_curr_pos = 127

Dim Elbow_curr_pos As Integer
Elbow_curr_pos = 127

Dim Temp As Byte

Hauptschleife:

Call Elbow_move(0)
Wait 1
Call Shoulder_move(255)
Wait 1

Goto Hauptschleife




Sub Shoulder_move(byval Shoulder_goto_pos As Integer)
Local Schritt As Integer

If Shoulder_curr_pos < Shoulder_goto_pos Then
Schritt = 1
Elseif Shoulder_curr_pos > Shoulder_goto_pos Then
Schritt = -1
Elseif Shoulder_curr_pos = Shoulder_goto_pos Then
Exit Sub
End If

Open "comd.7:9600,8,n,1" For Output As #2
For Shoulder_curr_pos = Shoulder_curr_pos To Shoulder_goto_pos Step Schritt
Temp = Shoulder_curr_pos
Print #2 , "#s" ; Chr(1) ; Chr(temp)
Print #2 , "#s" ; Chr(2) ; Chr(temp)
Print "SHOULDER: " ; "Schritt: " ; Schritt ; " CURR: " ; Temp ; " GOTO: " ; Shoulder_goto_pos
Next Shoulder_curr_pos
Close #2

Shoulder_curr_pos = Shoulder_goto_pos
End Sub


Sub Elbow_move(byval Elbow_goto_pos As Integer)
Local Schritt As Integer

If Elbow_curr_pos < Elbow_goto_pos Then
Schritt = 1
Elseif Elbow_curr_pos > Elbow_goto_pos Then
Schritt = -1
Elseif Elbow_curr_pos = Elbow_goto_pos Then
Exit Sub
End If

Print "elbow"

Open "comd.7:9600,8,n,1" For Output As #2
For Elbow_curr_pos = Elbow_curr_pos To Elbow_goto_pos Step Schritt
Temp = Elbow_curr_pos
Print #2 , "#s" ; Chr(3) ; Chr(temp)
Print "ELBOW: " ; "Schritt: " ; Schritt ; " CURR: " ; Temp ; " GOTO: " ; Elbow_goto_pos
Next Elbow_curr_pos
Close #2

Elbow_curr_pos = Elbow_goto_pos

End Sub


Sub Stepper_move(byval Stepper_goto_pos As Intgeger)

Local Betrag As Integer

If Stepper_goto_pos > Stepper_curr_pos Then

Betrag = Stepper_goto_pos - Stepper_curr_pos

Portc.5 = 0 'Richtung
Portc.3 = 0

For I = 0 To Betrag Step 1
Portc.3 = 0
Waitms 5
Portc.3 = 1
Waitms 30
Next I

Stepper_curr_pos = Stepper_goto_pos
Print Stepper_curr_pos

Elseif Stepper_goto_pos < Stepper_curr_pos Then

Betrag = Stepper_curr_pos - Stepper_goto_pos

Portc.5 = 1 'Richtung
Portc.3 = 0

For I = 0 To Betrag Step 1
Portc.3 = 0
Waitms 5
Portc.3 = 1
Waitms 30
Next I
Stepper_curr_pos = Stepper_goto_pos
Print Stepper_curr_pos

End If


End Sub


End


Das seltsame ist, dass diese Hauptschleife funktioniert:


Hauptschleife:

Call Shoulder_move(255)
Wait 1
Call Elbow_move(0)
Wait 1

Goto Hauptschleife



diese aber nicht:


Hauptschleife:

Call Elbow_move(0)
Wait 1
Call Shoulder_move(255)
Wait 1

Goto Hauptschleife



hier bewegt sich die Schulter nach ewiger Zeit auf 255, dannach passiert nichts mehr, egal wie lange ich warte.

mfg
jagdfalke

jagdfalke
03.07.2005, 20:56
Ich glaub ja nicht, daß es daran liegt, aber ich steuere den RNS1 mit der HW-UART.

Ok, und das ganze nochmal auf deutsch bitte !?

PicNick
04.07.2005, 06:42
Morgen !

Ich hab das Zeugs auf meiner RNBFRA 1.2 getestet. Da ich die Sevos über die eingebaute UART bediene, hab ich die Open und Close natürlich auskommentieren müssen und die "Print #2" auf normale "print" umgebaut. klaro

Erwartungsgemäß geht das pipifein ohne Probleme.
D.h. Am Programm ist deswegen kein Fehler zu finden, weil keiner da ist.

Also irgendwas hats mit dem Open Com zu zun.
probier mal NUR EINEN Open VOR der Hauptschleife und sonst nix (close ist sowieso überflüssig)

jagdfalke
04.07.2005, 15:58
Cool, es funktioniert. Danke !
Kannst du dir das erklären?

PicNick
04.07.2005, 16:07
Das freut mich, da es ja wirklich sehr seltsam war.

Begründung: Tscha, Ich muß erst in die disassembler- listen schauen (stinkt nach Arbeit).
Irgendwie mag er es nicht, mehrfach open/close zu machen.

Jetzt kommt's drauf an: Wenn irgendwo steht, man darf das nicht, sind wir die Dummen.
Wenn aber nicht, und ich komm ihm auf einen Fehler drauf, sind die BasCom-Leute die Dummen, dann gibt's eins auf die Glocke.

Schau'n wir halt.

jagdfalke
04.07.2005, 16:14
Ok, wegen meiner Frage nach dem Grund brauchst du dir die Arbeit aber nicht machne, gelle! Ich bin einfach nur froh dass es klappt.

PicNick
04.07.2005, 16:17
Ich bin auch froh, als Fachmann steht man ja saublöd da, wenn man das Problem nicht irgendwie in den Griff kriegt.

Aber wenn im BasCom tatsächlich ein Unfug passiert, gehört das ausgebessert.

jagdfalke
04.07.2005, 16:20
Ja, das stimmt schon. Solche Fehler gehören ausgebessert. Wenn so Leute wie ich so ein Problem haben und kein Forum mit Profis auf dem Gebiet schauts natürlich schlecht aus !!! (Es soll ja noch Leute geben die kein Internet haben :D )