Guten Morgen.
Wie hier im beitrag
angekündigt:Beitrag "Re: Wie ein schlecht dokumentierte Arduino Library nutzen?"
An und für sich Funktioniert das ganze.
Nur folgende Mankos:
Encoder zählt nicht richtig.
Arduino "hängt" sich beim schnellen drehen des encoder ab und zu auf und
der stepper dreht "Unendlich" in die letzte drehrichtung. (Das
"Unendlich" muss ich erst noch testen!)
Nicht gleich erschlagen, Die Variablen sind noch absolut "Nichtssagend"
und chaotisch weil ich nur das Nötigste angepasst habe damit es erst ein
mal läuft.
if ( rotating ); // wait a little until the bouncing is done
68
// Test transition
69
if (digitalRead(encoderPinA) != A_set ) { // debounce once more
70
A_set = !A_set;
71
// adjust counter - if A leads B
72
if ( A_set && !B_set )
73
StepperPos = -s; //change the 1 to steps to take when encoder turned
74
rotating = false; // no more debouncing until loop() hits again
75
}
76
}
77
78
void doEncoderB() {
79
if ( rotating );
80
if ( digitalRead(encoderPinB) != B_set ) {
81
B_set = !B_set;
82
// adjust counter + 1 if B leads A
83
if ( B_set && !A_set )
84
StepperPos = s; //change the 1 to steps to take when encoder turned
85
rotating = false;
86
}
87
}
88
89
void loop() {
90
91
buttonState = digitalRead(encoderButC);
92
buttonDState = digitalRead(encoderButD);
93
encoderPinANow = digitalRead(encoderPinA);
94
95
if ((encoderPinALast == HIGH) && (encoderPinANow == LOW)) {
96
if (digitalRead(encoderPinB) == HIGH) {
97
encoderPos++;
98
} else {
99
encoderPos--;
100
}
101
lcd.clear();
102
lcd.setCursor(0, 0);
103
lcd.print("Pos:");
104
lcd.setCursor(4, 0);
105
lcd.print(encoderPos);
106
lcd.setCursor(10, 0);
107
lcd.print("Max:-/700");
108
if ( RelPinStat == HIGH ) {
109
lcd.setCursor(0, 1);
110
lcd.print("Relais:AN ");
111
} else {
112
lcd.setCursor(0, 1);
113
lcd.print("Relais:AUS");
114
}
115
if ( Rel1PinStat == HIGH ) {
116
lcd.setCursor(11, 1);
117
lcd.print("Motor:AN ");
118
} else {
119
lcd.setCursor(11, 1);
120
lcd.print("Motor:AUS");
121
}
122
}
123
124
encoderPinALast = encoderPinANow;
125
126
if ( buttonState != encoderButCLast ) {
127
if ( buttonState == HIGH ) {
128
if ( RelPinStat == LOW ) {
129
digitalWrite(RelPin, HIGH);
130
RelPinStat = HIGH;
131
lcd.setCursor(0, 1);
132
lcd.print("Relais:AN ");
133
} else {
134
digitalWrite(RelPin, LOW);
135
RelPinStat = LOW;
136
lcd.setCursor(0, 1);
137
lcd.print("Relais:AUS");
138
}
139
}
140
}
141
142
encoderButCLast = buttonState;
143
144
if ( buttonDState != encoderButDLast ) {
145
if ( buttonDState == HIGH ) {
146
if ( Rel1PinStat == LOW ) {
147
digitalWrite(Rel1Pin, HIGH);
148
Rel1PinStat = HIGH;
149
lcd.setCursor(10, 1);
150
lcd.print("Motor:AN ");
151
} else {
152
digitalWrite(Rel1Pin, LOW);
153
Rel1PinStat = LOW;
154
lcd.setCursor(10, 1);
155
lcd.print("Motor:AUS");
156
}
157
}
158
}
159
160
encoderButDLast = buttonDState;
161
rotating = true;
162
163
if (LastStepperPos != StepperPos) {
164
LastStepperPos = StepperPos;
165
myStepper.step(StepperPos);
166
StepperPos = 0;
167
}
168
169
}
Umgebung:
Arduino IDE 1.8.19, alle Libs sind aus dem IDE eigenen Manager und auf
dem aktuellsten stand. OS ist Xubuntu 20.04.1.
Hardware:
Arduino Nano. (China, Old Bootloader.)
ULN2003 Board. (LB1233, der Stepper kommt aus einem Scanner. Da hab ich
auch das Darlington array her das pinkompatibel zum ULN2003 ist.)
Mitsumi M35SP-7NP 50Ohm/24V Stepper.
https://datasheetspdf.com/pdf-file/580641/MitsumiElectronics/M35SP-7/1
LCD: HD44780 , 20x4 mit PCF.
Encoder:
https://www.amazon.de/degree-encoder-compatible-Arduino-Raspberry/dp/B09Q8RSK6T
(Optisch und von der Funktion gleich, allerdings nicht dieses Modul
sondern ausgeschlachtet aus einer alten Stereoanlage.)
Für die Taster habe ich externe Pulldown widerstände, am encoder
zusätzlich 1nF kerkos.
Sooo, ich hoffe ich habe euch alle infos geliefert die ihr braucht um
mir eventeull bei dem problem mit dem encoder zu helfen.
Im Prinzip zählt er nur dann richtig wenn ich schnell genug drehe das
ich eine Rastposition überspringe und im Prinzip an der Rastposition
lande an der er bereits den zweiten zählen sollte. Es wäre allerdings
sehr schön wenn jede Rastposition vernünftig erkannt wird.
Vielen Lieben dank und bis später. ;)
Reduziere das Programm auf eine möglichst kleine Variante, die das
Problem so gerade eben noch hat. Zuerst mal gehören da die Bibliotheken
vom LCD und Stepper entfernt. Gebe die Variablen seriell aus, damit man
sehen kann, welche davon unerwartete Werte hat.
Sollte sich das Probleme ohne diese beiden Bibliotheken nicht
nachvollziehen lassen, dass ist auch das eine sehr nützliche Erkenntnis.
Finde in diesem Fall heraus, welche der beiden Bibliotheken den Fehler
auslöst.
Was mir da direkt negativ auffällt ist:
a) Ich sehe keinen Code zum Entprellen der Kontakte
b) Du machst zwischen den Abfragen der Kontakte Display-Ausgaben die mit
Sicherheit zu viel Zeit in Anspruch nehmen. Deswegen bekommst du bei
schnellem Drehen Probleme.
c) Du ruft immer wieder lcd.clear() auf. Dein Display wird daher beim
Drehen flackern und einen schlechten Kontrast zeigen. Notfalls kannst du
zuerst Leerzeichen ausgeben und dann mit den gewünschten Zahlen
überschreiben. Aber eigentlich ist das nicht nötig, da printf() Zahlen
bereits passend formatieren kann.
TL;DR, aber die Stepper Klasse ist sehr minimalistisch und
step(StepperPos) ist blockierend, was sich auf das Einlesen des Encoders
und die Reaktion auf die Tasten auswirkt bei großen Sprüngen in der
Position.
Die Interrupt Handler doEncoderA() und doEncoderB() fragen den Encoder
mit Entprellung ab, aber das Hauptprogramm (loop) fragt die Eingänge A
und B erneut direkt (ohne Entprellung) ab.
Generell wird davon abgeraten, Interrupthandler zu benutzen, weil die
Kontakte prellen und dabei beliebig viele Interrupts auslösen können.
Das Hauptprogramm kann dadurch stark ausgebremst werden. Solche Probleme
fallen eventuell erst viele Jahre später auf, wenn der Encoder nicht
mehr perfekt schaltet.
> if ( rotating ); // wait a little until the bouncing is done
Diese Zeile tut nicht das, was der Kommentar daneben sagt. Ich denke,
diese Zeile wird vom Compiler komplett entfernt.
Stefan ⛄ F. schrieb:> Reduziere das Programm auf eine möglichst kleine Variante, die das> Problem so gerade eben noch hat. Zuerst mal gehören da die Bibliotheken> vom LCD und Stepper entfernt. Gebe die Variablen seriell aus, damit man> sehen kann, welche davon unerwartete Werte hat.>> Sollte sich das Probleme ohne diese beiden Bibliotheken nicht> nachvollziehen lassen, dass ist auch das eine sehr nützliche Erkenntnis.> Finde in diesem Fall heraus, welche der beiden Bibliotheken den Fehler> auslöst.>> Was mir da direkt negativ auffällt ist:>> a) Ich sehe keinen Code zum Entprellen der Kontakte> b) Du machst zwischen den Abfragen der Kontakte Display-Ausgaben die mit> Sicherheit zu viel Zeit in Anspruch nehmen. Deswegen bekommst du bei> schnellem Drehen Probleme.> c) Du ruft immer wieder lcd.clear() auf. Dein Display wird daher beim> Drehen flackern und einen schlechten Kontrast zeigen. Notfalls kannst du> zuerst Leerzeichen ausgeben und dann mit den gewünschten Zahlen> überschreiben. Aber eigentlich ist das nicht nötig, da printf() Zahlen> bereits passend formatieren kann.
OK, also muss ich noch nachlesen wie ich das entprellen in software
richtig hinbekomme.
Deinen vorschlag umsetzen hat nur wenige minuten gedauert:
(Minimalversion)
1
//ML Steuerung (Versuch 1)
2
#include <Wire.h>
3
4
int encoderPinA = 2;
5
int encoderPinB = 3;
6
int encoderPos = 0;
7
int encoderPinALast = LOW;
8
int encoderPinANow = LOW;
9
int StepperPos = 0;
10
int LastStepperPos = 0;
11
int s = 1;
12
13
boolean A_set = false;
14
boolean B_set = false;
15
static boolean rotating = false;
16
17
18
void setup() {
19
Serial.begin(9600);
20
pinMode (encoderPinA, INPUT_PULLUP);
21
pinMode (encoderPinB, INPUT_PULLUP);
22
attachInterrupt(0, doEncoderA, CHANGE); //pin 2
23
attachInterrupt(1, doEncoderB, CHANGE); //pin 3
24
}
25
26
void doEncoderA() {
27
// debounce
28
if ( rotating ); // wait a little until the bouncing is done
29
// Test transition
30
if (digitalRead(encoderPinA) != A_set ) { // debounce once more
31
A_set = !A_set;
32
// adjust counter - if A leads B
33
if ( A_set && !B_set )
34
StepperPos = -s; //change the 1 to steps to take when encoder turned
35
rotating = false; // no more debouncing until loop() hits again
36
}
37
}
38
39
void doEncoderB() {
40
if ( rotating );
41
if ( digitalRead(encoderPinB) != B_set ) {
42
B_set = !B_set;
43
// adjust counter + 1 if B leads A
44
if ( B_set && !A_set )
45
StepperPos = s; //change the 1 to steps to take when encoder turned
46
rotating = false;
47
}
48
}
49
50
void loop() {
51
52
53
encoderPinANow = digitalRead(encoderPinA);
54
55
if ((encoderPinALast == HIGH) && (encoderPinANow == LOW)) {
56
if (digitalRead(encoderPinB) == HIGH) {
57
encoderPos++;
58
} else {
59
encoderPos--;
60
}
61
Serial.println(encoderPos);
62
}
63
64
encoderPinALast = encoderPinANow;
65
66
67
68
}
Serielle ausgabe:
1
10:42:57.568 -> 16
2
10:42:59.888 -> 17
3
10:43:01.181 -> 18
4
10:43:02.208 -> 19
5
10:43:02.274 -> 18
6
10:43:03.235 -> 19
7
10:43:03.932 -> 18
8
10:43:04.262 -> 19
9
10:43:05.159 -> 20
10
10:43:05.192 -> 21
11
10:43:06.716 -> 22
Hier besteht das problem bereits! Es wird erst ab der zweiten
Rastposition gezählt, es liegt also definitiv an meinem code.
J. S. schrieb:> TL;DR, aber die Stepper Klasse ist sehr minimalistisch und> step(StepperPos) ist blockierend, was sich auf das Einlesen des Encoders> und die Reaktion auf die Tasten auswirkt bei großen Sprüngen in der> Position.
Du kennst nicht zufällig eine bereits existierende Lib bei der ich
dieses problem nicht habe?
Ich hab allerdings auch kein problem damit zu versuchen die klasse
selbst zu ändern, wenn ich genug durchblick habe. ;-) (Also eher erst
später.)
Kilo S. schrieb:> wäre allerdings sehr schön wenn jede Rastposition vernünftig erkannt wird.
Die kurze Version der nächsten 50 Posts ist: frage den Impulsgeber auf
geeignete Art und Weise ab, dann geht das.
Tadellos geht das mit einem Timerinterrupt und Auswertung der A- und
B-Pegel in diesem Interrupt. Dann braucht man auch kein Gefrickel mit
Kondensatoren am Geber.
Fazit insgesamt: du solltest die Aufgaben trennen und sie so aufteilen,
dass sie sich gegenseitig nicht nachteilig beeinflussen.
Zuallererst machst du die Displayaktualisierung in der Hauptschleife und
das Einlesen der EA und das Berechnen des Drehgebers in einem
Timerinterrupt.
Ein ganz wichtiger Tipp zum Display: lass das LCD_clear() weg. Das
dauert eine Ewigkeit. Und zudem flackert das LED dadurch wie blöd (wenn
das Programm mal zügig durchläuft).
Ich mach das entweder so: bei der Initialisierung wird 1x der statische
Text an die entsprechende Position geschrieben und danach nur noch die
Teile des Displays aktualisiert, die sich ändern.
Oder ich schreibe alles blitzschnell in einen Displaybuffer und schreibe
von links oben nach rechts unten pro ms ein Zeichen vom Puffer aufs
Display. Ein 4x20 Display wird so ca. 12x pro Sekunde neu beschrieben.
Da flackert nichts und es beliben auch keine "ESD-Leichen" zurück, wenn
mal 1 Übertragung zum Display gestört wurde.
Zum Testen der Durchlaufzeit der Hautpschleife kannst du ja mal am
Anfang eines Schleifendurchlaufs einen EA-Pin setzen und am Ende wieder
zurücksetzen und diesen Pin auf einem Oszi/LA ansehen. Du wirst staunen,
wie langsam das Programm ist...
J. S. schrieb:> step(StepperPos) ist blockierend
Üble Sache.
Kilo S. schrieb:> Hier besteht das problem bereits!
Schmeisse die Interrupt-Handler auch raus. Deren Ausgaben verwendet dein
reduziertes Programm nicht mehr. So kannst du dich leichter auf den
wirklich relevanten Code konzentrieren.
> Du kennst nicht zufällig eine bereits existierende> Lib bei der ich dieses problem nicht habe?
Nein, ich bin kein Arduino Spezialist.
Lothar M. schrieb:> Die kurze Version der nächsten 50 Posts ist: frage den Impulsgeber auf> geeignete Art und Weise ab, dann geht das.
Genau das möchte ich mir doch hier erarbeiten!?
Wenn ich bereits wüsste wie, dann müsste ich ja nicht Fragen, die Tipps
bisher sind aber schon ein guter ansatz das ich gleich etwas zum thema
entprellen finden konnte!
Lothar M. schrieb:> Ein ganz wichtiger Tipp zum Display: lass das LCD_clear() weg. Das> dauert eine Ewigkeit. Und zudem flackert das LED dadurch wie blöd (wenn> das Programm mal zügig durchläuft).
Nun, wie ich bereits im anderen Beitrag angemerkt habe, ich bin mir
durch das viele lesen und testen im klaren darüber das es "Schnarchlahm"
sein kann weil ich noch keinen plan habe wie ich das mit dem Display am
besten mache.
Meine allererste noch ganz ganz wenig bearbeitete version war so
grottenschlecht das das Display nicht nur Flackerte oder Artefakte
zeigte.
Das geht sogar beides zusammen. ;-)
Hier mal der neue Code mit hoffentlich "Richtigem" entprellen.
1
//ML Steuerung (Versuch 1)
2
#include <Wire.h>
3
4
int encoderPinA = 2;
5
int encoderPinB = 3;
6
int encoderPos = 0;
7
int encoderPinALast = LOW;
8
int encoderPinANow = LOW;
9
int StepperPos = 0;
10
int LastStepperPos = 0;
11
int s = 1;
12
13
boolean A_set = false;
14
boolean B_set = false;
15
16
17
18
void setup() {
19
Serial.begin(9600);
20
pinMode (encoderPinA, INPUT_PULLUP);
21
pinMode (encoderPinB, INPUT_PULLUP);
22
attachInterrupt(0, doEncoderA, CHANGE); //pin 2
23
attachInterrupt(1, doEncoderB, CHANGE); //pin 3
24
}
25
26
void doEncoderA() {
27
static unsigned long last_interrupt_time = 0;
28
unsigned long interrupt_time = millis();
29
// If interrupts come faster than 200ms, assume it's a bounce and ignore
30
if (interrupt_time - last_interrupt_time > 200) {
31
// Test transition
32
if (digitalRead(encoderPinA) != A_set ) { // debounce once more
33
A_set = !A_set;
34
// adjust counter - if A leads B
35
if ( A_set && !B_set )
36
StepperPos = -s; //change the 1 to steps to take when encoder turned
37
}
38
last_interrupt_time = interrupt_time;
39
}
40
}
41
42
void doEncoderB() {
43
static unsigned long last_interrupt_time = 0;
44
unsigned long interrupt_time = millis();
45
// If interrupts come faster than 200ms, assume it's a bounce and ignore
46
if (interrupt_time - last_interrupt_time > 200) {
47
if ( digitalRead(encoderPinB) != B_set ) {
48
B_set = !B_set;
49
// adjust counter + 1 if B leads A
50
if ( B_set && !A_set )
51
StepperPos = s; //change the 1 to steps to take when encoder turned
52
}
53
last_interrupt_time = interrupt_time;
54
}
55
}
56
57
void loop() {
58
59
60
encoderPinANow = digitalRead(encoderPinA);
61
62
if ((encoderPinALast == HIGH) && (encoderPinANow == LOW)) {
63
if (digitalRead(encoderPinB) == HIGH) {
64
encoderPos++;
65
} else {
66
encoderPos--;
67
}
68
Serial.println(encoderPos);
69
}
70
71
encoderPinALast = encoderPinANow;
72
73
}
Ausgabe:
1
10:59:56.006 -> 1
2
10:59:58.028 -> 2
3
11:00:00.315 -> 3
4
11:00:03.199 -> 4
5
11:00:11.991 -> 5
6
11:00:13.915 -> 6
7
11:00:15.539 -> 7
8
11:00:16.565 -> 8
9
11:00:16.930 -> 7
10
11:00:19.052 -> 8
11
11:00:20.179 -> 9
12
11:00:21.107 -> 10
13
11:00:21.305 -> 9
14
11:00:21.835 -> 10
15
11:00:21.901 -> 11
16
11:00:22.001 -> 12
17
11:00:22.100 -> 13
18
11:00:22.828 -> 14
19
11:00:22.896 -> 15
20
11:00:22.962 -> 16
21
11:00:22.962 -> 17
22
11:00:22.994 -> 18
23
11:00:23.094 -> 19
24
11:00:23.161 -> 20
25
11:00:23.858 -> 21
26
11:00:23.925 -> 22
27
11:00:23.991 -> 23
28
11:00:24.057 -> 24
29
11:00:24.123 -> 25
30
11:00:24.222 -> 26
31
11:00:24.289 -> 27
32
11:00:24.322 -> 26
33
11:00:25.020 -> 27
34
11:00:25.086 -> 28
35
11:00:25.120 -> 29
36
11:00:25.218 -> 30
37
11:00:25.218 -> 31
38
11:00:25.218 -> 32
39
11:00:25.252 -> 33
40
11:00:25.285 -> 34
41
11:00:25.352 -> 35
42
11:00:26.148 -> 36
43
11:00:26.248 -> 37
44
11:00:26.347 -> 38
45
11:00:26.381 -> 39
46
11:00:26.481 -> 40
47
11:00:27.310 -> 41
48
11:00:27.377 -> 42
49
11:00:27.410 -> 43
50
11:00:27.443 -> 44
51
11:00:27.477 -> 45
52
11:00:27.544 -> 46
53
11:00:27.577 -> 47
54
11:00:27.643 -> 48
55
11:00:29.101 -> 49
56
11:00:29.366 -> 50
57
11:00:29.400 -> 51
58
11:00:29.466 -> 52
59
11:00:29.466 -> 53
60
11:00:29.500 -> 54
61
11:00:29.533 -> 55
62
11:00:29.567 -> 56
63
11:00:29.567 -> 57
64
11:00:29.670 -> 58
65
11:00:30.932 -> 57
66
11:00:30.965 -> 56
67
11:00:30.999 -> 55
68
11:00:31.032 -> 54
69
11:00:31.065 -> 53
70
11:00:31.133 -> 52
71
11:00:31.199 -> 51
72
11:00:31.232 -> 52
73
11:00:31.266 -> 51
74
11:00:31.299 -> 50
75
11:00:31.928 -> 49
76
11:00:31.961 -> 48
77
11:00:31.994 -> 47
78
11:00:32.028 -> 46
79
11:00:32.092 -> 45
80
11:00:32.092 -> 44
81
11:00:32.126 -> 43
82
11:00:32.126 -> 42
83
11:00:32.192 -> 41
84
11:00:32.690 -> 40
85
11:00:32.756 -> 39
86
11:00:32.790 -> 38
87
11:00:32.823 -> 37
88
11:00:32.957 -> 36
89
11:00:33.488 -> 35
90
11:00:33.520 -> 34
91
11:00:33.553 -> 33
92
11:00:33.588 -> 32
93
11:00:33.622 -> 31
94
11:00:33.687 -> 30
95
11:00:34.117 -> 29
96
11:00:34.150 -> 28
97
11:00:34.185 -> 27
98
11:00:34.185 -> 26
99
11:00:34.185 -> 25
100
11:00:34.217 -> 24
101
11:00:34.251 -> 23
102
11:00:34.284 -> 22
103
11:00:34.681 -> 21
104
11:00:34.715 -> 20
105
11:00:34.748 -> 19
106
11:00:34.781 -> 18
107
11:00:34.813 -> 17
108
11:00:34.847 -> 16
109
11:00:34.913 -> 15
110
11:00:35.279 -> 14
111
11:00:35.346 -> 13
112
11:00:35.378 -> 12
113
11:00:35.412 -> 11
114
11:00:35.412 -> 10
115
11:00:35.445 -> 9
116
11:00:35.445 -> 8
117
11:00:35.477 -> 7
118
11:00:35.512 -> 6
119
11:00:35.942 -> 5
120
11:00:35.977 -> 4
121
11:00:36.008 -> 3
122
11:00:36.041 -> 2
123
11:00:36.075 -> 1
124
11:00:36.107 -> 0
125
11:00:36.173 -> -1
126
11:00:36.738 -> -2
127
11:00:36.805 -> -3
128
11:00:36.838 -> -4
129
11:00:36.905 -> -5
130
11:00:36.971 -> -6
131
11:00:37.004 -> -7
132
11:00:37.070 -> -8
133
11:00:37.169 -> -9
134
11:00:37.269 -> -10
135
11:00:41.413 -> -9
136
11:00:41.479 -> -8
137
11:00:41.545 -> -7
138
11:00:41.578 -> -6
139
11:00:41.678 -> -5
140
11:00:41.744 -> -4
141
11:00:41.811 -> -3
142
11:00:41.844 -> -2
143
11:00:41.910 -> -1
144
11:00:41.942 -> 0
145
11:00:41.976 -> 1
146
11:00:42.042 -> 2
147
11:00:42.077 -> 3
148
11:00:43.369 -> 4
149
11:00:43.534 -> 3
150
11:00:45.091 -> 4
151
11:00:45.754 -> 5
152
11:00:46.416 -> 6
153
11:00:47.011 -> 7
Auch hier das problem weiterhin.
jetzt muss ich diesem Hinweis mal nachgehen:
Stefan ⛄ F. schrieb:> Die Interrupt Handler doEncoderA() und doEncoderB() fragen den Encoder> mit Entprellung ab, aber das Hauptprogramm (loop) fragt die Eingänge A> und B erneut direkt (ohne Entprellung) ab.
ALso nicht nur lernen den Interrupt vernünftig zu entprellen sondern
auch in der loop.
Kilo S. schrieb:> ALso nicht nur lernen den Interrupt vernünftig zu entprellen sondern> auch in der loop.
Die doppelte Abfrage des Encoders scheint mir allerdings äußerst
fragwürdig.
Lothar hat einen guten Ansatz beschrieben. Dazu muss das gesamte
Programm in seinen Grundzügen umgebaut werden. Aber ich denke der
Aufwand wird sich lohnen.
Stefan ⛄ F. schrieb:> Lothar hat einen guten Ansatz beschrieben. Dazu muss das gesamte> Programm in seinen Grundzügen umgebaut werden. Aber ich denke der> Aufwand wird sich lohnen.
Ja, nach ein wenig testen denke ich es ist sogar nur Hilfreich wenn ich
das ganze nochmal neu angehe.
Ich versuche im kopf schon eine halbwegs vernünftige struktur zu finden.
Stefan ⛄ F. schrieb:> Die doppelte Abfrage des Encoders scheint mir allerdings äußerst> fragwürdig.
Ja, bin ich ganz bei dir.
Ich hab nur noch keinen plan wie genau ich das lösen soll.
Im moment nutze ich ja die Pinabfrage noch zum bestimmen ob der Zahler
arbeiten soll.
Meine erste idee wäre im Interrupt eine weitere variable zu setzen und
diese abzufragen, erscheint mir aber nicht ganz so elegant wie die
rückgabe des interrupt direkt auszuwerten. Allerdings muss ich mir da
erst was überlegen.
für die Encoder gibt es doch DIE Routine von P. Dannegger die auch
selbst mit den billigen ALPS Encodern klarkommt, findet man hier über
die SuFu.
Den Stepper würde ich durch AccelStepper ersetzen. Da muss die
Arbeitsroutine auch in einer Loop aufgerufen werden und sollte nicht
zulange durch das Display verzögert werden. Wenn das ruckelt kann man
den AccelStepper.run evtl im Timer Interrupt aufrufen. Beispiele ansehen
wie in dem anderen Thread schon gesagt.
J. S. schrieb:> für die Encoder gibt es doch DIE Routine von P. Dannegger die auch> selbst mit den billigen ALPS Encodern klarkommt, findet man hier über> die SuFu.
Fürs erste würde ich das mit dem encoder gerne per hand machen, hat den
ganz einfachen grund das eben dieses "Libs Zusammenklicken" nur halbwegs
läuft und ich so auch besser und schneller in die sprache einsteige.
Nun hab ich mir für einen Test mal diesen code angesehen:
1
#define ClockPin 2 // Must be pin 2
2
#define DataPin 3 // Must be pin 3
3
#define readA bitRead(PIND,2)//faster than digitalRead() (((value) >> (bit)) & 0x01)
4
#define readB bitRead(PIND,3)//faster than digitalRead() (((value) >> (bit)) & 0x01)
Der ist auf alle fälle besser.
Er zahlt einzelne schritte bei relativ hoher geschwindigkeit ganz
ordentlich, macht aber ab und zu (fehlende entprellung) vor/rück sprünge
und überspringt auch mehrer dabei.
Er zählt auch einzelne schritte bei langsamer drehung, dabei überspringt
er aber ab und zu schritte (auch mehrere) und macht häufiger vor/rück
sprünge.
Allerdings ist der teils recht leicht zu kapieren und Zahlt annährend
wie gewünscht.
Elegant und anscheinend schnell gelöst durch das integrieren des counter
direkt in die definition des interrupt über eine verschachtelte if
abfrage!
Hier mal die ausgabe "Langsam":
1
13:05:37.526 -> -1
2
13:05:38.521 -> 0
3
13:05:39.218 -> -1
4
13:05:39.881 -> 0
5
13:05:40.545 -> -1
6
13:05:41.141 -> 0
7
13:05:41.175 -> 1
8
13:05:41.175 -> 2
9
13:05:41.175 -> 3
10
13:05:41.175 -> 4
11
13:05:42.269 -> 3
12
13:05:44.356 -> 4
13
13:05:44.389 -> 5
14
13:05:44.389 -> 8
15
13:05:44.389 -> 9
16
13:05:44.986 -> 8
Schnell:
1
13:06:13.977 -> 7
2
13:06:13.977 -> 8
3
13:06:14.010 -> 9
4
13:06:14.010 -> 8
5
13:06:14.043 -> 9
6
13:06:14.076 -> 10
7
13:06:14.076 -> 12
8
13:06:14.076 -> 13
9
13:06:14.076 -> 14
10
13:06:14.076 -> 15
11
13:06:14.076 -> 16
12
13:06:14.076 -> 15
13
13:06:14.109 -> 16
14
13:06:14.109 -> 18
15
13:06:14.142 -> 20
Jetzt fehlt mir noch eine möglichkeit neben der if das entprellen im
interrupt unterzubringen.
Bzw. ich vermute das es in den interrupt gehört um die loop nicht
unnötig langsamer zu machen?
Encoder per ISR führt hier regelmässig zum Krieg...
keine Lib, ein paar Zeilen C-Code, den man natürlich auch in eine C++
Klasse packen kann.
https://www.mikrocontroller.net/articles/Drehgeber
und da die Variante mit 'wackeligen Rastpunkten' wenn es einer der
billigen Encoder ist. Gute optische Encoder funktionieren aber durchaus
mit den Interrupts.
Kilo S. schrieb:> Bzw. ich vermute das es in den interrupt gehört um die loop nicht> unnötig langsamer zu machen?
Es ist im Grunde schurzegal wie langsam die Mainloop ist. Wenn sie "zu
langsam" ist, dann musst du die Ursache dafür halt suchen und und
beheben(**).
Aber in einen Interrupt gehört so wenig wie möglich, am besten nur das,
was nötig ist, um die Information, die du im Interrupt gewinnen kannst,
hinterher in der Mainloop abarbeiten zu können.
So wie wenn du grade Milch kochst und es klingelt der Postbote,
unterbricht diese Arbeit (Unterbrechung = Interrupt) und bringt einen
Brief von Tante Erna, die darum bittet, dass du sie mal besuchst.
Sinnigerweise rennst du dann nicht gleich los und fährst zur Tante,
sondern du nimmst den Brief entgegen und legst ihn auf den Tisch, und
gehst dann schnellstmöglich zurück zur Milch, um dein Porridge fertig zu
kochen. Und nach dem Essen (der Brei soll ja nicht kalt werden) kannst
du dir mal ansehen, was die Tante geschrieben hat.
(**) Meist sind das dann so Dinger, wo unnötigerweise auf irgendwas
gewartet wird. Da ist es dann besser, zu schauen, ob die Hardware schon
fertig ist und wenn nicht mit der noormalen Tätigkeit weiter zu machen.
So wie du ja auch nicht 2 Stunden vor die Waschmaschine hockst, sondern
bestenfalls zwischendurch mal nachschaust, ob die schon fertig ist.
Lothar M. schrieb:> Es ist im Grunde schurzegal wie langsam die Mainloop ist.
Ach, wenn das ganze einfach nur wie gewünscht einen schritt pro
rastpunkt in sagen wir einer sekunde abarbeitet ohne fehler oder sprünge
und dazwischen noch meine Relais schalten kann, bin ich völlig
zufrieden.
J. S. schrieb:> Gute optische Encoder funktionieren aber durchaus> mit den Interrupts.
Irgendwo hab ich bestimmt noch eine defekte maus wo sogar ein Optischer
drin sein könnte.
Der encoder steht zur debatte, ich hab keine schmerzen den
auszutauschen.
Update von mobil aus:
Wenn ich zurück bin probiere ich das entprellen in der loop aus.
Das sollte ja mit millis wie bei meinem Versuch davor funktionieren.
OK! Mooooooooment.
ich muss eben mal prüfen ob eventuell ein Hardware defekt (Encoder)
vorliegt!
Gleicher Code wie Vorher, Arduino eingestöpselt und der zählt nur noch
hoch aber runter geht nicht mehr?..
Kilo S. schrieb:> Jetzt fehlt mir noch eine möglichkeit neben der if das entprellen im> interrupt unterzubringen.
Was hast du immer mit deinem Entprellen?
Der Encoder gibt Gray-Code aus und der ist von Natur aus resistent gegen
Prellen. Die Kondensatoren sind dort genauso überflüssig. Frage das Ding
einfach mit einem Timer ab, der ausreichend schnell taktet, damit kein
Zustand übersehen wird.
Wolfgang schrieb:> Was hast du immer mit deinem Entprellen?> Der Encoder gibt Gray-Code aus und der ist von Natur aus resistent gegen> Prellen. Die Kondensatoren sind dort genauso überflüssig. Frage das Ding> einfach mit einem Timer ab, der ausreichend schnell taktet, damit kein> Zustand übersehen wird.
Hab ich ja bereits probiert. Funktionierte genauso schlecht wie meine
eigene Lösung. Die Lib die angeblich jeden encoder packt weil sie
Greycode und Statemachine verwendet...
Ist mir eigentlich auch egal!
Scheint als habe das Forum meinen letzten Post verschluckt.
Aber kurz dazu: Laptop Zugemacht, mit meiner Frau kurz die Tante
besuchen...
Arduino wieder angesteckt und der scheiß zählt plötzlich nur noch hoch
und nicht mehr runter.
Mein erstes Programm hingegen zählt hoch und runter. Die Hardware ist
also OK!
Und jetzt erkläre mir mal ohne Änderungen am Code wieso der vorher
funktionierende Code plötzlich NICHT MEHR funktioniert.
Und ja ich habe mehrere Adruinos (2) und bei beiden verhält es sich
gleich!
Ich kam nicht Mal zu dem Versuch etwas zu entprellen weil nichts mehr
richtig gelesen wird. Es wurde NICHTS anderes gemacht als ein mal USB
Abstecken und wieder anstecken!...
Probe aufs Exempel:
Hab gerade extra eine alte Maus zerlegt und dessen Encoder für das
Mausrad (kein optischer) anstelle meines verwendet.
Gleiches verhalten!
Was kann sich da plötzlich verändert haben?
Nochmals gegengetestet!
Der encoder aus einer Logitech G19, da er aus meinem Ersatzteilfundus
stammt und ich garantieren kann das er funktioniert ist es jetzt
offensichtlich der China Nano?
Je nach dem, manchmal nach dem neu anstecken am PC Klappt's, es werden
beide Drehrichtungen erkannt, aber hauptsächlich nicht. Dann zählt er
nur in die am Anfang verwendete Richtung...
Kilo S. schrieb:> void setup() {> Serial.begin(9600); //9600> pinMode(ClockPin, INPUT);> pinMode(DataPin, INPUT);
Also wenn das der letzte, aktuelle sourcecode ist,
da fehlt mir so ein ganz kleines bisschen Pull-Up.
Norbert schrieb:> Also wenn das der letzte, aktuelle sourcecode ist,> da fehlt mir so ein ganz kleines bisschen Pull-Up.
Stimmt, die fehlen.
Aber dann hätte es doch von Anfang an eigentlich nicht funktionieren
dürfen?!
Nun, ich hab gerade getestet..._PULLUP hinzugefügt.
Bringt auch keine Besserung.
Uwe K. schrieb:> Versuche es doch mal damit:
Nein, weil:
Kilo S. schrieb:> Fürs erste würde ich das mit dem encoder gerne per hand machen, hat den> ganz einfachen grund das eben dieses "Libs Zusammenklicken" nur halbwegs> läuft und ich so auch besser und schneller in die sprache einsteige.
Außerdem will ich wissen wieso das vorher funktionierende Programm
plötzlich nicht mehr will!
Benutzt du ein Steckbrett und/oder Dupont Kabel?
Wenn ja, ersetze alle Verbindungen durch gelötete Kupferlitzen.
Hast du einen Logic Analyzer?
Wenn nicht, besorge dir einen. Der billigste ist besser als keiner.
Kilo S. schrieb:> Uwe K. schrieb:>> Versuche es doch mal damit:>> Nein, weil:>> Kilo S. schrieb:>> Fürs erste würde ich das mit dem encoder gerne per hand machen, hat den>> ganz einfachen grund das eben dieses "Libs Zusammenklicken" nur halbwegs>> läuft und ich so auch besser und schneller in die sprache einsteige.>> Außerdem will ich wissen wieso das vorher funktionierende Programm> plötzlich nicht mehr will!
Ich empfehle dir, auf den Link zu klicken und mal in die Library
reinzuschauen. Versuche diese zu verstehen. Es sind nur ein paar
Coding-Zeilen ohne Wudu. Es ist nicht die PeDa-Routine. Danach hast Du
die Möglichkeit es von Hand mit deinem eigenen Coding umzusetzen. Es ist
garantiert prellfrei und kann auch per Interrupt aufgerufen werden. Gebe
der Idee wenigstens eine Chance.
Stefan ⛄ F. schrieb:> Benutzt du ein Steckbrett und/oder Dupont Kabel?
Nein, ich hab das gewackelt damit satt . Es ist bereits alles gelötet.
Da ich aktuell auch keine Verbindung zum Display oder dem ULN2003
brauche hab ich diese auch Gerade nicht abgeschlossen. Es ist nur der
Encoder verbunden.
Stefan ⛄ F. schrieb:> Hast du einen Logic Analyzer?> Wenn nicht, besorge dir einen. Der billigste ist besser als keiner.
Nein, wird aber bald angeschafft.
Allerdings Frage ich mich wie mir in diesem Fall ein Logic Analyzer
helfen soll, es würde ja nichts verändert.
Außerdem ist ja der Witz das es beim anstecken ab und an auch mal wieder
funktioniert, und dann beim weiteren testen einfach plötzlich nicht mehr
beide Richtungen erkennen kann.
Interessant auch das mein erstes Programm ja genauso wie vorher auch
zählt.
Kilo S. schrieb:> Außerdem will ich wissen wieso das vorher funktionierende Programm> plötzlich nicht mehr will!
Warum bist du dir so sicher, dass der Fehler in der Software ist?
Kilo S. schrieb:> PULLUP hinzugefügt.> Bringt auch keine Besserung
Irgendwie ist diese Vorgehensweise arg planlos.
So ähnlich wie Topfschlagen beim Kindergeburtstag. Nur mit einer kleinen
Änderung: auch die, die Tipps geben, haben eine Augenbinde auf...
Kilo S. schrieb:> es würde ja nichts verändert.
Wenn es die selbe Software ist und die selbe Schaltung und auch sonst
nirgends was geändert wurde, dann muss das ein Wunder sein. Glaubst du
an Wunder? Wenn nicht, dann mach dich strukturiert auf die Fehlersuche:
Schreib ein Programm, das die Portpins einliest und auf anderen Portpins
wieder ausgibt. Miss die Spannungen. Passt das alles zusammen und zu den
Datenblattangaben?
beim rumprobieren passiert es schnell das man etwas im Code verbiegt und
danach übersieht.
Ich empfehle da wärmstens sich mit git zu beschäfftigen und einfach
häufig commits zu machen. Damit sind Änderungen zu vorherigen Versionen
sofort sichtbar.
Sehr gut ist die git Anbindung in VisualStudio Code. Auch wenn wann
weiter mit der simplen Arduino IDE arbeiten möchte geht das parallel. Im
Code Verzeichnis 'git init' ausführen bzw. in VSC F1, dann git initialze
Eintrag ausführen. Einmal einen commit mit allen Dateien machen und von
da sieht man die Änderungen mit einem Click.
Kilo S. schrieb:> Allerdings Frage ich mich wie mir in diesem Fall ein Logic Analyzer> helfen soll, es würde ja nichts verändert.
Du kannst damit überprüfen, ob die Signale vom Encoder richtig bzw. wie
erwartet aussehen. Es macht nicht allzu viel Sinn, stundenlang übe rden
Quelltext zu grübeln, wenn die Signale gar nicht dem entsprechen, wofür
der Code geschrieben wurde.
> Außerdem ist ja der Witz das es beim anstecken ab und an auch mal wieder> funktioniert, und dann beim weiteren testen einfach plötzlich nicht mehr> beide Richtungen erkennen kann.
Klingt nach Wackelkontakt. Auch den würdest du mit dem Logic Analyzer
schnell erkennen.
Da ich den Vorschlag mit Git sehr gut finde, hänge ich da mal meine
Einstiegs-Anleitung dran: http://stefanfrings.de/git/index.html
Uwe K. schrieb:> Ich empfehle dir, auf den Link zu klicken und mal in die Library> reinzuschauen. Versuche diese zu verstehen.
Ich soll jetzt anfangen zwei prachen zu lernen um dann am ende mit einer
Sprache zu programmieren?
Vor allem soll ich als Anfänger jetzt hingehen und den C Code für C++
anpassen?
Also C++ geht sogar Recht gut zu verstehen, wenn man bereits PHP kann,
Syntax ist ziemlich ähnlich bisher, nur kleine Unterschiede, C und vor
allem sowas wie diese "Lib" die zwar auch nur eine Funktion enthält
(zumindest interpretiere ich das so) bringt mir höchstens das ich gerade
wie der Ochse vorm Berg stehe weil ich nicht weiß wie ich diese
auswerten soll wenn Return immer 0 ist!
So... Reicht die Erklärung dafür dir zu zeigen das dein Vorschlag es
NICHT von 0 an selbst in der Sprache die man lernen möchte (ich muss das
nicht machen, ich möchte es!) in die falsche Richtung geht?
Ich möchte Arduino/C++ lernen, und mich nicht erst in C einarbeiten um
danach zu sehen (Google spuckt vieles aus wenn man nach "Convert C Code
zo C++ Class" sucht) das man dazu erst beide Sprachen können muss.
Mein Lieblingskommentar zu diesem thema: I would suggest using the same
strategy you'd use to eat an elephant: take it one bite at a time. :-)
Wenn man den Aufwand, C in funktionierenden C++ Code umzuschreiben mit
dem Essen eines Elefanten Vergleicht, fange ich das erst gar nicht an!
Vor allem macht es keinen Sinn, ich könnte das aktuell ja gar nicht
übersetzen weil ich so viel C++ noch gar nicht kann!
Kilo S. schrieb:> Ich soll jetzt anfangen zwei Sprachen zu lernen?> Ich möchte Arduino/C++ lernen, und mich nicht erst in C einarbeiten
Wenn du C++ kannst, dann hast du 99% von C ganz nebenbei mit gelernt.
Und Arduino ist sowieso eine wilde Mischung aus beidem.
> Wenn man den Aufwand, C in funktionierenden C++ Code umzuschreiben mit> dem Essen eines Elefanten Vergleicht, fange ich das erst gar nicht an!
Ich habe meine LCD Bibliothek zuerst in Plain C (kein Arduino)
geschrieben, und dann nach Arduino/C++ portiert. Die Portierung dauerte
samt Dokumentation und Test nicht einmal einen Tag. Also übertreibe mal
nicht.
Stefan ⛄ F. schrieb:> Du kannst damit überprüfen, ob die Signale vom Encoder richtig bzw. wie> erwartet aussehen. Es macht nicht allzu viel Sinn, stundenlang übe rden> Quelltext zu grübeln, wenn die Signale gar nicht dem entsprechen, wofür> der Code geschrieben wurde.
Wackelkontakt kann ich ausschließen, da mein erster Versuch (erster
Beitrag) mit allen drei encodern zählt kann ich Defekte Hardware auch
ausschließen.
J. S. schrieb:> beim rumprobieren passiert es schnell das man etwas im Code verbiegt und> danach übersieht.
Nochmal, falls es überlesen würde: ich hab gestern das USB Kabel
abgezogen, den Laptop zugeklappt, war kurz weg, kam wieder, klappte den
Laptop auf, steckte das USB Kabel ein und ab dann ging schon der ganze
Blödsinn los.
Es gab KEINE Änderungen an Hard oder Software, nicht mal ein Leerzeichen
zusätzlich im Code, auch wenn ich das Funktionierende Beispiel ( Encoder
Testcode) hier aus dem Beitrag in einen leeren Sketch kopiere und
hochlade (läuft alles fehlerfrei durch) ergibt sich das gleiche
verhalten.
Auch speichere ich Funktionierende Sketches zur Sicherheit immer doppelt
ab bevor ich anfange Änderungen zu machen. Git brauche ich dafür nicht.
Stefan ⛄ F. schrieb:> Da ich den Vorschlag mit Git sehr gut finde, hänge ich da mal meine> Einstiegs-Anleitung dran: http://stefanfrings.de/git/index.html
Nett von dir, ich richte mir aber sicher kein lokales git ein, dessen
Nutzung ich dann auch noch lernen muss.
Als ich vor 19! Jahren mit PHP anfing hab ich auch kein Git gehabt,
Phase5 und XAMPP haben gereicht. In dem Fall kannst du Phase5 mit der
Arduino IDE ersetzen und XAMPP mit dem Compiler.
Einziger Unterschied, ich hatte die Sprachreferenz als Offlineversion
auf dem Rechner und es war leichter nachzuschlagen als aktuell bei
Arduino.
Kilo S. schrieb:> Es gab KEINE Änderungen an Hard oder Software
Also doch Wunder. Da können wir dir nicht helfen, das ist eher der
Fachbereich der Katholischen Kirche.
> Nett von dir, ich richte mir aber sicher kein lokales git ein
Brauchst du auch nicht. Man kann Git ohne Server und ohne zentrales
Repository nutzen. Schade dass du nicht einmal die ersten Absätze der
Anleitung gelesen hast.
> Als ich vor 19! Jahren mit PHP anfing hab ich auch kein Git gehabt,
Ich auch nicht, aber heute entwickelt man aus gutem Grund mit diesem
oder ähnlichen Tools. Wenn du auf dem Stand von vor 19 Jahren stecken
bleiben willst, dann musst du konsequenterweise auch Arduino ablehnen.
Stefan ⛄ F. schrieb:> Also doch Wunder
Entweder das oder der China Nano (kam ja bereits öfter vor) ist am Ende
doch Defekt, was allerdings durch die Tatsache daß mein erster Versuch
funktioniert unwahrscheinlich ist.
Stefan ⛄ F. schrieb:> Brauchst du auch nicht. Man kann Git ohne Server und ohne zentrales> Repository nutzen. Schade dass du nicht einmal die ersten Absätze der> Anleitung gelesen hast.
Ob das nun als Serverdeamon, Programm oder sogar nur als Script läuft,
völlig irrelevant. Ich benötige es nicht um die Änderungen im Programm
nachzuvollziehen da ich mir immer Kopien des original als .Ino.old*n*
(n=int) speichere und danach erst Änderungen mache.
Und wenn so ein Projekt größer und unübersichtlich wird folgen auch
Kommentare, wie früher am Anfang von PHP. Aber bei 28 Zeilen Code wie im
Testprogramm, das einfach lesbar ist und das ich auch Recht gut
verstehen kann... Unnötig.
P.S
Ich lass gleich mal das Oszilloskop Warmlaufen, das pingewackel des
Encoder dürfte sich auch damit erkennen lassen.
Stefan ⛄ F. schrieb:> Ich auch nicht, aber heute entwickelt man aus gutem Grund mit diesem> oder ähnlichen Tools. Wenn du auf dem Stand von vor 19 Jahren stecken> bleiben willst, dann musst du konsequenterweise auch Arduino ablehnen.
Das hat doch damit nichts zu tun.
Git mag für manche ein mittel der Wahl sein, ich sehe nur für mich als
einzelnen keinen Vorteil es zu nutzen.
Du darfst allerdings gerne ein wirklich gutes Beispiel nennen wo man das
als einzelner programmierer unbedingt benötigt um seinen eigenen von
niemand sonst veränderten Code nachzuvollziehen.
Kilo S. schrieb:> Ich soll jetzt anfangen zwei prachen zu lernen um dann am ende mit einer> Sprache zu programmieren?
FYI:
du benutzt schon einen Mischmasch aus C/C++:
1
SteppermyStepper(stepsPerRevolution,8,9,10,11);
2
LiquidCrystal_I2Clcd(0x27,20,4);
3
4
myStepper.setSpeed(10);
5
lcd.init();
6
lcd.backlight();
7
lcd.clear();
das gibt es in C nicht.
Kilo S. schrieb:> Außerdem will ich wissen wieso das vorher funktionierende Programm> plötzlich nicht mehr will!
Code der Scheiße ist kann auch einfach zufällig funktionieren wenn die
Randbedingungen gerade passen.
Kilo S. schrieb:> Ob das nun als Serverdeamon, Programm oder sogar nur als Script läuft,> völlig irrelevant.
Es muss gar nichts laufen! Du erstellst Schnappschüsse wann du willst.
Und nur dann läuft das Programm kurzzeitig. Vergleiche es mit Winzip.
Jeder Schnappschuss ist ein komprimiertes Archiv, das in ".git"
Unterverzeichnis abgelegt wird. Nur das Dateiformat ist halt ein
anderes.
> Ich benötige es nicht um die Änderungen im Programm> nachzuvollziehen da ich mir immer Kopien des original> als .Ino.old*n* (n=int) speichere und danach erst Änderungen mache.
Kannst du auch machen. Ja, dann brauchst du kein Git. Aber ein Tool,
dass Unterschiede vergleicht wäre dann hilfreich. Falls du noch keins
hast, für Windows empfehle ich WinMerge.
Einen Vorteil von Git kann ich dir für deinen Fall nennen: Wenn du eine
Zeile Code vor dir hast wo du denkst "die war mal anders" aber du kannst
dich nicht mehr an das Datum erinnern, dann kann dir die IDE dank Git
Integration automatisch heraus suchen, wann du sie geändert hast und
was du geändert hast.
Vermutlich brauchst du das nur selten, so dass eine manuelle Suche
ebenfalls akzeptabel ist. Spannender wird das Feature, wenn mehrere
Personen am Projekt arbeiten.
J. S. schrieb:> FYI:> du benutzt schon einen Mischmasch aus C/C++:
Allerdings einen Mischmasch der leichter zu verstehen ist als reines C.
J. S. schrieb:> Code der Scheiße ist kann auch einfach zufällig funktionieren wenn die> Randbedingungen gerade passen.
Naja, ein Blanker Arduino, drei Stücke Litze und ein encoder sind jetzt
nicht sonderlich viel an dem man die Randbedingungen verändern kann.
Übrigens ist das Ergebnis mit oder ohne Kondensatoren das gleiche, die
hab ich also auch wieder entfernt. Allerdings erst nach dem der Fehler
aufgetreten ist und dann auch erst sehr spät.
Aber: Wo ist der Code bis auf das er eben "Springt" beim zählen scheiße?
Solch verschachtelte Konstrukte wie die Funktion des Counter in den
interrupt zu legen sprechen eigentlich dafür das man die Sprache ganz
gut drin hat.
Ich hab solche verschachtelten If abfragen in PHP auch erst genutzt als
ich schon flüssig ohne viel nachdenken programmiern könnte.
Theoretisch sind die nämlich eigentlich "Schlechter Stil", da nur von
Leuten lesbar und nachvollziehbar die solche Konstrukte selbst Einsetzen
bzw. diese Schreibweise einer If auch verstehen.
Das erste Programm enthält so etwas ähnliches wie Entprellung alleine
schon deswegen, weil nach jedem Dreh-Schritt eine LCD Ausgabe gemacht
wird. Die verkürzten Programme fragen den Encoder schneller ab und
reagieren daher auch empfindlicher auf Kontaktprellen.
Stefan ⛄ F. schrieb:> Aber ein Tool, dass Unterschiede vergleicht wäre dann hilfreich.
Linuxer, diff. ;-)
Stefan ⛄ F. schrieb:> Vermutlich brauchst du das nur selten, so dass eine manuelle Suche> ebenfalls akzeptabel ist. Spannender wird das Feature, wenn mehrere> Personen am Projekt arbeiten.
Ja, am ende ist mir tatsächlich das Datum der Änderung egal. Das ist
auch das schöne, da ich immer eine Kopie vom funktionierenden Code als
Backup habe, kann ich auch wenn ich mich ganz verrennen sollte (gab's
auch bei PHP oft) einfach nochmal anfangen.
Bei PHP hatte ich immer folgende Struktur:
Main:
-backup
-working
-progress
-running_online
Backup ist selbsterklärend.
Working ist das Verzeichnis für die funktionierenden Dateien gewesen.
Progress war sozusagen die 1:1 Kopie von working, allerdings mein
"Hauptverzeichnis" zum Arbeiten am Code.
running_online lief dann am ende auf dem echten Server. Das war immer
"latest Working", und Working und Backup hatten bei mir immer den
Anspruch "Stable" zu sein. Auf Progress hab ich sogar im IRC extra Leute
geärgert und freiwillig und vollen Bewusstseins das es echt in die Hose
gehen kann dafür gesorgt das die meinen "Exposed Host" (ja, ich habe
einen XAMPP/Apache online gelassen! Später allerdings auch nur noch
unter Linux und als ich die Administration auch wirklich unter Kontrolle
hatte.) ordentlich Maltertieren.
Gratis Pentest. ;-)
Geile Zeit! Könnte man heute nicht mehr machen.
Und so in der Art wollte ich das eben mit Arduino auch machen. Nur eben
Backup, Working, Progress und aus Backup (=Working Stable) wird dann
"Running". Ich rationalisiere eben einen Ordner weg.
Der Mensch ist eben Gewohnheitstier.
Stefan ⛄ F. schrieb:> Das erste Programm enthält so etwas ähnliches wie Entprellung alleine> schon deswegen, weil nach jedem Dreh-Schritt eine LCD Ausgabe gemacht> wird. Die verkürzten Programme fragen den Encoder schneller ab und> reagieren daher auch empfindlicher auf Kontaktprellen.
Ja, interessant ist das es so scheint als sei das Schreiben (trotz
lahmen lcd.clear () ) des Display noch nicht genügend entprellung um
Sprünge zu Vermeiden.
Das verkürzte Programm ergänze ich gleich noch mal. Allerdings bin ich
nicht sicher ob das so greift, millis und interrupt mögen sich nicht.
Stefan ⛄ F. schrieb:> Kilo S. schrieb:>> Linuxer, diff.>> Ach so. Für Linux empfehle ich Meld.
;-) Auch.
Kilo S. schrieb:> Das verkürzte Programm ergänze ich gleich noch mal. Allerdings bin ich> nicht sicher ob das so greift, millis und interrupt mögen sich nicht.
Hier mal eine (Quick&Dirty) testversion.
Allerding genauso funktionsunfahig in beide richtungen zu zählen.
gefühlt scheint es aber zu funktionieren, weniger sprünge egal ob langam
oder schnell am encoder drehen.
1
#define ClockPin 2 // Must be pin 2
2
#define DataPin 3 // Must be pin 3
3
#define readA bitRead(PIND,2)//faster than digitalRead() (((value) >> (bit)) & 0x01)
4
#define readB bitRead(PIND,3)//faster than digitalRead() (((value) >> (bit)) & 0x01)
Mir leuchtet überhaupt nicht ein, warum du für den Data Pin einen
Interrupt-Handler einrichtest. Du fragst doch schon in der ISR für den
Takt den Data-Pin ab, und entscheidest dementsprechend, ob du hoch oder
runter zählst.
Warum duplizierst du den selben Code nochmal mit dem Data-Pin? Damit
reagierst du auf jeden Dreh-Schritt doppelt.
Eine Entprellung ist da nur schwer rein zu bekommen, das hast du ja
selbst schon gemerkt. Folge doch besser dem Vorschlag von Lothar, die
Pins in einem Timer-Interrupt abzufragen.
Stefan ⛄ F. schrieb:> Mir leuchtet überhaupt nicht ein, warum du für den Data Pin einen> Interrupt-Handler einrichtest. Du fragst doch schon in der ISR für den> Takt den Data-Pin ab, und entscheidest dementsprechend, ob du hoch oder> runter zählst.
Krieg ich keine logik für in den kopf...
Wie will ich denn die drehrichtung erkennen wenn ich nicht weiß ob data
nun vor oder nach Takt high oder low war. Ein pin zum zählen, einer für
die Richtungserkennung.
Kilo S. schrieb:> Wie will ich denn die drehrichtung erkennen wenn ich nicht weiß ob data> nun vor oder nach Takt high oder low war.
Data und Clock ändern sich nie gleichzeitig. Zum Zeitpunkt des Taktes
hat die Data Leitung daher den gleichen Pegel, wie kurz davor und auch
kurz danach.
Aber nach wie vor möchte ich davon abraten, den Encoder auf diese Weise
abzufragen, denn es funktioniert so nur mit extern entprelltem
Taktsignal.
Siehe https://www.mikrocontroller.net/articles/Drehgeber
Stefan ⛄ F. schrieb:> Data und Clock ändern sich nie gleichzeitig. Zum Zeitpunkt des Taktes> hat die Data Leitung daher den gleichen Pegel, wie kurz davor und auch> kurz danach.
Das beantwortet meine frage immer noch nicht, ich sehe keinen logischen
ansatz daraus eine verwertbare information zu gewinnen mit nur einem
pin.
Stefan ⛄ F. schrieb:> Folge doch besser dem Vorschlag von Lothar, die> Pins in einem Timer-Interrupt abzufragen.
Ist wieder so ein Lib scheißdreck!
https://www.arduino.cc/reference/en/libraries/timerinterrupt/
Kilo S. schrieb:> Das beantwortet meine frage immer noch nicht, ich sehe keinen logischen> ansatz daraus eine verwertbare information zu gewinnen mit nur einem> pin.
Von einem Pin war keine Rede, sondern von einem Interrupt. Löse bei
jeder Flanke an Clock einen Interrupt aus. In der Interruptroutine
fragst du wie gehabt ab, ob der Pegel von Data gleich dem Pegel von
Clock ist. Wenn ja, wurde links herum gedreht. Wenn nicht, wurde rechts
herum gedreht.
Aber:
Ich kann dir diese Methode nach wie vor nicht empfehlen, weil das so nur
mit extern entprelltem Takt zuverlässig funktioniert. Eine Entprellung
per Software lässt sich besser in eine periodische Abfrage per Timer
Interrupt unterbringen.
> Ist wieder so ein Lib scheißdreck!
Niemand hindert dich daran, von den wenigen Zeilen Code zu lernen und es
selbst zu programmieren. Du kannst es ja erst mal mit Clock-Interrupt
versuchen und später auf die komplexere Variante mit Entprellung zurück
kommen, wenn du mit dem Kontaktprellen konfrontiert wirst.
Hobby-Schaltungen müssen nicht von Anfang an perfekt sein. Learning by
doing, und mit kleinen Brötchen anfangen ist schon OK, wenn man die Zeit
dazu hat und kein Business oder Leben davon abhängt.
im mittlerweile mehrfach verlinkten Drehgeber Artikel ist simpler
C-Code, keine Lib.
Läauft auf dem Nano, hat den Nachteil der HW Abhängigkeit. Mit den
Arduino Lib Funktionen sollte es etwas portabler sein. Von daher ist
Nutzung von Timer und attachInterrupt nix Schlimmes.
Stefan ⛄ F. schrieb:> Niemand hindert dich daran, von den wenigen Zeilen Code zu lernen und es> selbst zu programmieren.
Alles gut, ich hab ja auch nur erwähnt das es eben wieder eine ist.
Stefan ⛄ F. schrieb:> Du kannst es ja erst mal mit Clock-Interrupt> versuchen und später auf die komplexere Variante mit Entprellung zurück> kommen, wenn du mit dem Kontaktprellen konfrontiert wirst.> Hobby-Schaltungen müssen nicht von Anfang an perfekt sein. Learning by> doing, und mit kleinen Brötchen anfangen ist schon OK, wenn man die Zeit> dazu hat und kein Business oder Leben davon abhängt.
Ja, ich lese mich gerade ein.
Wenn ich das richtig verstehe meint ihr also ich soll mit dem Timer
zyklisch die encoderabfrage laufen lassen und dessen rückgabewert
auswerten.
Gut, ich hab mir jetzt ein beispiel rausgesucht und versuche es
entsprechend anzupassen. Ich trottel such mir natürlich auch was aus wo
ich direkt am anfang erst mal Register und den ganzen kram lernen muss,
was einem bei Arduino ja eigentlich durch die vielen Libs abgenommen
wird. Ist jedenfalls eher selten anzutreffen habe ich den eindruck. ;-)
Naja, überlebenswichtig ist es nicht. Allerdings ein lang gehegter
"Wunsch" mir irgendwann mal eine steuerung für eine Magnetic Loop zu
bauen.
Aktuell ist es auch das einzig Praktikable am Funkhobby die steuerung zu
programmieren, außer mit kopfhörern am SDR lauschen.
Alles was Krach macht oder "Stinkt" (Löten) ist gerade nicht drin.
Heute ist meine Kleine Tochter genau 7 Tage alt, und jede sekunde ruhe
die sie schläft darf Papa und Mamma auch Ausruhen. ;-)
J. S. schrieb:> im mittlerweile mehrfach verlinkten Drehgeber Artikel ist simpler> C-Code, keine Lib.> Läauft auf dem Nano, hat den Nachteil der HW Abhängigkeit.
So weit ich die durchblickt habe ist es eine funktion deren rückgabewert
(jetzt hab ich's doch geblickt!) entweder 0, 1 oder -1 ist.
Auswertung wäre also;
0= Nichts ist passiert also mach auch nichts, 1= count++, -1 count--. So
weit so Logisch.
Ok, jetzt wo das (in C) durchblickt habe das es in der switch case doch
rückgabewerte gibt stellt sich mir die frage nach dem aufruf.
Die funktion selbst möchte (interpretation!) CLCK_PIN, DATA_PIN, reNum.
(Array Index?) übergeben haben.
Alles Ganzzahlen von 0-255, auch alles so weit so logisch, die pins am
encoder haben ja nur (eigentlich) nur 0 und 1, das prellen ist ja nur
der schnelle wechsel zwischen diesen zuständen.
Also, die funktion im Timer interrupt aufrufen, den rückgabewert
speichern und in der loop auswerten....
Ich hatte echt nicht gedacht das so was alltägliches (hat ja fast jeder
ein gerät zuhause das solch einen encoder nutzt) am ende doch so viel
"Softwareaufwand" beim lernen bedeutet.
P.S
Ja das mit dem Löten war leicht übertrieben, natürlich kann ich noch
Löten.
Allerdings zeitlich Begrenzt auf dem Balkon. ;-)
P.P.S
Eine "Libary" (rotaryEncode.h) enthält ja abgesehen von den nötigen
definitionen anderer "Libary’s" hauptsächlich funktionen. auch wenn .h
eigentlich "Header" sind...hmmm. Ja man mag sich über die definition
streiten.
Für mich definiere ich allerdings eine .h Datei die nur eine Funktion
enthält als "Lib/Libary".
Lothar M. schrieb:> Wenn es die selbe Software ist und die selbe Schaltung und auch sonst> nirgends was geändert wurde, dann muss das ein Wunder sein. Glaubst du> an Wunder? Wenn nicht, dann mach dich strukturiert auf die Fehlersuche:> Schreib ein Programm, das die Portpins einliest und auf anderen Portpins> wieder ausgibt. Miss die Spannungen. Passt das alles zusammen und zu den> Datenblattangaben?
Darauf möchte ich zusätzlich, nach reiflichem überlegen auch noch
antworten.
Es ist ja bekannt, das die "Chinaklone" nicht umbedingt immer top sind.
Also durchaus auch "Funktionierender Ausschuss" aus Chipfabriken (Was
eben als "Unverkäuflich" ausgemustert wird) aufgekauft, auf "Nano
Kompatible V3" Boards verkauft wird. Manchmal hilft es den Bootloader
neu zu brennen. Mal sind die Chips einfach Ausschuss, oder im besten
Fall Teil Funktional.
Durch meine eigene Motivation konnte ich ja ausschließen das es so ist.
Wie oft erlebt man hier das jemand sich echt den A**** aufgerissen hat
die Hardware auf eigene Faust zu prüfen weil er sich zwar sicher ist das
sie funktioniert, allerdings trotzdem in Betracht zieht das genau das
Gegenteil der Fall sein könnte?
Allerdings wir auch von "Wundersamen" verhalten bei manchen Boards
berichtet, eher älteren Datums, allerdings innerhalb der letzten 5-7
Jahre.
Ich weiß nicht mal wann ich mir die 2 für 5€ angeschafft habe, es sind
auch keine originale, daher ist eine Fehlfunktion (auch Beider Nano
Boards) therotetisch möglich gewesen.
Das meine versuche bisher ergeben haben das ich dies "ausschließen"
kann, es allerdings auch keiner von euch mit "Ähnlichem Encoder und Nano
Board" probiert hat den code auf "Neuer Legacy Hardware" zu testen....
Wer weiß, wer weiß!
Wunder..... Naja, nicht bei Elektronik. ;-)
Wäre echt cool wenn das jemand testen Könnte.
Kilo S. schrieb:> So weit ich die durchblickt habe ist es eine funktion deren rückgabewert> (jetzt hab ich's doch geblickt!) entweder 0, 1 oder -1 ist.> Auswertung wäre also;> 0= Nichts ist passiert also mach auch nichts, 1= count++, -1 count--. So> weit so Logisch.> Die funktion selbst möchte (interpretation!) CLCK_PIN, DATA_PIN, reNum.> (Array Index?) übergeben haben.
CLCK und DATA sind sehr unglückliche Bezeichnungen, da diese streng
genommen nicht stimmen. CLCK ist A und DATA ist B. Das "reNum" ist die
Nummer des Rotary Encoders, da die Funktion bis zu 8 Rotary Encoder
abfragen kann. Trage immer O ein, wenn es nur einer ist.
> Also, die Funktion im Timer Interrupt aufrufen, den rückgabewert> speichern und in der loop auswerten....
Den Rückgabewert solltest Du auf deinen Zähler Addieren. Deine Loop
könnte zu langsam sein.
1
encDelta+=rotaryEncode(PHASE_A,PHASE_B,0);
Wenn Du die Drehrichtung benötigt, dann speichere es in einen
Delta-Wert. und addiere diesen in der Loop. Beim Addieren, die
Interrupts mit CLI() ausschalten und danach mit SEI() wieder
einschalten.
Sonst direkt in deinen Zähler.
Diese Funktion darfst Du auch in Interrupt auswerten (beide Pins
brauchen ein Interrupt), da sie prellfrei ist. Muss man aber nicht.
> Ich hatte echt nicht gedacht das so was alltägliches (hat ja fast jeder> ein gerät zuhause das solch einen encoder nutzt) am ende doch so viel> "Softwareaufwand" beim lernen bedeutet.
Ja, das wird leicht unterschätzt besonders durch das Prellen und die
Rastung.
> P.P.S> Eine "Libary" (rotaryEncode.h) enthält ja abgesehen von den nötigen> definitionen anderer "Libary’s" hauptsächlich funktionen. auch wenn .h> eigentlich "Header" sind...hmmm. Ja man mag sich über die definition> streiten.> Für mich definiere ich allerdings eine .h Datei die nur eine Funktion> enthält als "Lib/Libary".
Formell ist es wohl nicht perfekt. Letztendlich habe ich nur eine
Funktion eingebaut. Durch RE_DETENT kann man den Rastpunkt einstellen.
Meist ist es 1. Ein Rastung durchläuft alle 4 Zustände. Bei 2 werden
zwei Zustande pro Rastung durchlaufen. Bei 4 ist keine Rastung vorhanden
(sehr selten bei Handgebern).
Es ist kein Problem, wenn Du die Funktion einfach in dein Programm
kopierst. Dann bist Du ohne Library. RE_DETENT solltest Du erstmal auf 1
stellen.
Kilo S. schrieb:> So weit so gut, bis auf die tatsache das immer noch nur in eine richtung> gezählt wird wie es scheint. ich teste weiter.
Probiers doch mal so, dass du nicht am Drehgeber drehst, sondern einfach
mit 2 Pullups und 2 Tastern definierte Pegel an A und B vorgibst. Denn
dann kannst du dauerhaft für einen stabilen high- oder low-Pegel an B
sorgen und am A beherzt herumtakten...
Ha, Kabelbruch!
Funktioniert! Ohne springen und fehler.
Das timing stimmt auch, 1 step/s packt das ganze.
Jetzt das ganze noch mit dem stepper zusammenbringen.
Kilo S. schrieb:> Ha, Kabelbruch!
Also doch eine andere Schaltung als ursprünglich.
Kilo S. schrieb:> Allerdings Frage ich mich wie mir in diesem Fall ein Logic Analyzer> helfen soll, es würde ja nichts verändert.
Du hättest sofort bei der 1. Messung am µC-Pin gesehen, dass sich da
nichts tut. Die Fehlerursache "Kabelbruch" hättest du dann 30s später
ganz von allein gefunden.
Lothar M. schrieb:> Also doch eine andere Schaltung als ursprünglich.
Nein! es ist genau das gleich wie vorher, drei kabel an denen ein
drehencoder hängt verbunden mit einem arduino. Das eins der kabel beim
hin und her räumen mal kaputt geht ist halt mal so...
Wie du auf so eine idee kommst erschließt sich mir nicht!
Lothar M. schrieb:> Du hättest sofort bei der 1. Messung am µC-Pin gesehen, dass sich da> nichts tut. Die Fehlerursache "Kabelbruch" hättest du dann 30s später> ganz von allein gefunden.
Schön, wie du siehst gings auch ohne ganz gut.
if ((encPinALast == HIGH) && (encPinANow == LOW)) {
45
if (digitalRead(encPinB) == HIGH) {
46
encPos++;
47
StepperPos =-s;
48
} else {
49
encPos--;
50
StepperPos = s;
51
}
52
}
53
encPinALast = encPinANow;
54
}
55
56
void loop() {
57
58
if (LastStepperPos != StepperPos) {
59
Serial.println("LastStepperPos");
60
Serial.println(LastStepperPos);
61
LastStepperPos = StepperPos;
62
Serial.println("StepperPos");
63
Serial.println(StepperPos);
64
myStepper.step(StepperPos);
65
StepperPos = 0;
66
}
67
68
}
An und für sich macht er einige schritte normal, danach springt er
abrupt zurück und macht wieder einige schritte normal.
Die ausgabe sieht für mich auch wie erwartet aus:
1
16:17:08.182 -> StepperPos
2
16:17:08.182 -> 0
3
16:17:08.779 -> LastStepperPos
4
16:17:08.779 -> 0
5
16:17:08.779 -> StepperPos
6
16:17:08.779 -> 1
7
16:17:08.812 -> LastStepperPos
8
16:17:08.812 -> 1
9
16:17:08.812 -> StepperPos
10
16:17:08.845 -> 0
11
16:17:09.044 -> LastStepperPos
12
16:17:09.044 -> 0
13
16:17:09.044 -> StepperPos
14
16:17:09.044 -> 1
15
16:17:09.077 -> LastStepperPos
16
16:17:09.077 -> 1
17
16:17:09.077 -> StepperPos
18
16:17:09.077 -> 0
19
16:17:09.276 -> LastStepperPos
20
16:17:09.276 -> 0
21
16:17:09.276 -> StepperPos
22
16:17:09.276 -> 1
23
16:17:09.309 -> LastStepperPos
24
16:17:09.309 -> 1
25
16:17:09.309 -> StepperPos
26
16:17:09.309 -> 0
27
16:17:10.668 -> LastStepperPos
28
16:17:10.668 -> 0
29
16:17:10.668 -> StepperPos
30
16:17:10.668 -> 1
31
16:17:10.701 -> LastStepperPos
32
16:17:10.701 -> 1
33
16:17:10.701 -> StepperPos
34
16:17:10.701 -> 0
35
16:17:10.999 -> LastStepperPos
36
16:17:10.999 -> 0
37
16:17:10.999 -> StepperPos
38
16:17:10.999 -> 1
39
16:17:11.032 -> LastStepperPos
40
16:17:11.032 -> 1
41
16:17:11.032 -> StepperPos
42
16:17:11.066 -> 0
43
16:17:11.895 -> LastStepperPos
44
16:17:11.895 -> 0
45
16:17:11.895 -> StepperPos
46
16:17:11.895 -> 1
47
16:17:11.928 -> LastStepperPos
48
16:17:11.928 -> 1
49
16:17:11.928 -> StepperPos
50
16:17:11.928 -> 0
51
16:17:12.127 -> LastStepperPos
52
16:17:12.127 -> 0
53
16:17:12.127 -> StepperPos
54
16:17:12.127 -> 1
55
16:17:12.160 -> LastStepperPos
56
16:17:12.160 -> 1
57
16:17:12.160 -> StepperPos
58
16:17:12.160 -> 0
59
16:17:12.459 -> LastStepperPos
60
16:17:12.459 -> 0
61
16:17:12.459 -> StepperPos
62
16:17:12.459 -> 1
63
16:17:12.492 -> LastStepperPos
64
16:17:12.492 -> 1
irgendwo hat sich ein "Logikteufel" eingeschlichen, ich seh ihn nur
nicht!
Stefan ⛄ F. schrieb:> Du hast keine Entprellung
Ich seh aber keine sprünge die das verhalten erklären würden und somit
auf ein prellen schliesen lassen.
Auch der Zähler selbst funktioniert ohne sprünge...
Kilo S. schrieb:> Ich seh aber keine sprünge die das verhalten erklären würden und somit> auf ein prellen schliesen lassen.
Zwei aufeinander folgende (prellende) Take an Pin A während Pin B nicht
prellt bewirkt, dass dein Zähler einmal herauf und dann wieder runter
zählt.
Beim Prellen können auch viel mehr Impulse entstehen.
Stefan ⛄ F. schrieb:> Zwei aufeinander folgende (prellende) Take an Pin A während Pin B nicht> prellt bewirkt, dass dein Zähler einmal herauf und dann wieder runter> zählt.
Wo siehst du da ein prellen?
Das sind zwei variablen, nicht eine. Der wechsel gleichzeitig ist
gewollt und auch richtig so.
Der timer lauft 50 mal pro sekunde durch und fragt ab, setzt den zahler
je nach richtung eins hoch oder runter und setzt StepperPos entweder auf
-1 oder 1. Es gibt kein "Prellen", StepperPos ist immer nur ein mal da
und der wert passt zur drehrichtung.
Kilo S. schrieb:> Wo siehst du da ein prellen?
Kontakte prellen halt, das liegt in deren Natur.
Ich denke wir haben dieses Thema oft genug angesprochen. Wenn du noch
irgendwelche Fragen dazu hast, lies deine Threads nochmal durch. Es
wurde bereits alles erklärt und Lösungen vorgeschlagen.
Uwe K. schrieb:> Versuche mal die Interrupts bei der Abfrage zu sperren.
Guter Hinweis. Während die erste Hälfte der int Variable (also 8 von 16
Bit) gelesen wird könnten sich nämlich die anderen (via Interrupt)
ändern und dann passen die 2 Bytes nicht mehr zusammen. Da er die
Variable immer wieder auf 0 zurück setzt fällt das noch nicht auf. Das
wird erst akut, wenn man Werte >255 hat.
Allerdings würde ich keine seriellen Ausgaben machen wollen, während die
Interrupts gesperrt ist. Dabei hängt sich der Mikrocontroller gerne mal
auf. Besser so:
1
volatileintStepperPos=0;
2
...
3
4
cli();
5
intcurrentPos=StepperPos;
6
sei();
7
8
if(LastStepperPos!=currentPos){
9
Serial.println("LastStepperPos");
10
Serial.println(LastStepperPos);
11
LastStepperPos=currentPos;
12
Serial.println("StepperPos");
13
Serial.println(currentPos);
14
myStepper.step(currentPos);
15
16
cli();
17
currentPos=0;
18
sei();
19
}
Außerdem sollten die Variablen, die sowohl in der ISR als auch außerhalb
verwendet werden, volatile sein. Sonst es es reines Glück, ob sie
überhaupt funktionieren.
Stefan ⛄ F. schrieb:> Kontakte prellen halt, das liegt in deren Natur.
In dem Fall war es allerdings nicht das prellen.
Der Nano den ich die ganze zeit benutze, der hat eine macke, mit dem
zweiten funktionierts!
Da lötet man schon alles extra zusammen, trotzdem spinnt die Hardware!
Stefan ⛄ F. schrieb:> Außerdem sollten die Variablen, die sowohl in der ISR als auch außerhalb> verwendet werden, volatile sein. Sonst es es reines Glück, ob sie> überhaupt funktionieren.
Wird übernommen.
Nach dem der Spaß nun funktioniert geht's an die gestaltung des Display.