Forum: Mikrocontroller und Digitale Elektronik Hilfe (Arduino) bei Schrittmotor Steuerung - Arduino zu langsam ?


von Daniel H. (schrauberhugo)


Lesenswert?

Moin ;D

Mein Ziel:

Ich möchte 3 Schrittmotoren meiner Fräsmaschine mit einem Arduino (Mega) 
steuern und die Position auf einem LCD ausgeben (Steuerung über Potis). 
Die benötigte Frequenz, die für die Motoren erzeugt werden muss, liegt 
bei 3,5 kHz, damit ich nicht einschlafe beim verfahren ;D

Mein Problem:

Damit es keine Schrittverluste gibt, benutze ich die AccelStepper 
Library zum Ansteuern. Bei dieser muss ich regelmäßig eine run()-Methode 
ausführen, damit 1 Puls bzw. Step erzeugt wird, falls genug Zeit 
verstrichen ist.  Die Frequenz mit der ich diese Funktion ausführe, muss 
also deutlich höher als 3,5 kHz liegen. Der Arduino braucht aber zu 
lange, um die Koordinaten per i2C-Protokoll auf das LCD zu übertragen 
und die Pins einzulesen, sodass mein Programm mit maximal 340 Hz läuft. 
:(((

Die Pulserzeugung auf einen zweiten Controller auszulagern funktioniert 
leider nicht, da ich dann die gezählten Schritte auch wieder übertragen 
müsste, und das dauert ja leider zu lange.

Hat jemand irgendeine Idee ?

Ich habe noch 2 STM32 mit 72 MHz da. Der Arduino hat nur 16MHz, aber die 
i2C-Übertragung braucht doch genauso lange oder ? Abgesehen davon ist 
die 4fache Geschwindigkeit auch noch nicht ganz genug.

Braucht es einen ganz anderen Controller ?


Viele Grüße von einem bastelnden Maschinenbau-Studenten, der sich an 
Software versucht  :O

: Bearbeitet durch User
von leo (Gast)


Lesenswert?

Daniel H. schrieb:
> Die Frequenz mit der ich diese Funktion ausführe, muss
> also deutlich höher als 3,5 kHz liegen. Der Arduino braucht aber zu
> lange, um die Koordinaten per i2C-Protokoll auf das LCD zu übertragen
> und die Pins einzulesen, sodass mein Programm mit maximal 340 Hz läuft.

Du musst den Ablauf der Funktionen entkoppeln. Die Anzeige kann ruhig 
langsamer laufen. Eine Library wie Tasker oder TaskScheduler hilft 
dabei.
Der Arduino ist sicher nicht zu langsam.

leo

von Daniel H. (schrauberhugo)


Lesenswert?

Hey Danke ;D
Und dann werden die Steps nicht unterbrochen ? Wenn die Wiederholung von 
step() unterbrochen wird, ruckelt der Motor und es kommt zu 
Schrittverlusten

von leo (Gast)


Lesenswert?

Daniel H. schrieb:
> Und dann werden die Steps nicht unterbrochen ?

Dein Programm bestimmt den Ablauf, es liegt an dir, was die CPU mit den 
16 MHz macht.

leo

von Johannes S. (Gast)


Lesenswert?

als abgehangenen Standard gibt es doch grbl, das läuft auf einem 
Mega2560 und auch auf den Bluepills mit STM32F103. Schrittfrequenzen 
habe ich nicht mehr genau im Kopf, aber 30 kHz sollten beim Mega2560 
drin sein.

von Gabriel M. (gabse)


Lesenswert?

Je nachdem welchen LCD Controller du verwendest könntest du auch die I2C 
Bittrate erhöhen. Besser wäre es aber das ganze versuchen Intelligent zu 
lösen. z.B. über Interrupts.

von Daniel H. (schrauberhugo)


Lesenswert?

OK, Ich versuche es mal mit der TaskScheduler Library. Die Frequenz an 
sich ist ja kein Problem, nur muss der Arduino, während der i2C 
Übertragung an das LCD mehrfach step() ausführen. Wie das gehen soll auf 
einem Board mit nur einem CPU kann ich mir gerade nicht vorstellen, da 
fehlt mir das Verständnis

von Johannes S. (Gast)


Lesenswert?

Interrupts sind das Zauberwort, ausgelöst von einem Hardwaretimer.

von Daniel H. (schrauberhugo)


Lesenswert?

Funktionieren Interrupts auch innerhalb der i2c-Übertragung ? Ideal wäre 
dass die Übertragung zB. alle 100us unterbrochen wird.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Entweder man verwendet eine Hardware I2C Schnitte, oder man unterbricht 
die I2C Übertragung ein paar mal. Denn bei einem 400kHz I2C kann man 
z.B. Nach jedem 10 Bit unterbrechen und ist dann immer noch 10x 
schneller als 3,5kHz...

Daniel H. schrieb:
> Funktionieren Interrupts auch innerhalb der i2c-Übertragung ? Ideal wäre
> dass die Übertragung zB. alle 100us unterbrochen wird
Kommt auf die Implementierung des I2C an. Bei halbwegs sinnvoller 
Umsetzung geht das.
Aber warum willst du da so oft unterbrechen?

: Bearbeitet durch Moderator
von Daniel H. (schrauberhugo)


Lesenswert?

Dass hört sich echt toll an, aber wie programmiert man sowas ? Wird das 
sehr kompliziert ?


Lothar M. schrieb:
> Aber warum willst du da so oft unterbrechen?

Weil die Pulse an den Motor an den Motor nicht unterbrochen werden 
dürfen, und der Motor halbwegs flüssig laufen soll, sonst gehen Steps 
verloren

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

Daniel H. schrieb:
> Dass hört sich echt toll an, aber wie programmiert man sowas ? Wird das
> sehr kompliziert ?

kommt drauf an... Hier ist ein Beispiel mit Lib: 
https://playground.arduino.cc/Deutsch/HalloWeltMitInterruptUndTimerlibrary/

In der Interrupt Service Routine (ISR) sollte aber nur wenig Code rein 
der schnell abgearbeitet wird, also keine Print Ausgaben oder Float 
Berechnungen. Auch digitalWrite ist nicht das schnellste, das sollte 
durch Portzugriffe ersetzt werden.

von Daniel H. (schrauberhugo)


Lesenswert?

Wenn ich die TaskScheduler-Library richtig verstanden habe, reiht die 
die einzelnen Tasks ja nur in eine Liste ein und arbeitet diese 
nacheinander ab, also werden die Tasks doch nicht gleichzeitig 
ausgeführt, oder ?

von Daniel H. (schrauberhugo)


Lesenswert?

Johannes S. schrieb:
> kommt drauf an... Hier ist ein Beispiel mit Lib:



Hey Danke !!
ich schaue es mir an.

Im Interrupt wird nur ein Pin aktiviert und deaktiviert. Ich hoffe mal 
das klappt

von leo (Gast)


Lesenswert?

Daniel H. schrieb:
> Wenn ich die TaskScheduler-Library richtig verstanden habe, reiht die
> die einzelnen Tasks ja nur in eine Liste ein und arbeitet diese
> nacheinander ab, also werden die Tasks doch nicht gleichzeitig
> ausgeführt, oder ?

Natuerlich hintereinander, du hast ja nur einen Prozessor. Die Tasks 
sollten halt kurz sein. delay() et al sind verboten. Du musst umdenken 
und das Programm in kleine Stuecke aufteilen.

leo

von Daniel H. (schrauberhugo)


Lesenswert?

leo schrieb:
> Programm in kleine Stuecke aufteilen.


aber wie teile ich LCD.print(variable) auf ?

von leo (Gast)


Lesenswert?

Daniel H. schrieb:
> leo schrieb:
>> Programm in kleine Stuecke aufteilen.
>
> aber wie teile ich LCD.print(variable) auf ?

Einzelne print() sind sicher schnell genug. Teile die Anzeige in 
kleinere Stuecke auf. Stichwort "State-Machine".

leo

von Johannes S. (Gast)


Lesenswert?

Prinzipiell kann man sowas mit einem TaskScheduler machen, aber der 
Luxus kostet auch wieder Laufzeit. Und je häufiger die Tasks aufgerufen 
werden, desto mehr verbrätst du mit diesem Overhead. Für die genannte 
Aufgabe würde ich das mit der Timer/Interrupt Lösung machen: das 
Hauptprogramm bedient LCD und Schnittstelle, in der Timer ISR werden die 
Pulse generiert. Wenn es in den kHz Bereich geht musst du nur 
kontrollieren ob das digitalWrite nicht zuviel Zeit kostet, das ist 
nicht sehr effizient. Wenn die Verarbeitung in der ISR zulange dauert 
dann kommt dein Hauptprogramm nicht mehr dran und die Ausgabezyklen 
werden nicht eingehalten. Da sollte ein Oszi oder LA zur Kontrolle 
vorhanden sein.

von Stacker (Gast)


Lesenswert?

Was spricht dagegen gleich GRBL zu verwenden? Du musst das Rad nicht neu 
erfinden, kannst deine eigenen Anpassungen vornehmen und der Community 
ggf. zurückgeben.

von Peter D. (peda)


Lesenswert?

Daniel H. schrieb:
> Der Arduino braucht aber zu
> lange, um die Koordinaten per i2C-Protokoll auf das LCD zu übertragen

LCD ist nicht zeitkritisch und darf ruhig unterbrochen werden, z.B. 
durch einen Timerinterrupt, der dann das Stepperzeugs macht.
Man darf nur keine Angst vor Interrupts haben, die sind die Stärke von 
MCs gegenüber komplexen Betriebssystemen auf GHZ-Multicore CPUs.

von Daniel H. (schrauberhugo)


Lesenswert?

Das ist super zu wissen ;D dann ist die Sache für mich klar:
Ich benutze jetzt den schnelleren STM32 Controller mit Interrupts, die 
abfragen, ob jetzt jetzt ein Step nötig ist. Vielleicht kann mir jemand 
noch eine Frage beantworten:

für den Arduino benutze ich:

#include "TimerOne.h"

Timer1.initialize(100);
Timer1.attachInterrupt(FUNKTION);

funktionieren meine Libraries für den Arduino auch auf dem STM32 ?
Ich frage vor allem, weil hier ja der Timer verwendet wird !?


An Alle - Vielen Dank, das hat mich sehr viel weiter gebracht ;D

von leo (Gast)


Lesenswert?

Daniel H. schrieb:
> funktionieren meine Libraries für den Arduino auch auf dem STM32 ?

Highlevel Libs eventuell, andere wie Timer sicher nicht. Lies halt mal 
die Doku.

leo

von leo (Gast)


Lesenswert?

Daniel H. schrieb:
> Ich benutze jetzt den schnelleren STM32 Controller mit Interrupts,

BTW:
- du brauchst keinen schnelleren Prozessor.
- die AVR 8-Bitter haben natuerlich auch Interrupts
- mit den Arduinos hast du eine viel breitere Library Basis

leo

von Daniel H. (schrauberhugo)


Lesenswert?

Das System ist fertig und die Interrupts können alle 50us laufen, ohne 
dass es das LCD stört. SUPER ! Mit der Geschwindigkeit hat der Arduino 
dank Interrupts überhaupt kein Problem mehr !

TOP Hilfe -- Vielen Dank euch !!!

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
Noch kein Account? Hier anmelden.