Forum: Mikrocontroller und Digitale Elektronik STM32 counter up/down mit Step/Dir Signalen


von Gerhard H. (sams_n)


Lesenswert?

Hallo Leute,

ich suche , wie im Betreff geschrieben , eine Möglichkeit beim STM32F411
die HW-counter für Step/Dir Signale zu realisieren (5 Stück !).
Es geht um das Lesen der Signale für die Steuerung einer
5-Achs CNC Fräsmaschine. (5 Step/Dir Signale mit max. 250 kHz)
Derzeit mache ich es mittels ext. Interupt möchte aber die Möglichkeit 
nutzen die Timer 1,2,3,4,5 zu verwenden , ähnlich den HW-Countern für
Quadrature Encoder.
Diese hab ich getestet , laufen perfekt mit den A/B Signalen von den 
Encodern.
Gibt es eine Möglichkeit die Timer Register so zu konfigurieren dass sie 
auch mit STEP/DIR Signalen so problemlos umgehen können ?
Ich finde keine Möglichkeit das Richtungssignal einzubinden um den 
Counter
ab- , bzw. aufwärts zählen zu lassen.
Bin für jede Hilfe dankbar.
Ich benutze MikroBasic , erhalte leider im MikroE Forum keinerlei Hilfe 
zu dem Thema.

Schönes Wochenende,
Gerhard

von Falk B. (falk)


Lesenswert?

Für den Fall, daß die Timer nicht passend konfiguriert werden können, 
hier eine Hardwarelösung.

Beitrag "Re: pulse direction signal zu encoder a b?"

von Gerhard H. (sams_n)


Lesenswert?

Hallo Falk,

danke für den Hinweis , den Beitrag kenne ich bereits.
Würde für den Fall , wenns wirklich keine Möglichkeit mittels HW-counter
beim STM32 gibt , ein paar AVR's verwenden.

Gruss Gerhard

von Mi N. (msx)


Lesenswert?

Gerhard H. schrieb:
> Gibt es eine Möglichkeit die Timer Register so zu konfigurieren dass sie
> auch mit STEP/DIR Signalen so problemlos umgehen können ?

Nein.

Gerhard H. schrieb:
> Würde für den Fall , wenns wirklich keine Möglichkeit mittels HW-counter
> beim STM32 gibt , ein paar AVR's verwenden.

Bei 250 kHz mußt Du die in Assembler programmieren und per IIC auslesen.
Eine kompakte Lösung wäre mit einem Pico-Board mit RP2040 möglich.
Reicht Dir denn der relative langsame Zugriff per IIC-Bus?

Oder anstatt diskreter Logik ein 8-pol. AVR zur Umsetzung Step/Dir -> 
PhaseA/PhaseB verwenden und dann auf die STM-Timer geben.

: Bearbeitet durch User
von Gerhard H. (sams_n)


Lesenswert?

Mi N. schrieb:
> Oder anstatt diskreter Logik ein 8-pol. AVR zur Umsetzung Step/Dir ->
> PhaseA/PhaseB verwenden und dann auf die STM-Timer geben.

Genau so hab ich es vor wenn es keine interne Möglichkeit im STM32 gibt.
Die AVR's in Assembler für die Wandlung Step/Dir --> A/B zu 
programmieren,
da sehe ich kein Problem.
Jedoch kann ich es kaum glauben dass die Timer des STM32 bei der 
Vielfalt an Möglichkeiten nicht zu konfigurieren sind um STEP/DIR zu 
lesen.
Warscheinlich sehe ich den Wald vor lauter Bäumen nicht .... oder so 
ähnlich.
Außerdem beschäftige ich mich erst seit 2 Wochen mit dem 32bitter , also
bin da recht neu dabei. (hobbymäßig..)

BG Gerhard

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Gerhard H. schrieb:
> Genau so hab ich es vor wenn es keine interne Möglichkeit im STM32 gibt.
> Die AVR's in Assembler für die Wandlung Step/Dir --> A/B zu
> programmieren,
> da sehe ich kein Problem.

Da wäre ich bei 250kHz VORSICHTIG. Ausser für unserem heldenhaften 
C-hater ist das auch in ASM schon sportlich. Aber vor allem, warum? Sind 
ZWEI kleine CMOS-ICs / Kanal zuviel? Es reichen sogar weniger, siehe 
Anhang! 9 Stück für 5 Kanäle.

> Jedoch kann ich es kaum glauben dass die Timer des STM32 bei der
> Vielfalt an Möglichkeiten nicht zu konfigurieren sind um STEP/DIR zu
> lesen.

Beim ATXmega kann man die IOs so konfigurieren, daß man damit steigende 
und fallende Flanken erkennt und Hardware-Events auslöst, welche direkt 
den Timer ansteuern. Vermutlich können das auch die STM32.

> Warscheinlich sehe ich den Wald vor lauter Bäumen nicht .... oder so
> ähnlich.

Zeig mal einen Link auf ein Datenblatt.

von Mi N. (msx)


Lesenswert?

Gerhard H. schrieb:
> Jedoch kann ich es kaum glauben dass die Timer des STM32 bei der
> Vielfalt an Möglichkeiten nicht zu konfigurieren sind um STEP/DIR zu
> lesen.

Wenn man genauer hinsieht, sind die Möglichkeiten doch begrenzt, wie 
auch andere Sachen bei den STM32. Es fällt meist erst dann auf, wenn man 
gezielt eine Lösung braucht.
Wenn Du den F411 erst kurz kennst, plane die Verwendung der IO-Pins 
sorgfältig, damit Du die benötigte Peripherie auch voll nutzen kannst.

> Die AVR's in Assembler für die Wandlung Step/Dir --> A/B zu
> programmieren,
> da sehe ich kein Problem.

Mit einem guten C-Compiler ginge das vielleicht auch schon. Es wäre 
einen Versuch wert - aber nicht bei schönem Sonnenwetter ;-)

von Gerhard H. (sams_n)


Lesenswert?


von Mi N. (msx)


Angehängte Dateien:

Lesenswert?

Mi N. schrieb:
> Mit einem guten C-Compiler ginge das vielleicht auch schon. Es wäre
> einen Versuch wert - aber nicht bei schönem Sonnenwetter ;-)

Da war gerade eine Wolke am Himmel, siehe Anhang.
Die war aber sehr klein, weshalb ein Test entfallen mußte ;-)

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Falk B. schrieb:
> Beim ATXmega kann man die IOs so konfigurieren, daß man damit steigende
> und fallende Flanken erkennt und Hardware-Events auslöst, welche direkt
> den Timer ansteuern. Vermutlich können das auch die STM32.

Damit kannst du Zählen, aber nicht zusätzlich mit einem zweiten Pin die 
Zählrichtung umzuschalten. Für das Umschalten wird man um einen 
Interrupt und eine paar Zeilen Programmcode wohl nicht drumherum kommen, 
wenn man nicht noch etwas zusätzliche Hardware spendieren will.

Die Wahrscheinlichkeit das es sowas fertig gibt dürfte arg gering sein 
weil es wohl keinen Sensor gibt er sowas ausgibt und eine µC das 
verarbeiten/zählen müsste. Zur Kommunikation zwischen zwei µC wäre sowas 
als Protokoll noch absurder. Gray-Code ist dagegen recht gebräuchlich 
und wird daher auch von etlichen µC in Hardware unterstützt.

von Mi N. (msx)


Lesenswert?

Mi N. schrieb:
> Die war aber sehr klein, weshalb ein Test entfallen mußte

Folglich werden in Zeile 21 noch + und - Flanken erkannt. Das muß noch 
angepaßt werden, erhöht die Laufzeit aber nur minimal.

von Gerhard H. (sams_n)


Lesenswert?

Hallo Mi N.,
danke für deine Mühe.
Das in Assembler für den AVR zu programmieren , damit hab ich kein 
Problem.
Werde ich auch machen falls es beim STM32 keine Möglichkeit gibt.
Wäre halt (warscheinlich) zu schön gewesen , Kabel anstecken und 
läuft....

von Mi N. (msx)


Lesenswert?

Mich hat einfach selber interessiert, ob man es bei hinreichender 
Ausführungszeit noch in C formulieren kann.

Bleibt noch offen, ob Dir die teilweise nur 16 Bit breiten Zähler im 
F411 auch reichen. Diese per Software zu vergößern könnte wegen 
up/down-Richtungswechsel heikel werden. Packt man die Zähler in einen 
kl. AVR sind 32 Bit kein Problem, der Zugriff per IIC dauert aber 
deutlich länger.

von Falk B. (falk)


Lesenswert?

Mi N. schrieb:
>> Die war aber sehr klein, weshalb ein Test entfallen mußte
>
> Folglich werden in Zeile 21 noch + und - Flanken erkannt. Das muß noch
> angepaßt werden, erhöht die Laufzeit aber nur minimal.

Ja. Aber man sollte nicht nur die Abtastung in der Schleife machen, auch 
den alten Wert kopieren. Eher so.
1
  while(1) {
2
    do {
3
      alt_step = temp;
4
      temp = PINB;
5
    } while( temp & ~alt_step & BIT(STEP) );  // auf +Flanke von STEP warten

Klar, wenn man vor weiß, da STEP auf LOW ist, muss man nur prüfen, ob es 
jetzt HIGH ist. Geht einfacher und schneller, erst recht in ASM. Aber 
bleibt das Problem, daß man DIR zur richtigen Zeit abtasten muss, um es 
dann auszuwerten. Naja, da hier noch Luft ist, sollte man es mit der 
Microoptimierung nicht übertreiben und eher auf Nummer sicher gehen.

: Bearbeitet durch User
Beitrag #7426339 wurde vom Autor gelöscht.
von Mi N. (msx)


Lesenswert?

Falk B. schrieb:
> Ja. Aber ...

Egal, man muß es erst einmal testen.

: Bearbeitet durch User
von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Hier mal als ASM. Kann man kaum schneller machen.

von Walter T. (nicolas)


Lesenswert?

Geht es nur ums Mitschreiben, oder sollen die Signale im STM32F411 
erzeugt werden?

von Gerhard H. (sams_n)


Lesenswert?

Mi N. schrieb:
> Bleibt noch offen, ob Dir die teilweise nur 16 Bit breiten Zähler im
> F411 auch reichen. Diese per Software zu vergößern könnte wegen
> up/down-Richtungswechsel heikel werden.
Das hab ich bereits per Overrun/Underrun Interrupt gelöst, funktioniert 
einwandfrei.

Falk B. schrieb:
> Hier mal als ASM. Kann man kaum schneller machen.
Danke, kann ich ev. gebrauchen.

Walter T. schrieb:
> Geht es nur ums Mitschreiben, oder sollen die Signale im STM32F411
> erzeugt werden?
Der STM32F411 muss (soll ;-) ) folgendes machen:
5x Step/Dir Signale einlesen --->
Im Hauptprogramm werden diese Werte verrechnet , dh. es wird die 
Nullpunktverschiebung der X,Y u. Z Achse in Bezug auf die Drehwinkel der
A- u. C-Achse berechnet (nennt man TCPM oder RTCP )
Daraus resultierend werden dann wieder STEP/DIR Signale für die 5 
Endstufen
generiert und in (fast) Echtzeit ausgegeben.
Derzeit lese ich die 5x STEP/DIR Signale mittels Interrupt ein, das 
frisst aber zuviel an Ressourcen. Der Debugger von MikroE sagt mir dass 
er ca. 120 Takte braucht um in die ISR rein u. raus zu kommen.
Deswegen muss das im Hintergrund ablaufen. Wenns eben nicht anders geht 
dann mit zus. AVR's od. Logic IC's über die quadratur Encoder Eingänge.
Dann hab ich genug Zeit für die trigonometrischen Berechnungen frei.

von Zino (zinn)


Lesenswert?

Wenn's nur ein Kanal wäre, könnte man STEP auf zwei Timer geben, einen 
davon im gated mode mit DIR. Mit ein wenig Mathematik kann dann der 
gewünschte Wert berechnet werden. Beim Auslesen muß man aufpassen, daß 
nicht ein STEP dazwischenfunkt, z.B. indem man in einer Schleife Zähler 
A, B und wieder A ausliest, bis man zweimal denselben Wert für Zähler A 
liest.

Leider ist das nicht auf 5 Kanäle skalierbar, weil das Routing für die 
Zählereingänge doch arg beschränkt ist und die STM32F4-Serie eh nur 8 
Zähler hat.

von Walter T. (nicolas)


Lesenswert?

Gerhard H. schrieb:
> Der Debugger von MikroE sagt mir dass
> er ca. 120 Takte braucht um in die ISR rein u. raus zu kommen.

Das klingt viel, aber weniger als die Hälfte wird es wohl nicht. Sind da 
die 24 Takte, um die ISR zu starten und zu verlassen schon dabei?

Sind alle Eingänge an einem Port, daß Du die Dekodierung direkt parallel 
mit allen Pins gleichzeitig in einem Datenwort machen kannst?

von Falk B. (falk)


Lesenswert?

Walter T. schrieb:
> Sind alle Eingänge an einem Port, daß Du die Dekodierung direkt parallel
> mit allen Pins gleichzeitig in einem Datenwort machen kannst?

Unsinn. Es gibt eine solide Lösung mit externer Hardware. Da muss man 
keine Handstände und Krampfaktionen in der Software machen und kann die 
CPU zu 100% mit sinnvollen Aufgaben auslasten. Problem gelöst.

von Gerhard H. (sams_n)


Lesenswert?

Hallo,

hab mal einen Arduino Nano mit Bascom/ASM programmiert.
Der soll die 5 Stp/Dir Kanäle einlesen und Quadrature Signale ausgeben.
Läuft am Simulator , kann aber erst heute abend testen.


1
$regfile = "m328pdef.dat"
2
$crystal = 16000000                               '16Mhz Quarz
3
$hwstack = 100 : $swstack = 200 : $framesize = 200
4
5
'-----------------------------------------------------------
6
'
7
'                          ___________
8
' C-out A      TXD    D1 -|           |-      V_IN
9
' C-out B      RXD    D0 -|   o o o   |-      GND
10
'              Reset  C6 -|   - o +   |- C6   Reset
11
'              GND       -|           |-      5V  out
12
' X-Step       INT0   D2 -|  Arduino  |-
13
' Y-Step       INT1   D3 -|           |-
14
' Z-Step       T0     D4 -|     N     |- C5   Z-out B
15
' A-Step       T1     D5 -|     A     |- C4   Z-out A
16
' C-Dir               D6 -|     N     |- C3   Y-out B
17
' C-Step              D7 -|     O     |- C2   Y-out A
18
' X-Dir               B0 -|           |- C1   X-out B
19
' Y-Dir               B1 -|           |- C0   X-out A
20
' Z-Dir               B2 -|    ___    |-
21
' A-Dir               B3 -|   |   |   |-      3v3 out
22
' A-out A             B4 -|   |   |   |- B5   A-out B  onboardLED
23
'                          -----------
24
'
25
'-------------------------------------------------------------------------------
26
27
Config Portb = &B1111_1111                        ' alle Pins output
28
Config Portc = &B0011_0000                        ' 4+5 output , Rest input
29
Config Portd = &B0000_0011                        ' 0+1 output , Rest input
30
31
'--- Config Interrupts -------------------------------------
32
33
Config Int0 = Falling
34
On Int0 X_step Nosave
35
Enable Int0
36
37
Config Int1 = Falling
38
On Int1 Y_step Nosave
39
Enable Int1
40
41
Config Timer0 = Counter , Edge = Falling
42
On Timer0 Z_step Nosave
43
Enable Timer0
44
45
Config Timer1 = Counter , Edge = Falling
46
On Timer1 A_step Nosave
47
Enable Timer1
48
49
50
Config Aci = On , Compare = On , Trigger = Falling
51
Acsr.acbg = 1                                     ' Int.Ref
52
On Aci C_step Nosave
53
Enable Aci
54
55
Enable Interrupts
56
57
Portb = 0
58
Timer0 = 255
59
Timer1 = 65535
60
61
$asm
62
ldi r28,&B00000001                                '1
63
ldi r29,&B00000100                                '4
64
ldi r30,&B00010000                                '16
65
ldi r31,&B01000000                                '64
66
SER R26                                           '256
67
$end Asm
68
69
' --- Do - Loop   ------------------------------------------
70
Do
71
Loop
72
End
73
74
' --- INTERRUPTS  ------------------------------------------
75
76
X_step:
77
$asm
78
in r8,SREG
79
sbic pinB , 0                                     'Dir Pin
80
Subi R16 , 2                                      '-2
81
add r16,r28                                       '+1
82
mov r17,r16                                       'copy
83
ANDI r17, &B00000011                              'bit 0 und 1 isolieren
84
sbrc r17,1
85
eor r17,r28                                       'unteres Bit umdrehen wenn oberes Bit 1
86
in r27 , portC
87
ANDI r27, &B11111100                              'output Register isolieren
88
add r27 , r17                                     'bit 0 u 1 out
89
Out Portc , R27
90
Out Sreg , R8
91
$end Asm
92
Return
93
94
Y_step:
95
$asm
96
in r8,SREG
97
sbic pinB , 1                                     'Dir Pin
98
Subi R18 , 8                                      '-8
99
add r18,r29                                       '+4
100
mov r19,r18                                       'copy
101
ANDI r19, &B00001100                              'bit 2 und 3 isolieren
102
sbrc r19,3
103
eor r19,r29                                       'unteres Bit umdrehen wenn oberes Bit 1
104
in r27 , portC
105
ANDI r27, &B11110011                              'output Register isolieren
106
add r27 , r19                                     'bit 2 u 3 out
107
Out Portc , R27
108
Out Sreg , R8
109
$end Asm
110
Return
111
112
Z_step:
113
$asm
114
in r8,SREG
115
Out Tcnt0 , R26                                   'timer auf 255 setzen
116
sbic pinB , 2                                     'Dir Pin
117
Subi R20 , 32                                     '-32
118
add r20,r30                                       '+16
119
mov r21,r20                                       'copy
120
ANDI r21, &B00110000                              'bit 4 und 5 isolieren
121
sbrc r21,5
122
eor r21,r30                                       'unteres Bit umdrehen wenn oberes Bit 1
123
in r27 , portC
124
ANDI r27, &B11001111                              'output Register isolieren
125
add r27 , r21                                     'bit 4 u 5 out
126
Out Portc , R27
127
Out Sreg , R8
128
$end Asm
129
Return
130
131
A_step:
132
$asm
133
in r8,SREG
134
Out Tcnt1l , R26                                  'timerL auf 255 setzen
135
Out Tcnt1l , R26                                  'timerH auf 255 setzen
136
sbic pinB , 3                                     'Dir Pin
137
Subi R22 , 32                                     '-32
138
add r22,r30                                       '+16
139
mov r23,r22                                       'copy
140
ANDI r23, &B00110000                              'bit 4 und 5 isolieren
141
sbrc r23,5
142
eor r23,r30                                       'unteres Bit umdrehen wenn oberes Bit 1
143
in r27 , portB
144
ANDI r27, &B11001111                              'output Register isolieren
145
add r27 , r23                                     'bit 4 u 5 out
146
Out Portb , R27
147
Out Sreg , R8
148
$end Asm
149
Return
150
151
C_step:
152
$asm
153
in r8,SREG
154
sbic pinD , 6                                     'Dir Pin
155
Subi R24 , 2                                      '-2
156
add r24,r28                                       '+1
157
mov r25,r24                                       'copy
158
ANDI r25, &B00000011                              'bit 0 und 1 isolieren
159
sbrc r25,1
160
eor r25,r28                                       'unteres Bit umdrehen wenn oberes Bit 1
161
in r27 , portD
162
ANDI r27, &B11111100                              'output Register isolieren
163
add r27 , r25                                     'bit 0 u 1 out
164
Out Portd , R27
165
Out Sreg , R8
166
$end Asm
167
Return

von Walter T. (nicolas)


Lesenswert?

Dann kannst Du Dir ordentlich auf die Schulter klopfen, daß Du es 
schaffst, die CPU 100% mit sinnvollen Dingen zu beschäftigen! Ich habe 
meistens so eine Auslastung um 10...60%.

von Falk B. (falk)


Lesenswert?

Wenn man Interesse hat, kann man das auch in einen CPLD packen, die gibt 
es ziemlich billig auf Ebay. Hier incl. Programmieradapter für unter 15 
Euro!

https://www.ebay.de/itm/232684120955

Oder der hier, allerdings braucht man dann noch den Programmieradapter 
für XILINX.

https://www.ebay.de/itm/385453238900
https://www.ebay.de/itm/272374665838

Hier der XILINX Adapter, natürlich etwas teuer für die Einzelanwendung.

https://www.ebay.de/itm/272600102573

Hier die Billigversion, aber wer hat schon noch einen echten 
Parallelport am Computer?

https://www.ebay.de/itm/202022683374

Wenn du magst, kann ich dir so einen CPLD von XILINX programmieren, ich 
hab das Kabel und Know How hier. Altera kann ich nicht, hab kein Kabel 
dafür.

von Falk B. (falk)


Lesenswert?

Gerhard H. schrieb:
> Hallo,
>
> hab mal einen Arduino Nano mit Bascom/ASM programmiert.

Schau mal was dort oben steht! Längere Quelltexte als Anhang!

> Der soll die 5 Stp/Dir Kanäle einlesen und Quadrature Signale ausgeben.
> Läuft am Simulator , kann aber erst heute abend testen.

Ohje, ASM im BASIC Compiler 8-0
Das ist alles deutlich langsamer als meine Version. Und wenn die Takte 
gleichzeitig kommen, wird es nochmal langsamer. Es reicht nicht, wenn es 
prinzipiell funktioniert, es muss auch SICHER bei maximaler Last 
funktionieren. Man kann vieles in Software machen, aber nicht alles.

von Mi N. (msx)


Lesenswert?

Gerhard H. schrieb:
> hab mal einen Arduino Nano mit Bascom/ASM programmiert.
> Der soll die 5 Stp/Dir Kanäle einlesen und Quadrature Signale ausgeben.

Wir wissen nicht, welche Achsen zu welcher Zeit welche Ausgangssignale 
liefern. Vielleicht hast Du ja Glück und Deine Lösung reicht Dir aus. 
Mich wundert auch ein wenig, daß es zuvor allein per Software gelaufen 
ist.
Selber würde ich die Lösung niemals in nur einen einzigen ATmega328 
packen.

Gerhard H. schrieb:
>> Bleibt noch offen, ob Dir die teilweise nur 16 Bit breiten Zähler im
>> F411 auch reichen. Diese per Software zu vergößern könnte wegen
>> up/down-Richtungswechsel heikel werden.
> Das hab ich bereits per Overrun/Underrun Interrupt gelöst, funktioniert
> einwandfrei.

Die F411 Timer arbeiten nicht alle gleich. Insbesondere werden die 
Interrupt-Flags eines Timers nicht immer über einen einzigen ISR-Vektor 
verarbeitet. Die NVIC-Priorität kann man passend einstellen, die 
ISR-Vektoren haben jedoch eine feste Priorität, was genau verkehrt herum 
sein kann. Weder kenne ich Deine Software noch möchte ich hier 
dramatisieren, daher nur dieser Hinweis.
Wenn alles einwandfrei funktioniert, ist es gut. Und wenn es Aussetzer 
gibt, sind die sicherlich so selten, daß sie nur alle paar Stunden 
auftreten ;-)

von Gerald M. (gerald_m17)


Lesenswert?

Das sollte doch für einen STM32 kein Problem sein.
Interrupts für Überlauf und Unterlauf der Timer aktivieren. Interrupt 
für jedes Dir-Signal aktivieren und die Stepsignale an die Counter dran.
Bei einem "dir-Interrupt" entsprechend die Richtung des Counters 
einstellen. Fertig.
So oft ändert sich ja die Richtung nicht, so dass diese paar Interupts 
nicht ins Gewicht fallen.

von Zino (zinn)


Lesenswert?

Gerald M. schrieb:
> Bei einem "dir-Interrupt" entsprechend die Richtung des Counters
> einstellen. Fertig.

Wir wissen nicht, wieviele ns zwischen der Änderung von DIR und dem 
nächsten STEP minimal vergehen. Wir kennen nur den Abstand zwischen zwei 
gleichsinnigen STEP-Flanken.

von Gerhard H. (sams_n)


Lesenswert?

Gerald M. schrieb:
> Bei einem "dir-Interrupt" entsprechend die Richtung des Counters
> einstellen. Fertig.

Werde ich auch mal probieren

Zino schrieb:
> Wir wissen nicht, wieviele ns zwischen der Änderung von DIR und dem
> nächsten STEP minimal vergehen. Wir kennen nur den Abstand zwischen zwei
> gleichsinnigen STEP-Flanken.

Leider habe ich dazu auch keine Info , bzw. nicht die Mittel dies zu 
messen.
Der step Impuls ist 12 ns breit.
Wenn STEP und Dir gleichzeitig gesetzt werden und auf die fallende 
Flanke
von STP getriggert wird (aktiv high) müsste das laufen.

von Falk B. (falk)


Lesenswert?

Gerhard H. schrieb:
> Leider habe ich dazu auch keine Info , bzw. nicht die Mittel dies zu
> messen.
> Der step Impuls ist 12 ns breit.

WIRKLICH? Kann ich nicht ganz glauben. Und das willst du per SOFTWARE 
dekodieren! Viel Glück!

von Gerhard H. (sams_n)


Lesenswert?

Gerhard H. schrieb:
> Der step Impuls ist 12 ns breit.

ohje FEHLER !!! , Impulsbreite ist 1,2µs also 1200ns

: Bearbeitet durch User
von Mi N. (msx)


Lesenswert?

Gerald M. schrieb:
> Das sollte doch für einen STM32 kein Problem sein.
> Interrupts für Überlauf und Unterlauf der Timer aktivieren. Interrupt
> für jedes Dir-Signal aktivieren und die Stepsignale an die Counter dran.
> Bei einem "dir-Interrupt" entsprechend die Richtung des Counters
> einstellen. Fertig.
> So oft ändert sich ja die Richtung nicht, so dass diese paar Interupts
> nicht ins Gewicht fallen.

Jetzt habe ich doch noch ins Datenblatt gesehen.
Dort gibt es nur ein gemeinsames Flag UIF, was bei Über- und Unterlauf 
gesetzt wird. Die ISR muß daher noch nachsehen, was zu tun ist und 
hoffen, daß sich zwischendurch nichts verändert hat.
Die Annahme, daß sich die Richtung nur eher selten ändert, ist mir zu 
optimistisch. Es kann ja alles so funktionieren, wie Du geschrieben 
hast, hängt aber doch von den (derzeit unbekannten) Eingangssignalen ab.

Timer 2 - 5 haben nur einen ISR-Vektor. Da kann man Richtungsumschaltung 
über einen CC-Interrupt auslösen und UIF nach Bedarf verwerten.
Bei Timer 1 hat 'TIM1_UP_TIM10' höhere Priorität als 'TIM1_CC'. Hier 
kann es Probleme geben. Es kann sinnvoll sein, UIF durch ein CC-Flag zu 
ersetzen, um nur einen Vektor benutzen zu müssen.
Wie oben geschrieben, gilt dies bei der Erweiterung von 16 Bit Timern 
auf 32 Bit - sofern notwendig.

@TO:
Ich habe noch einen Vorschlag für Dich, die Zähler in einen externen 
ATtinyXX2 zu packen: 
http://mino-elektronik.de/mt12_iic/mt12_iic.htm#qcnt_tiny202
Anstelle der Eingänge PHA und PHB müßte man das Programm auf STEP/DIR 
anpassen. Vielleicht mache ich das noch selber.

von Gerald M. (gerald_m17)


Lesenswert?

Zino schrieb:
> Wir wissen nicht, wieviele ns zwischen der Änderung von DIR und dem
> nächsten STEP minimal vergehen.

Wir wissen, dass es sich um eine CNC-Fräße handelt. Die beschleunigt und 
bremst ab. Bei einer Richtungsumkehr wird normal einiges berechnet, so 
dass nicht beide Pulse gleichzeitig kommen.

Mi N. schrieb:
> Die ISR muß daher noch nachsehen, was zu tun ist und hoffen, daß sich
> zwischendurch nichts verändert hat.
> Die Annahme, daß sich die Richtung nur eher selten ändert, ist mir zu
> optimistisch.

Das Nachsehen bei einem Überlauf von 5x 16-Bit Timern ist keine 
Zauberei. Selbst bei den genannten  250kHz passiert das nur wenige Male 
in der Sekunde.
Ich habe mir den genannten Controller nicht genau angeschaut, viele 
bieten auch die Möglichkeit einen Timer als "Prescaler" zu nehmen. 
Vielleicht gibt es ja die Möglichkeit solch einen STM32 auszuwählen.
Und die Richtungsumkehr kommt definitiv bei einer CNC Fräse nicht oft 
vor, weil das physikalisch nicht geht.

Mi N. schrieb:
> Timer 2 - 5 haben nur einen ISR-Vektor.
Die Dir-Signale kommen natürlich an eigene Pins mit Interrupt und haben 
nichts mit den Countern zu tun, außer eben dass sie im Interrupt das 
Register eines Counter ändert um dle Zählrichtung umzudrehen.

Da bis 250kHz angegeben ist gehe ich außerdem von einem sehr hohen 
Mikrostepping aus. Da macht ein verschluckter Step nichts aus, da die 
Auflösung dann deutlich höher ist als die Genauigkeit der Fräse. Da sie 
außerdem genau so oft in die eine wie die andere Richtung fährt, 
gleichen sie sich aus (sofern das überhaupt vorkommt)

von Mi N. (msx)


Lesenswert?

Gerald M. schrieb:
> Da macht ein verschluckter Step nichts aus, da die
> Auflösung dann deutlich höher ist als die Genauigkeit der Fräse.

Es geht mir nicht um einen verschluckten Schritt, sondern um einen 
verschluckten Überlauf eines Timers.
Aber schön, wenn alles so einfach ist.

von Gerald M. (gerald_m17)


Lesenswert?

Mi N. schrieb:
> sondern um einen verschluckten Überlauf eines Timers.

Wie gesagt, der Überlauf selbst kommt maximal 10x pro Sekunde vor, 
keine Ahnung wie die sich da verschlucken sollen. Der Timer setzt auch 
ohne Interrupt die Flag, dann prüft man halt in jedem Interrupt alle 
Flags ab.

: Bearbeitet durch User
von Gerhard H. (sams_n)


Lesenswert?

Gerald M. schrieb:
> Wie gesagt, der Überlauf selbst kommt maximal 10x pro Sekunde vor

Das ist leider nicht so.
Theoretisch kann man auch im Überlaufbereich nur einige Takte hin und 
her pendeln, z.B. Abzeilen von sehr kleinen Flächen beim Fräsen, dan 
kommt der Überlauf hunderte wenn nicht gar tausende male pro Sekunde.

Gerald M. schrieb:
> Da macht ein verschluckter Step nichts aus

Doch , auch ein verlorender Takt ist zuviel.
Da ich die Genauen Werte in trigonometrischen Funktionen weiter 
verrechne
muss da ALLES stimmen.

von Gerald M. (gerald_m17)


Lesenswert?

Dann rück mal raus mit den Mikroschritten, der maximalen Beschleunigung 
und dem Ruck, wenn du die Achse mit 1KHz vorwärts und rückwärts fahren 
lässt.

Idealerweise gleich noch sagen wieviel Mikrometer ein Schritt 
entspricht.

Du sagst, du machst es aktuell mit Interrupts. Meine Variante ist 
deutlich besser (wenn es vorher geklappt hat reicht es definitiv) und 
lässt 98% der CPU Teit übrig für andere Aufgaben.

von Gerald M. (gerald_m17)


Lesenswert?

Kurzes Rechenbeispiel:
Schrittmotor maximale Drehzahl bevor das Drehmoment komplett abgefallen 
ist: 10U/s. Bei 200 Pulse pro Umdrehung sind das maximal 2000 
Vollschritte pro Sekunde. Für 250kHz bräuchte man 128 Mikroschritte.
Bei einer maximalen Geschwindigkeit der Fräse von 1500mm/min wäre ein 
Vollschritt also 25mm/s bei 2000 Vollschritten pro Sekunde bei etwa 
12,5um.
Ein verpasster Mikroschritt ist also irgendwo bei 100nm Fehler. Aus 
Erfahrung kann ich dir sagen, dass thermischer Drift, ungenaue 
Gewindesteigung und Spiel deutlich mehr Fehler verursachen. Ganz zu 
Schweigen davon, dass ein Schrittmotor solch eine Auflösung mechanisch 
nicht her gibt.

Von daher kann deine Fehlerbetrachtung maximal von akademischer Natur 
sein.

von Gerhard H. (sams_n)


Lesenswert?

Gerald M. schrieb:
> Dann rück mal raus mit den Mikroschritten, der maximalen Beschleunigung
> und dem Ruck, wenn du die Achse mit 1KHz vorwärts und rückwärts fahren
> lässt.
>
> Idealerweise gleich noch sagen wieviel Mikrometer ein Schritt
> entspricht.
für die derzeitigen Tests habe ich 1µm für einen Schritt eingestellt.
1000 Schritte = 1mm
250000 Schritte/s  / 1000  = 250mm/s =15m/min Schub

Gerald M. schrieb:
> Du sagst, du machst es aktuell mit Interrupts
Derzeitiger Stand:
STEP/DIR zu A/B quadrature Wandler mittels AVR
STM32:
TIM2 u. TIM5 lesen quadrature direkt in 32bit counter register
TIM1,TIM3 und TIM4 werden over-/underrun der 16bit counter mit
interrupts in 32 bit Werte weitergegeben

Gerald M. schrieb:
> Von daher kann deine Fehlerbetrachtung maximal von akademischer Natur
> sein.
Ich kenne die Thematik. Ich baue seit Jahrzehnten die verschiedensten 
Hobby-CNC Maschinen. Nun geht es aber um ganz andere Sachen. "TCPM" 
5-Achs Maschinenkinematk Berechnung in Echtzeit. D.h. werden hier Takte 
verschluckt werden auch diese Berechnungen falsch sein. Nicht nur so wie 
bei einer normalen 3-achs Kinematik dass eine Achse ein paar Steps 
daneben steht. Daher muss das Lesen der Signale zu 1000% sicher 
funktionieren bevor ich mich den nächsten Themen dieses Projektes widme.
Erste tests heute Nacht sehen sehr gut aus.  Alle 5 Achsen mal ca. 20min 
auf "Vollgas" ein 5x CNC Programm laufen lassen. Zumindest 4 Achswerte 
konnte ich am LCD Display kontrollieren ,  TIM2,3,4,5 passten exakt.
Stresstest Programm im over-/underrun Bereich der 3 16bit Timer werde 
ich ev. heute abend machen.

: Bearbeitet durch User
von Gerald M. (gerald_m17)


Lesenswert?

Ja, das Problem, warum es keine Hardware Schnittstelle gibt, die 
automatisch Step und Dir Signale einliest ist, dass es ja nicht wie A/B 
ein Sensorsignal ist, sondern ein Steuersignal, was vom Prinzip her 
irgendwo bekannt sein muss. Wenn man das einlesen muss ist beim System 
etwas nicht richtig.

Es gibt verschiedene Varianten:

STM32 und Timer im Counter Mode, wie ich das geschrieben habe.

FPGA macht das problemlos

Umwandlung in A/B Signal. Hier gibt es bestimmt eine analoge Schaltung 
(A und B durch Flip Flops erzeugt (eins bei fallender das andere auf 
steigende Flanke). Das Dir Signal investiert ein Ausgabgssignal eines 
Flip Flops.

von Gerhard H. (sams_n)


Lesenswert?

Gerald M. schrieb:
> Ja, das Problem, warum es keine Hardware Schnittstelle gibt, die
> automatisch Step und Dir Signale einliest ist, dass es ja nicht wie A/B
> ein Sensorsignal ist, sondern ein Steuersignal, was vom Prinzip her
> irgendwo bekannt sein muss. Wenn man das einlesen muss ist beim System
> etwas nicht richtig.

Ist aber eben bei Hobby-CNC PC-Steuerungen seit je her standard
(Mach3, mach4, UCCNC, Benazan, .....)

Wandlung step/dir --> A/B sehe ich als erledigt , geht im AVR 
zuverlässig.
over/underrun der 3 16bit counter muss ich noch weiter testen.

von Zino (zinn)


Lesenswert?

Der STM32F411 kann quadrature encoder input nur für vier Timer, der TO 
braucht das für fünfe.

von Zino (zinn)


Lesenswert?

Ich muß mich korrigieren: Laut STM32F411-Datenblatt sind es vier Timer 
(TIM2 bis TIM5), laut Reference Manual fünf Timer (TIM1 bis TIM5), die 
das können.

von Gerhard H. (sams_n)


Lesenswert?

Hallo,

vorerst einmal DANKE für die vielen Tipps die ich in diesem Thread 
erhalten habe.
Ich habe in letzter Zeit nun einige Varianten durch probiert, d.h. 
Stresstests   mit verschiedenen G-Codes über mehrere Stunden Laufzeit 
bei max. speed. (380kHz an allen 5 Achsen)
Dabei wurde besonders darauf geachtet dass die benötigten Interrupts f.
16bit Timer- Über/Unterlauf und Richtungsumkehr alle gemeinsam 
angefordert wurden.
Hier meine Varianten u. Ergebnisse:
A:
5 externe AVR's mit dem Code von Falk.
stp/dir->AB quadrature -> STM32
Ergebnis: 1A; 0 Fehler an allen 5 Achsen über mehrere Stunden
B:
5 externe AVR's mit meinem Code (Int0).
stp/dir->AB quadrature -> STM32
Ergebnis: 1A; 0 Fehler an allen 5 Achsen über mehrere Stunden
C:
STEP Signale an STM32 Timer1-5
DIR Signale an Eingangpins mit Interrupts
Ergebnis: 2-5 Steps Fehler an verschiedenen Achsen über mehrere Stunden

Also stand fest , Variante A od. B wird verwendet.
Aber irgendwie ließ mich der Gedanke einfach nicht los
dass es direkt am STM32 auch laufen muss.
Also nochmal an den Tmer Registern stundenlang rumgebastelt bis ich eine 
Lösung hatte.
Hier die Timer Register Einstellung:
1
  RCC_APB1ENR.TIM2EN = 1              
2
  TIM2_CR1.EN = 0                    
3
  TIM2_CCMR1_Input.CC1S0 = 1         
4
  TIM2_CCMR1_Input.CC1S1 = 0        
5
  TIM2_CCMR1_Input.CC2S0 = 1        
6
  TIM2_CCMR1_Input.CC2S1 = 0        
7
  TIM2_CCER.CC1P = 1                
8
  TIM2_CCER.CC1NP= 1                
9
  TIM2_SMCR.SMS0 = 1                
10
  TIM2_SMCR.SMS1 = 0                
11
  TIM2_SMCR.SMS2 = 0               
12
  TIM2_ARR = 4294967295            
13
  TIM2_PSC = 0                     
14
  TIM2_CR1.EN = 1

Damit lässt sich ein STP/DIR Signal an den quadrature Eingängen 
einwandfrei lesen.
Der Timerwert muss noch durch 2 dividiert werden , aber damit kann ich 
leben.
Tests ,nur steigende od. fallende Flanke am STP Eingang zu verwenden,
funktionieren nicht.
Auch "TIMx_PSC = 1" funktioniert nicht da dieser Wert erst beim ersten 
Richtungswechsel , dh. Flankenwechsel am DIR Eingang gelesen wird.

BG Gerhard

von Zino (zinn)


Lesenswert?

Falls mal jemand in der Zukunft ein ähnliches Problem hat, diesen Faden 
findet und  warum auch immer die Lösung von Gerhard nicht verwenden kann 
oder will: Ich stieß beim Stöbern bei Digi-Key auf den LS7184N, der 
konvertiert von A/B nach STEP/DIR. Kostet deutlich mehr als ein ATtiny 
o.ä. und ist ein Marktplatzangebot (wohl direkt vom Hersteller), dafür 
muß er nicht programmiert werden.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Zino schrieb:
...
> konvertiert von A/B nach STEP/DIR.

Der Thread ging aber um STEP/DIR eingangssignale...

von Zino (zinn)


Lesenswert?

Stimmt, ich bitte um Vergebung.

von Gerald M. (gerald_m17)


Lesenswert?

Wenn man nicht programmieren will, geht auch der Vorschlag:
Beitrag "Re: pulse direction signal zu encoder a b?"

von Gerhard H. (sams_n)


Lesenswert?

Hallo Gerald,
der Tip wurde am Thread Anfang schon von Falk gegeben
BG Gerhard

von Viktor (derviktor)


Lesenswert?

Ich weiß, ich bin eigentlich zu spät, aber würde nicht ein einfacher 
D-Flip-Flop pro Kanal reichen? Das wären dann 2,5 mal 74HC74 statt 5 
AVRs.

Da der Encoder-Modus immer beide Flanken zählt, schaltet man den 
Flip-Flop als 1-Bit Prescaler für STEP (^Q auf D). Der 3-fach XOR ist in 
jedem der 5 Timer ja schon drin. Der muß alle 3 Signale (DIR, STEP und 
STEP/2) verbinden, und schon hat man den anderen Bit vom Gray-Code:
1
DIR  S  S/2 XOR
2
 0   0   0   0
3
 0   1   1   0
4
 0   0   1   1
5
 0   1   0   1
6
 0   0   0   0
7
8
 1   0   0   1
9
 1   1   1   1
10
 1   0   1   0
11
 1   1   0   0
12
 1   0   0   1

Mit TI1S=1 liegt der XOR-Ausgang an TI1. Jetzt muß STEP/2 noch auf 
CH2/TI2 liegen und mit SMS=001 nur TI2-Flanken gezählt werden.

Zur Sicherheit sollten die Signale gefiltert werden (IC1F und IC2F). Vor 
allem TI1, weil STEP/2 immer ganz kurz nach STEP schaltet (Verzögerung 
des Flip-Flops), und am XOR-Ausgang deswegen Gliches auftreten können. 
Zu jeder anderen Zeit dürfen DIR und TI1 feiern, was sie wollen. Daher 
sind diese Fälle auch nicht in der Tabelle oben drin.

Alle Angaben ohne Gewähr. Ich bin auf diesen Thread nur gerade zufällig 
gestoßen und habe nichts davon ausprobiert.

von Viktor (derviktor)


Lesenswert?

PS: TIM9 im 1-bit PWM Modus kann das 5. Flip-Flop ersetzen, womit nur 
noch 2 externe Chips nötig sind. Keine Ahnung, ob das alles gleichzeitig 
auf Pins zu mappen ist. Hauptsache, die philosophische Frage nach einer 
rein internen Lösung ist damit mit "ja" beantwortet ;)

von Rainer W. (rawi)


Lesenswert?

Mi N. schrieb:
> Die ISR muß daher noch nachsehen, was zu tun ist und hoffen, daß sich
> zwischendurch nichts verändert hat.

"hoffen" ist in der Software immer ein schlechtes Konzept. Das führt zu 
seltenen, scheinbar unerklärlichen Fehlern, die entsprechend übel zu 
debuggen sind.
Im Fall eines Dir-Interrupts müsstest du einen Blick in die 
Zeitspezifikationen deiner Geber werfen. Vermutlich ist die Reaktion auf 
den Interrupt so langsam, dass dein Hardwarezähler noch einen Puls mit 
der alten, falschen Richtung zählt, bevor die Interruptroutine so weit 
ist, dass sie die Richtung umschalten kann. Da müsste der Zählerstand 
dann korrigiert werden.
Zur Kontrolle ist es sicher gut, in der ISR das Dir-Signal noch einmal 
einzulesen und zu prüfen. Da kommt es auch drauf an, wie sauber die 
Signale von deinen Gebern kommen.

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.