Forum: Mikrocontroller und Digitale Elektronik STM32h7, Schrittmotor mit hoher Interpolation ansteuern und wissen wo man ist?


von Gerald M. (gerald_m17)


Lesenswert?

Hallo zusammen,

ich suche gerade nach Ideen wie ihr das angehen würdet.
Ich möchte zwei Schrittmotoren antreiben, und habe hierfür als 
Schrittmotortreiber die TMC2660. Diese können bis zu 256-fach 
Mikroschritte. Das bedeutet bei einem "normalen" Schrittmotor mit 200 
Schritten pro Umdrehung, dass man 51,200kHz für eine Umdrehung pro 
Sekunde als Schrittfrequenz braucht. Bei 10 U/s brauche ich also eine 
Frequenz von etwa 500kHz.
Zum Problem:
Meine (im Moment noch Dummy-) Servorate mit der die Rampe für die 
Schrittmotoren berechnet wird habe ich willkürlich auf 100Hz festgelegt. 
Wenn ich jetzt die Timer auf "Toggle Pin" bei "Output Compare" stelle 
und keinen Interrupt benutze (also die HAL Funktion 
"HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_4)"), funktioniert die Rampe wie 
sie soll.

Aktiviere ich nun den Interrupt mit "HAL_TIM_OC_Start_IT(&htim1, 
TIM_CHANNEL_4)", um die PinToggle im Interrupt mitzuzählen, damit ich 
weiß wo der Schrittmotor gerade steht, beschleunigen die Schrittmotoren 
nur auf etwa 3U/s. Nach etwas debuggen ist mir aufgefallen, dass die HAL 
Interrupt Routine ("TIM1_CC_IRQHandler(void)" ruft 
"HAL_TIM_IRQHandler(&htim1)" auf), welche die ganzen Flags prüft und 
auch löscht, etwas länger ist. Wenn ich selbst in 
"TIM1_CC_IRQHandler(void)" die Flags lösche und dann die Funktion per 
return beende ohne den "HAL_TIM_IRQHandler(&htim1)" aufzurufen, 
beschleunigt der Motor wieder normal.

Allerdings soll der Mikrocontroller natürlich noch viel mehr andere 
Dinge machen als nur die Position des Schrittmotors zu zählen. Aber 
überschlagsmäßig ist auch direkt klar: 2x Interrupts mit 500kHz, bei 
(noch niedrigen) 200Mhz bedeutet dass ich nur etwa 200 Instruktionen 
zwischen den Interrupts Zeit habe. Schon alein für das Einspringen und 
sichern der Floatingpoint Einheit gehen 20 Cycles drauf, dann noch 
Schritmtotorposition aktualisieren und Flags löschen. Dann noch den 
neuen Timer-Compare-Wert berechnen (auch noch eine float-Division) und 
zack ist keine Rechenzeit mehr übrig.

Mir ist natürlich klar dass ich einfach weniger Mikroschritte wählen 
kann oder auch das Interpolationsfeature des TMC2660, bei dem zwischen 
16fach Mikroschritte noch einmal interpoliert wird, nutzen kann.
Am liebsten wäre mir aber eine Idee wie ich die Position des 
Schrittmotors kenne ohne immer einen Interrupt auszulösen.
Beispielsweise dachte ich daran die Schrittmotortimer ohne Interrupt 
laufen zu lassen, gleichzeitig aber einen zweiten Timer mit Interrupt 
laufen zu lassen der den gleichen Comparewert bekommmt, allerdings einen 
Prescaler von 15 (also nur 1/16 so schnell zählt) hat. Im Interrupt 
dieses Timers wird dann die Position des Schrittmotors gezählt (nur eben 
als hätte der Motor 16 Mikroschritte). Allerdings vermute ich dass durch 
nicht synchrones Zählen die berechnete Position von der echten mit der 
Zeit auseinander läuft.
Ähnliches gilt auch für "Position rechnen in der Servoloop". Da ich den 
Compare-Wert nur alle 10ms berechne, weiß ich natürlich wie lange ich 
mit welcher Schrittfrequenz fahre. Aber hier wird wahrscheinlich durch 
Jitter die berechnete Position von der echten mit der Zeit abweichen.

Hat sonst jemand eine Idee?

von N. M. (mani)


Lesenswert?

Also ich habe jetzt mehrmals deinen Text gelesen, aber mir ist immernoch 
nicht klar wo deine Position genau her kommt.
Encoder? Oder zählst du nur die Schritte?

Wieso braucht man zum Zählen einen Interrupt? Da gibt es beim H7 doch 
mit Sicherheit auch Hardware dafür wie ein Counter on Edge x oder ein 
QEI oder so was...

von Gerald M. (gerald_m17)


Lesenswert?

Hallo,
ja, ich zähle einfach die Schritte.
Deswegen habe ich ja gefragt ob jemand eine andere Lösung hat.

von Wolfgang (Gast)


Lesenswert?

Gerald M. schrieb:
> Am liebsten wäre mir aber eine Idee wie ich die Position des
> Schrittmotors kenne ohne immer einen Interrupt auszulösen.
Die Position des Motors kennst du höchstwahrscheinlich sowieso nicht 
wirklich mit dieser 256-Step Genauigkeit, da dein Schrittmotor das 
Ansteuersignal gar nicht so genau in eine mechanische Position umsetzt.
Die hohe Rechenbelastung hast du nur, wenn sich die Schrittfrequenz auf 
einer Rampe ändert. Wie lang ist deine Interruptverarbeitung und wie 
hoch ist daran der Anteil für den "Luxus" der Nutzung des HAL. Brauchst 
du dort wirklich diese Auflösung? Oder reicht es, die Rampen mit 
16-µSchritt zu fahren und für ruhiger Dauerstrecken, auf denen keine 
Rechnerei erforderlich ist auf 256-µSchrittbetrieb umzuschalten?

von Stefan F. (Gast)


Lesenswert?

Manchmal ist es sinnvoller, die Ansteuerung der Motoren, und die 
sonstige Programmlogik voneinander zu trennen. Es ist nicht verboten, 
mehrere Mikrocontroller einzusetzen.

Man sollte dabei auch immer berücksichtigen, wie aufwändig die 
Programmierung ist. Wenn du zu viel auf einem µC machst, wird die 
Softwareentwicklung auffällig teuer. Je geringer die produzierte 
Stückzahl ist, umso schlechter ist das dann.

Die Reduktion der Hardware, um jeden Cent heraus zu quetschen, lohnt 
sich oft nicht.

von Gerald M. (gerald_m17)


Lesenswert?

Hallo,

die Position im Mikroschritt Betrieb ist mir relativ egal. Mit reicht 
die Position des Vollschritts.
Der Schrittmotor bewegt einen Kolben, der natürlich nur begrenzt Hub hat 
und den ich ungern im den Hardstop fahren würde.
Die momentane Mikroschritt Position kann ich sogar vom Schrittmotor 
Treiber abfragen.

Ich selbst brauche in der Interrupt Routine nur eine Addition 
("Stepper.Position += Stepper.Direction"). Dazu noch das Makro 
"__HAL_TIM_CLEAR_IT" was im Endeffekt auch nur ein Registerzugriff 
bedeutet. Den Rest habe ich ja durch das return deaktiviert.

Mein "Problem" ist auch, dass es nicht nur reicht die Pulse zu zählen, 
sondern es muss auch die Laufrichtung beachtet werden.

von Gerald M. (gerald_m17)


Lesenswert?

Stefan ⛄ F. schrieb:
> Manchmal ist es sinnvoller, die Ansteuerung der Motoren, und die
> sonstige Programmlogik voneinander zu trennen. Es ist nicht verboten,
> mehrere Mikrocontroller einzusetzen.

Das stimmt natürlich. Zumal das hier nur ein Hobbyprojekt ist. Die 
Platine habe ich allerdings schon hier liegen (und per Hand mit ~200 
Bauteilen bestückt). Das Problem hatte ich bei meinen Tests so 
allerdings nicht im Blick.

von m.n. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Es ist nicht verboten,
> mehrere Mikrocontroller einzusetzen.

Hier aber garnicht erforderlich.

Wolfgang hatte doch schon die wesentlichen Punkte genannt. Für hohe 
Geschwindigkeiten braucht man keine Mikroschritte. 256 Mikroschritte 
sind sowieso fraglich, sofern man nicht einen guten Schrittmotor und 
leichtgängige Mechanik verwendet. Das Ganze dann noch mit HAL zu 
programmieren, ist äußerst fraglich.

Um die genaue Position des Motors anhand der erzeugten Schritte zu 
ermitteln, muß man nur mitzählen. Lediglich beim Umschalten der 
Mikroschritte muß man den richtigen Schritt abwarten, um den Modus zu 
ändern.
Zwei Stepper mit 10 U/s schafft schon ein ATmega328.

Gerald M. schrieb:
> die Position im Mikroschritt Betrieb ist mir relativ egal. Mit reicht
> die Position des Vollschritts.

Dann nimm doch durchgehend 1/4 oder 1/8 Schritt. Damit bleiben die 
Taktfrequenz niedrig, die Resonanzen gering und die Programmierung recht 
einfach.

> Mein "Problem" ist auch, dass es nicht nur reicht die Pulse zu zählen,
> sondern es muss auch die Laufrichtung beachtet werden.

Dafür kann man dann statt einer Addition eine Subtraktion nehmen ;-)

von Gerald M. (gerald_m17)


Lesenswert?

m.n. schrieb:
> Dann nimm doch durchgehend 1/4 oder 1/8 Schritt. Damit bleiben die
> Taktfrequenz niedrig, die Resonanzen gering

Das entspricht leider gar nicht meiner Erfahrung. Bei solch kleinen 
Mikroschritt ist der Motor deutlich laufruhiger und man bekommt viel 
weniger Resonanzen.
Ansonsten hätte die ganzen Mirkoschritte ja auch keinen Sinn. Denn die 
Position wird vermutlich ab 16-fach Mikroschritten nicht wirklich 
genauer.

Mit höherer Geschwindigkeit die Mikroschritten zu reduzieren wäre auch 
möglich. Dann muss natürlich dann auch das Timing passen.

von Johannes S. (Gast)


Lesenswert?

Wenn die Position gar nicht so genau gebraucht wird dann sollte die 
Interpolation im Treiber reichen. Die Laufruhe hat man damit bei 
moderater Taktfrequenz.

von georg (Gast)


Lesenswert?

Gerald M. schrieb:
> dass die HAL
> Interrupt Routine ("TIM1_CC_IRQHandler(void)" ruft

Bei so einer Problematik schreibt man sich in ein paar Minuten in 
Assembler eine Interrupt-Service-Routine, die nichts tut als einen 
Zähler aufwärts oder abwärts zu zählen, die ist sicher schnell genug.

Georg

von m.n. (Gast)


Lesenswert?

Gerald M. schrieb:
> m.n. schrieb:
>> Dann nimm doch durchgehend 1/4 oder 1/8 Schritt. Damit bleiben die
>> Taktfrequenz niedrig, die Resonanzen gering
>
> Das entspricht leider gar nicht meiner Erfahrung. Bei solch kleinen
> Mikroschritt ist der Motor deutlich laufruhiger und man bekommt viel
> weniger Resonanzen.

Ja und?
Soll alles geräuschlos ablaufen oder gehen etwa Schritte verloren?
Ich denke, Du suchst eine praktikable Lösung?

von Gerald M. (gerald_m17)


Lesenswert?

georg schrieb:
> Bei so einer Problematik schreibt man sich in ein paar Minuten in
> Assembler eine Interrupt-Service-Routine, die nichts tut als einen
> Zähler aufwärts oder abwärts zu zählen, die ist sicher schnell genug.
>
> Georg

Hallo Georg, ich bezweifle dass der Compiler aus:
1
void TIM2_IRQHandler(void)
2
{
3
  /* USER CODE BEGIN TIM2_IRQn 0 */
4
  MotorCold.position += MotorCold.direction;
5
  __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_CC4);
6
  return;
7
  /* USER CODE END TIM2_IRQn 0 */
8
  HAL_TIM_IRQHandler(&htim2);
9
  /* USER CODE BEGIN TIM2_IRQn 1 */
10
11
  /* USER CODE END TIM2_IRQn 1 */
12
}
mit
1
#define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__)      ((__HANDLE__)->Instance->SR = ~(__INTERRUPT__))
etwas anderes macht als du in Assembler.

m.n. schrieb:
> Ja und?
> Soll alles geräuschlos ablaufen oder gehen etwa Schritte verloren?
> Ich denke, Du suchst eine praktikable Lösung?

Geräuschlos wäre schön, ja. Außerdem zitiere ich hierzu aus meinem 
ersten Post:

Gerald M. schrieb:
> Mir ist natürlich klar dass ich einfach weniger Mikroschritte wählen
> kann oder auch das Interpolationsfeature des TMC2660, bei dem zwischen
> 16fach Mikroschritte noch einmal interpoliert wird, nutzen kann.
> Am liebsten wäre mir aber eine Idee wie ich die Position des
> Schrittmotors kenne ohne immer einen Interrupt auszulösen.

von Johannes S. (Gast)


Lesenswert?

ich habe zum SM Takten einen Timer als OneShot konfiguriert und in der 
ISR die Zeit zum nächsten Schritt berechnet und den Timer wieder 
getriggert. Die ISR hat dafür mit Interpolation in float auf einem F407 
@ 168 MHz ca. 0,7 µs gebraucht. Die Interruptlast ist damit variabel, 
bei stehendem Motor passiert gar nix.
Die HAL bietet in dem OC und OneShot Mode wenig Unterstützung, ich habe 
nur die Initialisierung und ein paar HAL Makros genutzt. Auch die 
unübersichtliche HAL ISR, die dann mit weak Callbacks arbeitet, habe ich 
durch eine eigene ISR ersetzt. Das geht bei den Cortex-M ja sogar gut 
zur Laufzeit weil die ISR Vektoren ins RAM kopiert werden können.

von georg (Gast)


Lesenswert?

Gerald M. schrieb:
> Am liebsten wäre mir aber eine Idee wie ich die Position des
>> Schrittmotors kenne ohne immer einen Interrupt auszulösen.

Du kannst natürlich einen externen Vor/Rückwärtszähler an Step/Dir 
anschliessen und den nur bei Bedarf auslesen. Aber nur um Interrupts zu 
vermeiden? Die sind doch für den Controller das täglich Brot.

Georg

von c-hater (Gast)


Lesenswert?

m.n. schrieb:

> Zwei Stepper mit 10 U/s schafft schon ein ATmega328.

Der schafft noch WESENTLICH mehr...

Tja: nix BASIC, nix PASCAL, nix C. Einzig pure Asm treibt ihn zu 
Höchstleistungen. Denn nur das erlaubt, die ganzen Bremsen der 
Hochsprachenabstraktionen (und ihrer RT-Umgebung) leicht zu entfernen.

Vor allem: nur in Asm kann man auch zuverlässig BEWEISEN, dass er 
bestimmte Anforderungen erfüllt. Auch über die eigentliche 
Schrittsteuerung hinausgehend für das Gesamtsystem...

Ja, das ist deutlich mehr Aufwand bei der Entwicklung. Ob sowas 
ökonomisch lohnt, hängt tatsächlich von der Stückzahl ab, diesbezüglich 
hat Stefan F. absolut Recht.

Aber (gerade für ein privates Projekt): Da guckt man doch nicht 
unbedingt auf die Kosten der Arbeitszeit. Da will man was schönes bis 
perfektes mit minimierten Hardwarekosten. Aber OK: das ist natürlich nur 
meine Sicht der Dinge. Also mehr so eine "der Weg ist das Ziel"-Sache. 
Die Alternative ist allerdings (wenn die Erreichung des Ziels das 
einzige Ziel ist):

Kaufe was kommerziell Entwickeltes. Billiger und zuverlässiger kannst du 
selber nichts entwickeln...

Also auf keinen Fall Arduino-Gebastel. Das ist (relativ) teuer UND 
garantiert massiv suboptimal UND garantiert letztlich garnix (nichtmal 
die grundsätzliche Funktion).

So sieht's aus...

von Harald W. (wilhelms)


Lesenswert?

Gerald M. schrieb:

> Der Schrittmotor bewegt einen Kolben, der natürlich nur begrenzt Hub hat
> und den ich ungern im den Hardstop fahren würde.

Eine sicherheitsrelevante Positionsbestimmung allein durch Schritte
zählen halte ich für einen Entwicklungsfehler. Dort sollte immer noch
ein Endschalter sitzen, der den Motor hardwaremäßig ausschaltet.

von Wolfgang (Gast)


Lesenswert?

Harald W. schrieb:
> Eine sicherheitsrelevante Positionsbestimmung allein durch Schritte
> zählen halte ich für einen Entwicklungsfehler.
Woher weisst du, dass die Positionsbestimmung sicherheitsrelevante ist.
Um das zu beurteilen, müsste man wissen, was das Anfahren des Hardstops 
außer "ungerne" für schädliche, insbesondere sicherheitsrelevante 
Nebenwirkungen hätte.

von (Gast)


Lesenswert?

Einfach wäre es, pro Kanal einen weiteren Zähler zu opfern. Teilweise 
kann man die Zähler im STM kaskadieren -> Datenblatt und Refman 
studieren. Alternativ kann man natürlich auch extern den Step-Ausgang 
auf den Eingang eines Zählers legen. Dann muss man nur noch auf 
Überläufe und die Schrittrichtung achtgeben, hat die Position aber im 
Prinzip immer im Zählerregister vorrätig, ohne Rechenzeit zu verbraten.

von m.n. (Gast)


Lesenswert?

c-hater schrieb:
> m.n. schrieb:
>
>> Zwei Stepper mit 10 U/s schafft schon ein ATmega328.
>
> Der schafft noch WESENTLICH mehr...

Du kennst doch garnicht die Rahmenbedingungen.
Zudem sind Deine vollmundigen Aussagen nichts wert. Viel Gelaber, aber 
wenn Du auf konkretes Vorgehen angesprochen wirst, kneifst Du. Lass 
stecken!

@TO
Soweit ich Dich verstanden habe, schaffst Du von den gewünschten 10 U/s 
bislang mit Rampe nur 3 U/s. Da würde ich mich doch zunächst einmal 
darum kümmern, wie Du die geforderte Geschwindigkeit hinbekommst, bevor 
es besonders leise oder wie auch immer funktionieren soll.
Was Du auf jeden Fall meiden solltest, sind die intransparenten 
HAL-Aufrufe.

Auch lese ich, daß Du nur 200 MHz CPU-Takt verwendest. Ich lasse die H7 
immer mit 480 MHz laufen, die werden dann etwas handwarm, was ich aber 
als sehr angenehm empfinde: es wird gearbeitet ;-)

So, wie ich Dich verstanden habe, willst Du einen Kolben verfahren, 
indem eine Fahrt von der Ist- auf eine Sollposition durchgeführt wird. 
Startrampe, lin. Bewegung und Stopprampe: das läuft alles in der ISR ab 
und daher kann/soll/muß die Position auch in der ISR erfaßt werden.

von Gerald M. (gerald_m17)


Lesenswert?

Wolfgang schrieb:
> Harald W. schrieb:
>> Eine sicherheitsrelevante Positionsbestimmung allein durch Schritte
>> zählen halte ich für einen Entwicklungsfehler.
> Woher weisst du, dass die Positionsbestimmung sicherheitsrelevante ist.
> Um das zu beurteilen, müsste man wissen, was das Anfahren des Hardstops
> außer "ungerne" für schädliche, insbesondere sicherheitsrelevante
> Nebenwirkungen hätte.

Danke. Tatsächlich hat der Motortreiber sogar eine "Hardstop-Erkennung". 
Wenn sich die Last ruckartig über einen bestimmten Punkt hinaus ändert 
gibt er ein "Stall"-Signal per Pin aus (so werde ich auch die 
Referenzfahrt durchführen). Ansonten ist das so konstruiert dass der 
Kolben im Hardstop nichts kaputt macht.

Mich würde die Position nicht nur wegen den Endstops interessieren, 
sondern auch weil ich nur eine bestimmte Menge Wasser pumpen möchte. 
Also entsprechend früh anfangen muss zu bremsen. Hierbei entspricht ein 
Fullstep ürigens etwa 15 Mikroliter. Mir reicht es wen ich am Ende auf 
einen Milliliter genau bin.

von Gerald M. (gerald_m17)


Lesenswert?

m.n. schrieb:
> Auch lese ich, daß Du nur 200 MHz CPU-Takt verwendest. Ich lasse die H7
> immer mit 480 MHz laufen, die werden dann etwas handwarm, was ich aber
> als sehr angenehm empfinde: es wird gearbeitet ;-)
>
> So, wie ich Dich verstanden habe, willst Du einen Kolben verfahren,
> indem eine Fahrt von der Ist- auf eine Sollposition durchgeführt wird.
> Startrampe, lin. Bewegung und Stopprampe: das läuft alles in der ISR ab
> und daher kann/soll/muß die Position auch in der ISR erfaßt werden.

Ja, den Takt erhöhen geht auf jeden fall noch.

Zur Kolbenfahrt:
Ich plane eine Espressomaschine, welche aber anstatt einer 
Vibrationspumpe eine Kolbenpumpe hat, wie die alten 
Handhebel-Espressomaschinen. Nur bewege ich den Kolben nicht mit Gefühl 
von Hand, sondern über einen Schrittmotor mit Spindel.
Idealerweise fahre ich ein "Flowprofil" ab ohne zu regeln (bei anderen 
Espressomaschinen wird hierfür der Druck geregelt). Allerdings möchte 
ich auch ein "klassisches" Druckprofil fahren, bei dem der Durchfluss 
nach dem Druck geregelt wird.

Falls ich keine Lösung mit selbstzählenden Timern o.ä. finde, werde ich 
eben auf eine berechnete Menge an Espresso zurückgreifen (Fluss welchen 
ich vorgebe integrieren) und danach einfach wieder die Referenz 
anfahren.

m.n. schrieb:
> Soweit ich Dich verstanden habe, schaffst Du von den gewünschten 10 U/s
> bislang mit Rampe nur 3 U/s. Da würde ich mich doch zunächst einmal
> darum kümmern, wie Du die geforderte Geschwindigkeit hinbekommst, bevor
> es besonders leise oder wie auch immer funktionieren soll.

Mit "Handgeschriebener" ISR funktionieren auch die 10 U/s. Aber trotzdem 
habe ich alle paar hundert Cycles einen Sprung in die ISR, was eben nur 
durch den Sprung inkl. speichern der FloatingPoint Unit, Position zählen 
und löschen der Flag an die 40-50 Cycles brauch. Das stört mich einfach 
insgesamt, da noch mehrere andere Parameter geregelt werden sollen. Wenn 
man die HAL-ISR anschaut, sieht man auch, dass dort gar nicht so viel 
mehr gemacht wird. Ich schätze also dass ich mich bei 10U/s schon 
ziemlich nah an der Reserve des STM32H7 befinde (zumindest bei aktueller 
Clock).

Edit: Zur Regelung an sich. Ich habe eine Servorate von 100Hz ausgesucht 
um alles zu steuern. Allerdings weiß ich nicht ob das für die 
Motorregelung reicht. Alle anderen Regelparameter sind eher gemütlich 
(fast ausschließlich Temperaturen).

: Bearbeitet durch User
Beitrag #6248538 wurde von einem Moderator gelöscht.
von Pieter (Gast)


Lesenswert?

moin Gerald,

Frage: Verstehe ich das richtig: Du treibst einen Kolben über eine 
Spindel mit einem Schrittmotor an?
Welchen Hub bringt eine Motorumdrehung -> welche Fördermenge ergibt das?

von Gerald M. (gerald_m17)


Lesenswert?

Hallo, du verstehst richtig.
Der Schrittmotor ist zum Kolben 1:2.5 untersetzt und der Kolben hat 
einen Durchmesser von 44mm. Die Spindel hat eine Steigung von 
4mm/Umdrehung. Also 2.5ml pro Motorumdrehung.

von Pieter (Gast)


Lesenswert?

moin,

also ist die Fördermenge bei 10U/s => 25ml/s.
10U => 2000 VollSteps
Somit ist 1 VollStep => 12,5µl
Für die 2000 Steps/s ist aller 500µs ein TimerINT notwendig.
Die Drehrichtung darf nur bei Motorstillstand geändert werden, bleibt im 
INT daher unberücksichtigt.
Die Drehzahl ( eigendlich die Schrittzahl ) pro Sec. liegt im Bereich 
0..2000.

Das INT macht nur:
------------------
if ( StepPin > 0 )
  {
    StepSum += Steps;
   if ( StepSum > 2000 ){ StepSum -= 2000; IstPOS += 1; StepPin = 0 }
  }
  else StepPin = 1;
----------------

Da der TimerINT das StepPin ein/ausschaltet muss er mit der halben Zeit
laufen, also TimerINT auf 4000/s. Der INT selber braucht <1µs auf 250µs, 
das sollte keine Rolle spielen.
Im Main setzt Du dann die Drehzahl und los gehts. Die Drehzahl kannst Du 
mit einer (sin^2-) Rampe hochfahren und die Position mit SollPos == 
IstPOS überwachen.
===========
Kolbendurchmesser 44mm -> 138,23mm^2
Hub/Step  4mm/ 200Step -> 0,02mm
ergibt bei mir 2,7646ml

Um exakt zu arbeiten, bräuchtest Du einen Nullschalter der die Position 
besser 0,02mm erkennt.

Habe ich micht verständlich ausgedrückt?

von Wolfgang (Gast)


Lesenswert?

Gerald M. schrieb:
> Mich würde die Position nicht nur wegen den Endstops interessieren,
> sondern auch weil ich nur eine bestimmte Menge Wasser pumpen möchte.
> Also entsprechend früh anfangen muss zu bremsen.
Das rechtzeitige Bremsen muss doch sowieso im Algorithmus für die 
Berechnung der Schrittabstände drin stehen. (siehe z.B. AN_8017: Atmel 
AppNote AVR446 - Linear speed control of stepper motor)

von Johannes S. (Gast)


Lesenswert?

Pieter schrieb:
> Habe ich micht verständlich ausgedrückt?

Und wo sind die Mikroschritte geblieben?

von m.n. (Gast)


Lesenswert?

c-hater schrieb im Beitrag #6248538:
> Insert coin and demands->get a working solution.
>
> Darunter gibt's von mir nur Hilfe zur Selbsthilfe und Warnungen vor
> offensichtlichen Fehlentwicklungen. Keinerlei Wichsvorlagen für lau.
> Wer lernfähig und lernwillig ist, wird meine Beiträge zu schätzen
> wissen, der Rest ist mir eigentlich ziemlich egal.

Ich verstehe. Aber gut, daß Du mal über Deine Krankheit geredet hast.

Pieter schrieb:
> Für die 2000 Steps/s ist aller 500µs ein TimerINT notwendig.
> ...
> Da der TimerINT das StepPin ein/ausschaltet muss er mit der halben Zeit
> laufen, also TimerINT auf 4000/s. Der INT selber braucht <1µs auf 250µs,
> das sollte keine Rolle spielen.

Diese 2000 Schritte/s macht aber der Motor nicht als 
Start-Stopp-Frequenz. Daher ist eine Rampe unumgänglich. Vollschritt ist 
ebenfalls nicht empfehlenswert; die machen nun wirklich Krach!
Auch muß die Timerfrequenz nicht verdoppelt werden, bloß um den 
Ausgangsimpuls wieder zu löschen. Bei geschickter Planung setzt der 
Timer den Ausgang nach ein paar µs per Hardware (Compare-Output) selber 
zurück.

Pieter schrieb:
> Um exakt zu arbeiten, bräuchtest Du einen Nullschalter der die Position
> besser 0,02mm erkennt.

Nicht unbedingt. Die relative Bewegung könnte schon ausreichen. Es 
dürfen lediglich keine Schritte verloren gehen (hohes Risiko bei 
Vollschritt) und dann reicht auch ein einfacher Schalter (ggf. auch ein 
Anschlag).

von Gerald M. (gerald_m17)


Angehängte Dateien:

Lesenswert?

Hallo Pieter,

die Ansteuerung habe ich ja bereits. Ich kann durch den Timer auch ein 
Interrupt auslösen lassen, und in diesen zählen. Allerdings ist dieser 
Interrupt sehr Resourcenhungrig. Deshalb hätte ich gerne eine Variante 
bei der ich den Interrupt nicht brauche, oder zumindest seltener.

Pieter schrieb:
> ===========
> Kolbendurchmesser 44mm -> 138,23mm^2
> Hub/Step  4mm/ 200Step -> 0,02mm
> ergibt bei mir 2,7646ml

Hier hast du vermutlich den Umfang des Kolbens berechnet. Die 
Untersetzung von 1:2.5 hast du vermutlich überlesen. Aber interessant 
dass trotzdem fast der gleiche wert raus kommt.

Die Schrittmotortreiber kann man (und habe ich) übrigens einfach auf 
einen Schritt bei jedem Flankenwechsel (also auch Low zu High) 
einstellen. Dann fällt die doppelte Geschwindigkeit des Timers wieder 
heraus.

@Wolfgang, das rechtzeitige Bremsen ist an sich auch nicht schwer. Zumal 
ich ja die Beschleunigung kenne. Allerdings muss ich um rechtzeitig 
bremsen zu können (also z.b. damit 30ml Wasser in der Tasse sind) eben 
wissen wieviel bisher schon herausgelaufen ist. Und dafür brauche ich 
wieder die Schritte.

Ich denke ich werde den Schrittmotor ansteuernden Timer ohne Interrupt 
laufen lassen, und parallel dazu einen weiteren Timer mit 1/16 der 
Frequenz. Dieser wird dann immer auf den gleichen Capture Wert wie der 
Schrittmotor Treiber gelegt und zählt somit die 16tel Mikroschritte im 
Interrupt. Bei einem Wechsel der Schrittfrequenz erhalte ich zwar 
Ungenauigkeiten (da der zweite Counter erst zählt wenn der Schrittmotor 
16 Mal gesteppt hat, ich also diese Schritte nicht Messe), ich vermute 
aber dass diese deutlich unterhalb meiner Toleranz liegen. Eventuell 
kann ich ja auch noch statistisch immer einen halben 16tel Schritt 
hinzuzählen
und statistisch bin ich dann an der richtigen Position.

Damit ihr euch vorstellen könnt wie das aussieht, habe ich ein Foto 
einer Decent Espresso Maschine angehängt.

von Johannes S. (Gast)


Lesenswert?

die low-Tech Automaten messen den Wasserzufluss mit einem einfachen 
Flügelrad, wäre das nicht auch ausreichend genau? Was im Puck hängen 
bleibt kann man doch eh nur abschätzen, was rauskommt auf den ml genau 
zu bestimmen ist doch kaum möglich?
Und wie geschrieben, der 16x oder 32x Mode plus Interpolation sorgt 
schon für einen seidenweichen lauf. Aber auch bei 3D-Druckern bringt das 
nur akustische Verbesserung und keinen Gewinn an Genauigkeit. Und bei 50 
kHz Interruptfrequenz kann man immer noch bequem mit float 
interpolieren. Wobei das v doch auch immer gleich sein wird und die 
Rampen nur einmal in eine Tabelle gepackt werden müssten.

von MaWin (Gast)


Lesenswert?

Gerald M. schrieb:
> Hat sonst jemand eine Idee

Du braucht die Schritte nicht zu zählen, denn dein Programm gibt ja vor, 
wie viele Schritte gemacht werden solle. Dein Programm weuss also schon 
wie viele Schritte.

Und ja: 256 Mikroschritte sind technisch einfach Unsinn. Schrittmotore 
drehen nicht genauer, als das Verhältnis von Drehmoment zu Haltemoment, 
meist 1:10.

Die Welt ist leider voll von Leuten, die glauben: viel bringt viel.

von Gerald M. (gerald_m17)


Lesenswert?

Ich möchte noch einmal betonen dass ich die "Genauigkeit" der 
Mikroschritte nicht brauche. Mir geht es wirklich nur um den ruhigen 
Lauf. Ich weiß auch dass der Treiber sehr gut interpolieren kann, aber 
prinzipbedingt sind native 256-Mikroschritte eben gleichmäßiger. Mir 
geht es hauptsächlich um die technische Möglichkeit. Denn der 
Mikrocontroller kann problemlos die Pulse für die 256 Mikroschritte 
erzeugen. Nur das mitzählen belastet ihn Recht stark. Deshalb suche ich 
nach einer Lösung die "von alleine" mitzählt.

Und @MaWin, das ist auch das Problem. Ich gebe per Timer vor wie schnell 
ich fahren möchte, weiß also nur durch Mitzählen in einem Interrupt wo 
ich bin. Dieser Brauch aber sehr viel Rechenzeit da er häufig aufgerufen 
und angesprungen werden muss. Deshalb würde ich ihn gerne vermeiden und 
nur den automatischen Pintoggle benutzen, der komplett ohne Rechenzeit 
auskommt.

von KM (Gast)


Lesenswert?

Gerald M. schrieb:

>... Nur das mitzählen belastet ihn Recht stark. Deshalb suche ich
> nach einer Lösung die "von alleine" mitzählt.

Ja dann benutz doch deinen Pulse Toggle Ausgang (intern oder extern) als
Clk Source für einen der Timer/Counter. Der H7 hat doch genug, oder?

von ... (Gast)


Lesenswert?

Counter?

von m.n. (Gast)


Lesenswert?

Gerald M. schrieb:
> Ich gebe per Timer vor wie schnell
> ich fahren möchte, weiß also nur durch Mitzählen in einem Interrupt wo
> ich bin. Dieser Brauch aber sehr viel Rechenzeit da er häufig aufgerufen
> und angesprungen werden muss. Deshalb würde ich ihn gerne vermeiden und
> nur den automatischen Pintoggle benutzen, der komplett ohne Rechenzeit
> auskommt.

Die Schritte mit einem freilaufenden Timer zu erzeugen, ist doch nur bei 
längeren, konstanten Geschwindigkeiten sinnvoll. Bei Deiner Anwendung 
mit kurzen Hüben, kommt nach erfolgter Startrampe doch schon gleich die 
Stopprampe.
Du unterschätzt m.M.n. auch die Geschwindigkeit des H7. Das Teil ist 
affenschnell und verkraftet durchaus hochfrequente ISRs. Es bliebe auch 
noch der Weg, die Rampen per Integer-Berechnungen zu erzeugen. Das spart 
ein paar Zyklen für PUSH/POP der float-Register.
Das Schrittmuster (Timerwerte) könnte man auch ins RAM schreiben und per 
DMA ausgeben. Aber ich denke, das ist einfach Quatsch.

von Gerald M. (gerald_m17)


Angehängte Dateien:

Lesenswert?

KM schrieb:
> Gerald M. schrieb:
>
>>... Nur das mitzählen belastet ihn Recht stark. Deshalb suche ich
>> nach einer Lösung die "von alleine" mitzählt.
>
> Ja dann benutz doch deinen Pulse Toggle Ausgang (intern oder extern) als
> Clk Source für einen der Timer/Counter. Der H7 hat doch genug, oder?

Gibt es dazu auch Hilfe? Spontan finde ich nicht wie ich konkret den 
Ausgang des Tim1 Ch4 (dessen Pin PE14 an dem Step Eingang des ersten 
Schrittmotors verbunden ist) und Tim2 Ch4 (mit Pin PB11) an Motor 2, 
intern mit einem Counter verbinden kann. Die Richtung kann ich ja per 
Software addieren wenn ich die Position wissen möchte.
Das wäre mein Wunschszenario.

Ich nutze übrigen Timer 1 und 2 für die beiden Stepper, Timer 3 und 
Timer 4 im Encodermodus, und Timer13 für den Servozyklus. Alle anderen 
Timer sind noch frei. Bild der Ursprungskonfiguration in CubeMX habe ich 
angehängt.

m.n. schrieb:
> Die Schritte mit einem freilaufenden Timer zu erzeugen, ist doch nur bei
> längeren, konstanten Geschwindigkeiten sinnvoll. Bei Deiner Anwendung
> mit kurzen Hüben, kommt nach erfolgter Startrampe doch schon gleich die
> Stopprampe.
> Du unterschätzt m.M.n. auch die Geschwindigkeit des H7. Das Teil ist
> affenschnell und verkraftet durchaus hochfrequente ISRs. Es bliebe auch
> noch der Weg, die Rampen per Integer-Berechnungen zu erzeugen. Das spart
> ein paar Zyklen für PUSH/POP der float-Register.
> Das Schrittmuster (Timerwerte) könnte man auch ins RAM schreiben und per
> DMA ausgeben. Aber ich denke, das ist einfach Quatsch.

Ich empfand es als elegant, die Geschwindigkeit in jedem Servozyklus 
einmal zu berechnen und dann autark weiterlaufen zu lassen. Dafür muss 
sogar nur ein Register beschrieben werden. Für die Regelung später kann 
dann auch einfach der Wert vergrößert oder verkleinert werden.
Ich weiß dass der H7 schnell ist. Doch fals es wie gerade erwähnt eine 
Möglichkeit gibt den h7 nicht zu belasten, würde ich diese natürlich 
bevorzugen. So kann ich später bei den Regelungen etwas "mehr auf den 
Putz" hauen und einen predictive Control Algorithmus einprogrammieren.

: Bearbeitet durch User
von Hugo H. (hugohurtig1)


Lesenswert?

c-hater schrieb:
> Vor allem: nur in Asm kann man auch zuverlässig BEWEISEN, dass er
> bestimmte Anforderungen erfüllt.

Welche?

von Gerald M. (gerald_m17)


Angehängte Dateien:

Lesenswert?

Also,

ich bin den Interrupt los. (Ganz ohne Assambler :P )

Und zwar haben die Timer die Möglichkeit, ein Triggersignal (TRGO) 
auszusenden. Wann dies passiert kann sogar im CubeMX konfiguriert 
werden.

Hierfür muss im Reference Manual die "internal trigger connection" der 
verschiedenen Timer untereinander angeschaut werden und freie Timer 
ausgesucht werden, welche diese Trigger aufnehmen können. Anhand der 
angehängten Tabelle habe ich mich für Timer 5 als Slave für Timer 1 
entschieden, und Timer 8 als Slave für Timer 2.
Als Trigger habe ich das "Update Event" ausgesucht (man kann auch auf 
das Capture Compare Event eines Channels triggern, das ergab bei mir 
allerdings nur die halbe Zählfrequenz, da ich ja den Pin Toggle, und 
immer nur entweder auf steigende oder fallende Flanke getriggert werden 
kann).
Den Slave auf "Slave Mode" auf "External Clock Mode 1" stellen, und als 
Triggerquelle den ITR aus der tabelle eintragen.

Funktioniert :)

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.