PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ZeichenKETTE einlesen und damit G'keit von 2 Steppern regeln



commander7
17.05.2005, 18:17
Hallo zusammen,

Ich habe eine Frage zum einlesen von Daten via RS232 in meinen ATmega8. Hab zwar schon zig Threads gelesen, bin aber doch nicht schlau geworden. Ich kann zwar schon einzelne Ascii-Werte einlesen und die als Echo an meinen PC zurücksenden, jedoch holt der Inkey() Befehl doch nur ein Zeichen nach dem anderen aus dem Buffer heraus und nicht eine ganze Zeichenfolge. Wie stelle ich das jetzt an, dass wenn ich dem AVR z.B. den Wert 255 sende, er mir nicht nacheiander 2 dann 5 und nochmal 5 zurückgibt, sondern er 255 in eine Variabel abspeichert. Hab dazu im Anhang mein bisheriges Programm angefügt.

Gruss commander7

pebisoft
17.05.2005, 18:50
$regfile = "m8def.dat"

Enable Interrupts

$crystal = 8000000
$baud = 9600

Dim Test As String * 10

Do

Input Test
waitms 500
print test

Loop

End

mfg pebisoft

MrNiemand
17.05.2005, 19:32
$regfile = "m8def.dat"
$crystal = 16000000
$baud = 38400

On Urxc Rs232int
Enable Urxc
Enable Interrupts



Rs232int:
If Udr = 13 Then 'return?

Instring = Buf + Chr(udr)
Bc = Len(instring)
Bc = Bc - 1
Instring = Mid(instring , 2 , Bc)



Buf = ""
'Print "instring: " ; Instring


Else
Buf = Buf + Chr(udr)

'add to buffer
End If

Return


Nur so ca. halt lässt sich noch vereinfachen in Instring steckt dann die der aktuelle Inhalt der bis zum letztn Chr(13) gekommen ist

Fehlen halt noch die Dims der Variablen aber das wirst du hinbekommen oder?

commander7
28.05.2005, 17:58
hallo zusammen

ich bin nun einen Schritt weiter gegangen, da das einlesen der Zeichenkette nun funktioniert. Bei meinem weiterentwickelten Programm will ich per RS232 einen Wert einlesen und anhand von diesem die Geschwindigkeit des Timer1 regeln. Wenn der Timer1 abgelaufen ist, soll ein Interrupt ausgelöst werden und in diesem soll der Motor einen Schritt machen.

Erfreulicherweise dreht sich der Motor auch ganz langsam, aber leider bewirkt das Senden einer neuen Geschwindigkeit beim Timer gar nichts. Das Zeichen empfängt er aber richtig, da ich es mit dem Echo konrollieren kann.

Kann mir jemand einen Tipp geben, was an meinem Programm falsch ist, das der Timer1 seine "Geschwindigkeit" nicht ändert?

Michael
28.05.2005, 18:40
Hallo commander7,
du mußt den Timer im Interrupt verstellen bzw. neu laden.
Bei deiner Variante ist beim nächsten IRQ alles beim alten.
Gruß, Michael

commander7
28.05.2005, 19:02
hallo michael,
danke für die antwort. mit welchem befehl tue ich das?

gruss commander7

Michael
28.05.2005, 19:17
Hallo commander7,

mit welchem befehl tue ich das?
mit Timer1 = Tempo.
Der muß aber aus dem Hauptprogramm raus und in den IRQ.
Gruß, Michael

commander7
29.05.2005, 20:05
hallo michael,

ich habe jetzt Timer = Tempo im Interrupthandler gleich oben an Return geschrieben. Leider aber dreht der Motor immer noch stur seine Runden ohne die Geschwindigkeit zu ändern. Hast du noch einen Rat?

gruss commander7

Michael
29.05.2005, 21:30
Hallo commander7,

Leider aber dreht der Motor immer noch stur seine Runden ohne die Geschwindigkeit zu ändern.
Das mag daran liegen, daß Tempo eine Byte-Variable ist und Timer1 ein Word.
Du änderst also maximal den 256ten Teil, oder 0,4%. Klar daß du nicht merkst, ob der Motor schneller wird.

Hast du noch einen Rat?
Du könntest die Variable Tempo mit 256 multiplizieren und diesen Wert in den Timer1 schreiben. Vermeide aber Rechenaufgaben im Interrupt.
Gruß, Michael

commander7
04.06.2005, 23:59
hallo,

Hab es nun hingekriegt, dass Tempo zu ändern *freu*. Aber eben erst mit einem Motor und ich will aber schon zwei ansteuern. Mit dem jetztigen Programm dreht sich der linke Stepper (Timer0) einwandfei. Ich habe nun für den rechten Motor den Timer2 eingesetzt, da Timer1 ja ein 16Bit Timer ist. Das Problem ist aber, dass sich betreffende Motor zwar vorwärts und rückwärts dreht, aber sein Tempo ist viel zu schnell und es kann nur geringfügig geändert werden. Das heisst im Klartext: Linker Motor läuft richtig, Rechter aber schon bei kleinem Tempo ( < 10) viel schneller und wenn ich mit dem Tempo hochfahre dann fängt er schon früh an zu stocken, da er wie ich vermute nicht so schnell drehen kann.

Ist es möglich, dass der Fehler eintritt, weil sich Timer0 und Timer2 irgendwie in die Quere kommen oder hab ich was falsch programmiert?

Erklärung zur Ansteuerung:
Über das CommControl sende ich via RS232 zuerst die Geschwindigkeit (-236 bis 236) und für den linken Motor als Code für den AVR eine 100 und für den Rechten ein 101.


gruss commander7

recycle
05.06.2005, 00:36
Hab es nun hingekriegt, dass Tempo zu ändern *freu*. Aber eben erst mit einem Motor und ich will aber schon zwei ansteuern. Mit dem jetztigen Programm dreht sich der linke Stepper (Timer0) einwandfei.

Kannst du nicht beide Motoren über den selben Timer steuern?
Anstatt den Timerintervall zu ändern, könntest du doch mit festem Intervall eine Funktion aufrufen und in dieser Funktion entscheiden, ob die Motoren einen Schritt machen oder nicht.

ungefähr so:


Dim Tempolinks As Byte
Dim Temporechts As Byte
Dim Temp As Byte
Const X = 255


Sub Go()
Incr Temp
If Temp > Tempolinks Then Call Rechtermotorvor()
If Temp > Temporechts Then Call Rechtermotorvor()
If Temp = X Then Temp = 0
End Sub



Timerirq:
Call Go()
Return

Bei X = 255 hoppelt dein Roboter vermutlich etwas um die Kurve, wenn du mit weniger Geschwindigkeitsstufen auskommst, könntest du X kleiner und dafür den Timerintervall entsprechend grösser machen.

Das ist aber eh nur eine auf die schnelle hingeschmierte Idee. Es gibt sicherlich elegantere Lösungen beide Motoren mit einem Timer zu steuern. Den 2. Timer wirst du sicher irgendwann auch noch für was anderes gut gebrauchen können.

commander7
05.06.2005, 09:27
Hallo recycle,

Ja du hast es auf den Punkt gebracht. Das beste wäre wirklich beide Motoren mit nur einem Stepper zu steuern. Dazu fehlt mir aber bis jetzt der passende Ansatz.
Bei deinem Beispiel blicke ich aber noch nicht ganz durch. Sollte da nicht bei
If Temp > Tempolinks Then Call Rechtermotorvor()
If Temp > Tempolinks Then Call Linkermotorvor() stehen. Andernfals verstehe ich den Ansatz gar nicht mehr. Und ausseredem ist ja da Vorwärts/Rückwärts noch nicht berücksichtigt (oder täusche ich mich da?), könnte man das nicht auch hineinbringen.

Aber wenn du schon sagst,
Das ist aber eh nur eine auf die schnelle hingeschmierte Idee. hoffe ich das sich jemand meldet der einen eleganten Ansatz kennt. Ich danke aber trotzdem für die Starthilfe.


Gruss commander7

PicNick
05.06.2005, 09:41
Hi, ich mach das so: Ich laß den Timer0 mit 1 mS permanent tickern. Und für jeden Motor gibt es einen Wert, nach wieviel solchen Tickern er einen Step machen soll (=Geschwindigkeit).
Die Festlegung der Richtung der einzelnen Motoren und der Speed-wert werden woanders festgelegt (also bei dir in der PC-Kommandobearbeitung, bei anderen durch Sensoren, etc)

Michael
05.06.2005, 11:24
Hallo commander7,

Ist es möglich, dass der Fehler eintritt, weil sich Timer0 und Timer2 irgendwie in die Quere kommen oder hab ich was falsch programmiert?
prinzipiell solltest du systematisch vorgehen und dein Programm Schritt für Schritt ausbauen.
Das was du vorhast geht aber. Hier ein Video:
http://www.team-iwan.de/videos/pics/xr-120-90.jpg (http://www.team-iwan.de/videos/vids/xrace-lr.wmv)
Bei diesem Roboter werden die Schrittmotoren über Timer0 und Timer1 angesteuert(Timer2 hat er nicht). Damit kann er saubere Kurven ohne Ruckeln fahren.
Versuche also erstmal Timer2 richtig zum laufen zu bringen, erster Ansatz wäre, gleiche Werte in beide Timer zu schreiben, dann siehst du, ob Timer2 richtig funktioniert.
Gruß, Michael

commander7
05.06.2005, 11:26
hallo PicNick,

vielen dank für deine Antwort. Könntest du mir noch ein wenig nachhelfen (wie sag ich dem AVR nach wievielen Ticks er den Step machen soll?). Ich bin noch Anfänger bei der Programmierung von AVR Chips und das oben gepostete Programm von mir ist das Beste, was ich im Moment hinkriege.

gruss commander7

PicNick
05.06.2005, 11:59
Naja, ich versuch mal das wesentliche zusammenzufassen


$crystal = 8000000 'Quarzfrequenz
$baud = 9600 'Baudrate für RS232

Config Timer0 = Timer , Prescale = 64 'Timer 1mS
Const Tmr_c_preload = 131

Dim Timflag As Byte

Dim Stpleft As Byte '
Dim Speedleft As Byte '

Dim Stpright As Byte '
Dim Speedright As Byte '

Enable Interrupts 'General enable

On Timer0 Interrupt_ticker ' Timer for Timer Queue

Enable Timer0
Start Timer0 ' timer starten

Timer0 = Tmr_c_preload


Speedleft = 10 ' Geschwindigkeit linker Mot
' je kleiner, je schneller
' ca 2 od. 3 ist maximum, je nach motor
Speedright = 15 ' rechter Mot (etwas langsamer)



Do
if Timflag = 1 then
Timflag = 0
decr Stpleft
if Stpleft = 0 then
Stpleft = Speedleft
call schrittlinks() ' ein schritt linker motor
end if
decr Stpright
if Stpright = 0 then
Stpright = Speedright
call schrittrechts() ' ein schritt rechter motor
end if
end if


Loop

End

'=============================
Interrupt_ticker:
Timer0 = Tmr_c_preload
Timflag = 1
Return

Wie gesagt, der Timer gibt alle mS ein Signal
das merkt er in der Do-Schleife und setzt das Signal zurück.
dann wird erst vom linken Zähler eins abgezogen
kommt null raus, --> ein Schritt und Zähler wieder auf "speed"

dann dasselbe rechts

In einer mS mach der 8 MHZ - avr 8000 Cycles, d.h Zeit genug, zwischendurch sich mit der Tastatur zu befassen oder mit sensoren.
Warteschleifen sind allerding pfui.

Die Speed kann jederzeit irgendwo anders im Programm geändert werden

commander7
05.06.2005, 16:05
@PicNick:
Vielen Dank, werde mal versuchen damit etwas zurechtzubasteln.

@Michael:
hab mal den Timer2 etwas untersucht. Bei meinem Programm für nur einenen Stepper funktioniert alles mit dem Timer0 einwandrei. Nun habe ich das mal mit dem Timer2 getestet und schon fing der Motor wieder an zu meckern. Die Richtung stimmt zwar und ändert sich richtig, aber schon bei Tempo = 0 dreht der Motor sehr schnell und wenn ich das Tempo nur wenig erhohe, dann fängt er an zu stocken bis hin zum Pfeiffkonzert (übrigens genau gleich wie mit beiden Motoren gleichzeitig).
Ich kann einen Hardwarefehler ausschliessen, da ich das gleiche Problem auch mit dem anderen Motortreiber und Stepper probiert habe.
Tritt genau das gleiche Problem auf.

Timer0 und Timer2 sollten doch bei einem AtMega8 genau gleich sein, nur der Timer1 ist doch ein 16Bit Timer.
Könnte vieleicht an den Fuses etwas falsch eingestellt sein, oder was stimmt sonst mit meinem Timer2 nicht ???

gruss commander7

Michael
05.06.2005, 16:45
Hallo commander7,

nur der Timer1 ist doch ein 16Bit Timer.
du kannst ihn ja zw. 65280 und 65535 betreiben. Dann verhält er sich (in diesem Fall) wie ein 8 bit Timer.


Nun habe ich das mal mit dem Timer2 getestet und schon fing der Motor wieder an zu meckern....
....oder was stimmt sonst mit meinem Timer2 nicht ???
wahrscheinlich wird Timer2 von Bascom nicht richtig angesprochen.

Gruß, Michael

commander7
05.06.2005, 19:17
was kann man da machen? Habe Bascom Version 1.11.7.3.

gruss commander7

commander7
05.06.2005, 20:13
Hab es nun mit dem Timer1 und 65280 - 65535 hingekriegt und die Timer kommen sich nicht spürbar in den Weg. Glücklich bin ich damit aber noch nicht ganz. Es nimmt mich schwer wunder was mit dem Timer2 los ist...

Hatte jemand auch schon ein solches Problem???

mfg commander7

recycle
06.06.2005, 01:14
@Commander7

Bei deinem Beispiel blicke ich aber noch nicht ganz durch. Sollte da nicht bei
If Temp > Tempolinks Then Call Rechtermotorvor()
If Temp > Tempolinks Then Call Linkermotorvor() stehen. Andernfals verstehe ich den Ansatz gar nicht mehr.

Hast recht, da habe ich mich verschrieben.


Und ausseredem ist ja da Vorwärts/Rückwärts noch nicht berücksichtigt
Stimmt. Ich wollte ja auch nicht das komplette Programm für dich schreiben, sondern nur einen Vorschlag machen, wie man beide Motoren über einen Timer ansteuern könnte.
Im Prinzip sollte das Programmschnippsel dasselbe ausdrücken, was PicNick dir anschliessen in Worten geschrieben hat.
Der Timer gibt einfach nur einen festen Takt vor. Ob und in welche Richtung die einzelnen Motoren dann bei diesem Takt einen Schritt machen bestimmst du ausserhalb der Interruptfunktion des Timers.

Wenn du vorwärts und rückwärts berücksichtigst bleibt as Prinzip ja dasselbe.

Wenn du zwei Timer für die Motoren verwendest könntest du irgendwann vor dem Problem stehen, dass du zuwenige Timer hast, weil es in Bascom auch einige Funktionen gibt die intern einen der Timer benötigen.