Hallo, ich verzweifele gerade ein wenig an meiner Unfähigkeit. Ich habe eine ISR, die für den Schrittmotor zuständig ist. Sie soll den Motor entweder anhand einer Zielposition in Bewegung setzen, oder aber in eine Richtung schicken. Folgender Code hält den Motor nie mehr an, selbst wenn ich alle Variablen auf 0 setze (stepper.target, stepper.position, stepper_on). Aber das Problem ist wohl eher meine Un-Logik denn die Variablen. Kann mir bitte jemand zum AHA-Erlebnis verhelfen? :-)
ach mist: if(stepper.on || (stepper.position !=stepper.target)) { // so there's a reason to be moving // just .. which way? // either go straight to specified position // or go some direction if((stepper.on&&stepper.dir) || (stepper.target>stepper.position)) { // go down stepper.step --; stepper.position --; } if((stepper.on&&(!stepper.dir)) || (stepper.target<stepper.position)) { stepper.step++; stepper.position ++; } STEPPER_PORT=(STEPPER_PIN & ~STEP_MASK) | step[stepper.step]; // update stepper outputs } else { /* todo: turn off or hold properly*/ STEPPER_PORT=(STEPPER_PIN & ~STEP_MASK) | 0; // turn off / stepper.on=0; }
Es ist recht schwirig zu erraten, was die verschiedenen Variablen bedeuten und welche Wertebereiche sie annehmen können. Aber: die beiden folgenden Zeilen sollen Bits setzen und zurücksetzen. STEPPER_PORT=(STEPPER_PIN & ~STEP_MASK) | step[stepper.step]; // ok STEPPER_PORT=(STEPPER_PIN & ~STEP_MASK) | 0; // turn off / da wird nichts zurückgesetzt. vermute mal eher: STEPPER_PORT=(STEPPER_PIN & STEP_MASK); // turn off / Oder anders herum.
Hi Profi, danke für Deine Antwort! Es ging mir eher um die Struktur des ganzen, ich kann anscheinend keinen klaren Gedanken fassen. Bis ich versucht habe, auch die Zielvorgabe zu berücksichtigen, hat alles (soweit) problemlos funktioniert. Rauf, runter. Er gibt fleißig die richtigen Bitmuster aus. Nur jetzt fängt der Motor sofort an, sich zu bewegen, wenn die ISR durchlaufen wird.. Zu den Bitoperationen: das "| 0" hat tatsächlich keine Auswirkung. Die Negierung hat aber ihren Sinn (http://www.mikrocontroller.net/articles/Bitmanipulation#Bestimmte_Bits_l.F6schen_.28Standard_C.29)
Jetzt habe ich es auch gerade gesehen, wie Du es mit den Bits gemeint hast. zu Zielvorgabe: brauchst Du nicht eher 4 Fall-Unterscheidungen? 2 für die Richtung und 2 für < und >
Ha!
Das hab ich gestern auch gedacht, und seitdem verstehe ich nicht, wieso
ich mit 2*1 Bit weniger sinnvoll Informationen darstellen kann als mit
1*2 Bit.
"Off, Hold, Up, Down" sollte alles berücksichtigen, zumal damit mit
>1 das Schrittmuster ausgeführt werden kann, und andernfalls höchstens
noch der Strom abgeschaltet werden soll.
Allerdings hat er gestern auch damit immer noch Mist gebaut, ich werde
mich gleich nochmal in Ruhe darum kümmern.
Das meinte ich mit 'meine Logik': Wenn der Schrittmotor sich durch den Zustand 'rauf' bewegt, wird ja seine Position verändert (!= Soll). Die ISR steuert gegen, der Motor bleibt unter Strom stehen. Argh! Also entweder führe ich jetzt noch einen anderen Zustand ein, oder aktualisiere den Soll-Wert... Ich glaube, ein weiterer Zustand ist verständlicher..
So, jetzt funktioniert es endlich. Man sollte berücksichtigen: - Stimmt die Zählrichtung mit der Drehrichtung überein? - Falls vom Zählerstand 0 rückwärts gedreht wird, gibt es einen Überlauf (Motor dreht dann einmal durch den Wertebereich, bis Ist=Soll).
- Stimmt die Zählrichtung mit der Drehrichtung überein? genau das meinte ich mit den 4 Fallunterscheidungen: 2 für die Richtung ... Falls vom Zählerstand 0 rückwärts gedreht wird, gibt es einen Überlauf. das könnte man umgehen, indem man alle Variablen um 1 (oder 128) höher ansetzt. Bei 128 kann man dann statt des Carry-Flags das Vorzeichen-(S)-Flag abfragen. na, Hauptsache es geht. Kannst Du mal bitte den gesamten Code anhängen, würde mich interessieren. Danke!
Hallo, ich habe letztens vergebens nach bestehenden Schrittmotorroutinen gesucht, welche auch eine Beschleunigungs-/Bremsrampe enthalten. Durch Zufall fand ich dann einen Artikel in der CT, mit einem Beispielcode...welchen ich garnicht mal so schlecht finde. Vielleicht ist das ja auch was für Dich. Der Softlink der CT: ftp://ftp.heise.de/pub/ct/listings/0405-214.zip Gruss, Thomas
@Thomas: als ich obigen Post tippte, überlegte ich noch, ob ich was zu den Rampen schreiben soll. Jetzt hast Du damit angefangen. Von einem CT-Artikel (Heft5/2004 S.214) hätte ich mir etwas mehr Detail gewünscht als "An dieser Stelle wollen wir nicht verhehlen, dass das Ermitteln des optimalen Verlaufs mit viel Experimentieraufwand verbunden sein kann. ... Für die Beispielanwendung haben wir eine lineare Verringerung der Taktzeiten von Schritt zu Schritt angesetzt. ... Manchmal ist eine Exponentielle Beschleunigung günstiger, weil Resonanzbereiche schneller durchfahren werden und der Motor schneller die Drehzahl erreicht." Dazu muss ich aus 25-jähriger Stepper-Erfahrung sagen, das reicht für einfache Experimente aus. Will man einen Stepper ordentlich (ernsthaft) betreiben, muss man seine Gehirnwindungen etwas mehr strapazieren. Siehe meine Ausführungen im wiki: http://www.mikrocontroller.net/articles/Schrittmotoren
@Stepper-Profi Bezüglich der neuronalen Wicklungen kann ich Dir nur zustimmen. Meines Erachtens ist das, was in dem o.g. Programm als Beschleunigung gemacht wird, genau verkehrt herum. Im unteren Drehzahlbereich wird die Geschwindigkeit langsam verändert und im oberen viel zu schnell. Außerdem löst man mit einer 8 stufigen Rampe kein Problem. Mit der von Dir angeführten feinen Frequenzänderung bei hohen Drehzahlen kommt man locker auf 200-500 Rampenschritte von Start-Stop-Frequenz bis auf Solldrehzahl für schnelle Bewegung. Für eine 'gute' Rampe braucht man daher eine entsprechend große, zuvor berechnete Tabelle, oder man hat einen schnellen µC, der die Rampe in Echtzeit berechnet. Per µC kann man dann auch Gechwindigkeitsänderungen während der Fahrt vornehmen.
Hallo, es hat wohl jemand meine Verbindung gekappt, erst jetzt habe wieder Zugang zur Interwelt. Ist ja fast lebenswichtig! Leider habe ich einen herben Rückschlag einstecken müssen, nachdem es so erfolgreich aussah. Ich weiß auch nicht, wo der Fehler liegt. Ich habe wohl bei der Programmiererei eine Änderung zuviel vergessen, die einen neuen Fehler verursacht hat, den ich dann wiederum falsch bekämpft habe. Oder beim Flashen ist was schiefgelaufen, ich vertraue AVRdude irgendwie nicht so richtig. Zwischenzeitlich hat es gereicht, daß ich meinen Finger in die Nähe eines Tasters gehalten habe, damit das Programm ihn als geschaltet erkannt hat (active-low, internal pull-up an). Danach habe ich einige structs weggelassen und die volatile-variablen für die ISR 'normal' deklariert. Möglicherweise überlaste ich meine ISR aber schon wieder. Habe ein bißchen die Schnauze voll, wäre schön, wenn Ihr den entscheidenden Tip habt! Rampen etc. brauche ich vorerst nicht, wird vermutlich eh nicht in den Tiny2313 passen. Aber danke, ich guck's mir mal an. Anbei die ISR mit Peter Dannegers Entprellroutine, die Abfragefunktionen (da mag der Fehler liegen, weil eine Abfrage den Status ändert?), und die eigentliche Initialisierungsroutine für den Schrittmotor, mit Endschalter. Funktion: Schalter offen? -> Rauf, bis er schließt Runterfahren, bis er öffnet. Der erste Zustand wird (wurde mal) erkannt, aber danach geht nix mehr Ich habe versuchshalber noch einen Handtaster in der Abfrage, aber auch da passiert nicht das, was ich gerne hätte. Hier noch ein paar Variablen: // debounce inputs volatile uint8_t key_state, key_press, key_release; // stepper motor step patterns const uint8_t step[4] = {STEP_PATTERN}; volatile uint8_t stepper_mode, stepper_speed; volatile int16_t stepper_position, stepper_target; Vielleicht verstehe ich auch das 'volatile' miß, Peter Danneger hat es teilweise nicht in seinem Code.. Das sollte ich mal ausprobieren, aber habe erst nachher wieder Zeit. Danke schonmal für Euer Interesse!
Vielleicht sollte ich noch schreiben, daß F_CPU 4MHz ist, der ISR-Prescaler 64, das OCR ist mit 255 - also Aufruf alle 4ms..
Ich drängele nur ungerne, aber da ich leider nicht weiterkomme hätte ich gerne Anregungen zur Problemfindung und -lösung.. Jetziges Verhalten (Entprell-Variablen als volatile deklariert): Die Schalterabfrage läuft irgendwie falsch. stepper_init(); (!switch_state(1<<ZEROPOS)) wird richtig geprüft, aber die darauffolgenden Abfragen (while(switch_state()))funktionieren nicht wie gedacht, das Programm blockiert nicht, sondern läuft einfach weiter. Das ist mir schleierhaft, denn es wird ja durch switch_state() nichts verändert, weshalb folgende Abfragen ebenfalls gültig sein sollten. Ich hoffe, einer von Euch weiß Rat..
@Michael: genau das meine ich auch. Allerdings ist die Geschwindigkeit der CPU gar nicht nötig, man kann die Berechnungen vereinfachen. Wenn ich mal Zeit habe, gibt es im Wiki-Artikel eine Erweiterung mit Code. Mit Tabelle: ja, momentan mache ich es so, dass jeder Schritt beim Beschl/Bremsen einen Tabelleneintrag braucht. Allerdings kann man die Tabelle wesentlich verkürzen, wenn man zwischen den Einträgen interpoliert. @ichbin: wenn beim Annähern schon was ausgelöst wird, tippe ich auch auf ein Hardwareproblem: externe 1k-Pullups schon eingebaut (die Internen sind evtl. zu schwach)? Die Variablen key_xxx würde ich static machen. In so einem Fall baue ich gerne Debug-Ausgaben über die Serielle ein, die man am PC betrachten kann.
@Profi Hast Du schon 'mal eine automatische Umschaltung - z.B. zwischen 1/8 Schritt auf 1/2 Schritt - bei höheren Drehzahlen realisiert ? Die hohe Auflösung macht langsame Fahrten ruhiger und die gröbere Auflösung, reduziert die Interruptbelastung bei hohen Drehzahlen, wo 1/8 Schritt sowieso dummy ist.
Hi Profi, danke für deine Antwort. Diese Variablen sind wie in Peter Dannegers Codebeispielen global definiert, ein static macht doch daher nicht so viel Sinn, oder? Ich greife in einer ISR und in Funktionen darauf zu. Kann man denn die Entprell-Abfrage-Routinen überhaupt so einsetzen, wie ich es hier versuche (in einer while-Schleife pollen)?
Die ISR dauert gerade mal 18µs, überladen habe ich sie also auch nicht. ... Ich hatte noch eine Reihe von Variablen (structs, volatile) deklariert, die ich jetzt mal rausgeschmissen habe - schon bekomme ich sinnvolle Werte aus den Abfragefunktionen für die Entprellroutine. Ich kann nicht beurteilen, was da schiefläuft, aber - sollte der Compiler einen nicht warnen?
@Michael: bin ein Freund hoher Drehzahlen, deshalb nur 1/2 und 1/1-Schritt Umschalten sollte problemlos möglich sein, etwa bei 1-2 kHz. @ichbin: Du kannst den Warning-Level einstellen. Ich stelle immer alle Warnings an und code so, dass keine Warnings kommen. Aber in C kann man problemlos korrekten Code schreiben, der völlig unsinnig ist, denke an verschattete Variablen, Pointer und andere fiese Seiteneffekte.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.