ich bin zur Zeit an einem schulischen Projekt. Ich schicke über mein CANOe auf dem PC diverse CAN-Botschaften auf mein Arduino-CAN-Shield, mein Arduino liest die Botschaft aus (diese Besteht aus Geschwindigkeit, Schrittanzahl, Drehrichtung) und von da soll es auf einen Schrittmotor gehen der dann aus und ein fahrt.
Ich habe das jetzt so mit dem Arduino Mega programmiert das sich meine Schrittmotor befehle in einer ISR sich befinden, das ich auch während dem Aus und Einfahren des Motors weiterhin CAN-Botschaften empfangen kann. Nur leider funktioniert das ganze innerhalb der ISR, mit einem normalen DC Motor funktioniert das so wie gewollt.
Habt ihr Ideen wie ich das lösen kann? Weiteres Problem ist, das wenn ich das ganze in meinem loop mache, das ich dann keine Botschaften mehr über den Bus erhalte. Wie erwähnt funktioniert das ganze mit einem DC Motor recht gut, aber da werden halt keine extra Libs benötigt.
analogWrite(motorSpeedPin, Geschwindigkeit); //Drehzahl Motor
digitalWrite(controlPin1, HIGH); //Drehrichtung Motor
digitalWrite(controlPin2, LOW); //Drehrichtung Motor
Bei geeigneter Programmierung stören sich Interrupts gegenseitig kaum. Du brauchst also eine Stepper-Bibliothek, die auch mit Interrupts arbeitet, wie das alle guten Bibliotheken machen.
DrDiettrich:
Du brauchst also eine Stepper-Bibliothek, die auch mit Interrupts arbeitet, wie das alle guten Bibliotheken machen.
DrDiettrich:
Am professionellsten ist die AccelStepper Bibliothek.
Die arbeitet aber auch nicht mit Interrupts, sondern vertraut darauf, dass ihre 'run' Methode im loop oft genug aufgerufen wird. Ich habe eine eigene Lib, die den Motor im Timerinterrupt ansteuert, d.h. der läuft z.B. auch noch während eines delay() weiter. Allerdings hat sie (noch) keine Anfahr- und Bremsrampe wie die AccelStepper.
Wenn Du eine Lib kennst, die den Stepper per Interrupt ansteuert, würde mich das auch sehr interessieren.
DrDiettrich:
Was erwartest Du, wenn Du Stepper.step(1000); einmal in loop() aufrufst? Wie soll das ohne Interrupts weitergehen?
Du bist gedanklich bei einer anderen Bibliothek, die Methode step gibt es bei AccelStepper nicht.
Stepper.run(); muß möglichst häufig aufgerufen werden, macht die Bewegung:
/// Poll the motor and step it if a step is due, implementing
/// accelerations and decelerations to achive the ratget position. You must call this as
/// fequently as possible, but at least once per minimum step interval,
/// preferably in your main loop.
/// \return true if the motor is at the target position.
boolean run();
Für neue Ziele gibt es dann beispielsweise sowas:
/// Set the target position. The run() function will try to move the motor
/// from the current position to the target position set by the most
/// recent call to this function.
/// \param[in] absolute The desired absolute position. Negative is
/// anticlockwise from the 0 position.
void moveTo(long absolute);
DrDiettrich:
Trotzdem bleibt die Frage: was stört Dich bei Stepper.run()? Auch wenn das ständig in loop() aufgerufen werden muß, dazu ist loop() ja schließlich da.
Es war deine Aussage, dass eine Stepper Lib gebraucht wird, die mit Interrupts arbeitet ( und dass das alle guten Libs so machen ).
Die loop-Version kann problematisch werden, wenn ein komplexer Sketch mit entsprechenden loop-Laufzeiten und schnelle Schrittmotorbewegung mit evtl. noch Microstepping zusammenkommen. Die AccelStepper macht pro run()-Aufruf immer nur einen Schritt.
Das ist Bestandteil meiner MobaTools. Einzeln gibt's das nicht, da sich dort verschiedene Klassen den Timer 1 teilen. Aber man muss natürlich nicht alle Klassen nutzen und instanziieren - man kann auch nur den Stepper nutzen. Dann liegt gegebenenfalls halt etwas Code brach . Einen Teil wird der Compiler wegoptimieren, aber überall klappt das nicht. Aber solange es in's Flash reinpasst...
Die Lib hat aber auch Grenzen, was die Motorgeschwindigkeit angeht. Derzeit ist das Timerraster auf 200µs festgelegt.
Ja, diese Aussage war falsch. Nach nochmaligem Wühlen in der Adafruit Dokumentation bin ich mir nicht sicher, was mit diesem Shield und Bibliothek überhaupt möglich ist. Eigentlich müßte ein Shield mit I2C Anschluß selbständig arbeiten können, die Beispiele sehen aber nicht danach aus.
MicroBahner:
Das ist Bestandteil meiner MobaTools.
Na die habe ich doch, gerade aktualisiert. Danke
DrDiettrich:
Eigentlich müßte ein Shield mit I2C Anschluß ...
Ich fürchte, nur die Adafruit_Motor_Shield_V2_Library eventuell mit AccelStepper zusammen kann diese sehr spezielle Hardware ansteuern. Daher dürften alle gut gemeinten Ratschläge, andere Bibliotheken betreffend, in die Irre führen.
rosch92:
Wo finde ich so eine Lib die auch in Interrupts funktioniert?
Vermutlich nirgendwo.
Daten von CAN einlesen, auswerten und der Stepper-Bibliothek übergeben, dafür benötigst Du nach meiner Einschätzung keine ISR.
Anmerkung: Die CAN-Schnittstelle dürfte wie die serielle im Hintergrund mit Interrupts arbeiten.
Problem ist das wenn während der Bewegung des Motors eine erneute CAN-Message kommt, sich auf meinem Bus nichts mehr regt und der auch nichts mehr empfängt. Wenn das ganze in nem Interrupt wäre, könnte mein Bus auch während der Bewegung CAN Botschaften auswerten.
Oder gibts da einen Trick?
Problem ist das wenn während der Bewegung des Motors eine erneute CAN-Message kommt, sich auf meinem Bus nichts mehr regt und der auch nichts mehr empfängt. Wenn das ganze in nem Interrupt wäre, könnte mein Bus auch während der Bewegung CAN Botschaften auswerten.
Oder gibts da einen Trick?
Trick?
Debuggen, den Fehler beheben.
In Nebenläufigkeiten denken.
Nicht blockierenden Code schreiben.
combie:
Ich behaupte:
Du hast "between" gelesen, aber dein Hirn hat daraus "in range of" draus gemacht.
Die 0x60 ist eine gültige Adresse, die 0x80 aber nicht. mein Gehirn ist leider nicht in der Lage, diesen Umstand aus dem Wörtchen "between" herauszuinterpretieren. Da wünschte ich mir eine eindeutigere Formulierung.
Auf Stacking Shields ist Lady Ada meinem von postmaster-ino übernommenem Vorschlag gefolgt:
"You can adjust the address of the shields to range from 0x60 to 0x7F for a total of 32 unique addresses."
So lange ein Interrupt bearbeitet wird, sind andere Interrupts gesperrt. Es wäre also völlig falsch, lang laufenden Code in eine ISR zu legen.
Der Stepper-Treiber wartet die ganze Zeit nur darauf, wann der nächste Impuls ausgegeben werden soll. Dieses Warten sollte eigentlich blitzschnell abgehandelt werden, und der CAN Firmware ständig genügend Zeit übrig lassen. Einige Methoden können aber blockierend implementiert sein, es kommt also drauf an, welche Bibliothek und welche Methode(n) Du verwendest.