Forum: Mikrocontroller und Digitale Elektronik Zwei Interrupts gleichzeitig Laufen


von sicajo (Gast)


Lesenswert?

moinsen Community,

Ich habe Folgendes Problem:

ich habe zwei Schrittmotoren die ziemlich empfindlich auf delays 
Reagieren ( wenigen µs)
so da ich die nicht einfach im main() laufen lassen kann da alles andere 
dort drin auch einen delay haben. Also hab ich die in einen Interrupt 
reingesteckt. So ein Motor läuft auch Top, den main() kann ich auch 
nebenbei benutzen. so lange rede kurzer Sinn: ich habe zwei 
Schrittmotoren die exakt (oder wie es möglich ist) gleichzeitig laufen. 
Meine Überlegung war, einen zweiten Interrupt laufen zu lassen. Aber es 
läuft immer nur ein Motor von den zweien. Kann das überhaupt 
funktionieren ? wenn ja wo ist der Fehler an meinem Code? Danke schonmal 
:)
1
 
2
3
uint16_t Schwellwert = 65400;
4
uint16_t Schwellwert1 = 65400;
5
6
void setup() 
7
{ 
8
 noInterrupts();
9
  
10
  TCCR1A = 0;
11
  TCCR1B = 0;
12
13
  TCCR2A = 0;
14
  TCCR2B = 0;
15
16
  TCNT1 = Schwellwert;
17
  TCCR1B |= (1 << CS12);
18
  TIMSK1 |= (1 << TOIE1);
19
20
  TCNT2 = Schwellwert1;
21
  TCCR2B |= (1 << CS12);
22
  TIMSK2 |= (1 << TOIE1);
23
  
24
  interrupts();
25
26
27
}
28
void loop()
29
{
30
31
  // Motor_Rueckwaerts_Links();
32
  // Motor_Rueckwaerts_Rechts();
33
34
  // Motor_Vorwaerts_Links();
35
  // Motor_Vorwaerts_Rechts();
36
37
  // Motor_Aus();
38
39
}
40
41
42
ISR(TIMER1_OVF_vect)
43
{
44
  TCNT1 = Schwellwert;
45
  
46
  Motor_Rueckwaerts_Rechts();
47
48
}
49
50
51
ISR(TIMER2_OVF_vect)
52
{
53
  TCNT2 = Schwellwert1;
54
55
  Motor_Rueckwaerts_Links();
56
}

von man oh man (Gast)


Lesenswert?

sicajo schrieb:
> Motor_Rueckwaerts_Rechts();

sicajo schrieb:
> Motor_Rueckwaerts_Links();

zeig bitte den code der funktionen

von Viktor B. (coldlogic)


Lesenswert?

Zwei Interrupts genau gleichzeitig laufen lassen kann zu interessanten 
Effekten führen. Versuch mal, den Lauf der Motoren in einem Interrupt 
zusammenzufassen oder einen der Schwellwerte leicht verändert zu 
initialisieren und später mit dem richtigen Wert zu beschreiben

von Horst (Gast)


Lesenswert?

Je nach Controller solltest Du im Datenblatt auch Interrupt-Prioritäten 
finden.

Wenn's knapp wird, sollte man beim Betreten einer ISR lieber die 
Interrupts als erstes deaktivieren und sie vorm verlassen wieder 
aktivieren.

von man oh man (Gast)


Lesenswert?

Viktor B. schrieb:
> Versuch mal

wenn der code con Motor...() in der loop() zu lang war, warum sollte es 
dann in der isr besser sein? die interrupts laufen ueber, das ist es. 
:->>>

von DEELAY (Gast)


Lesenswert?

Deine Schrittmotoren reagieren empfindlich auf Delay.
Und schon mal klar: im µs-Bereich.

Solche Probleme gibt es eher selten bei Schrittmotoren, aber
umso häufiger bei schlecht durchdachten Konzepten. Bevor du dir
das nicht selbst klargemacht hast, wirst du auch mit GHz-µCs
nix zum Laufen bekommen.
Isso...

von Jim M. (turboj)


Lesenswert?

Horst schrieb:
> Je nach Controller solltest Du im Datenblatt auch Interrupt-Prioritäten
> finden.

AVR kennt keine Interrupt Prioritäten, da geht nur einer.

von malsehen (Gast)


Lesenswert?

sicajo schrieb:
> TCNT2 = Schwellwert1;
>   TCCR2B |= (1 << CS12);      TCCR2B|=(1<<CS22); ???
>   TIMSK2 |= (1 << TOIE1);     TIMSK2|=(1<<...

von m.n. (Gast)


Lesenswert?

Auf die Gefahr hin, daß es für Dich einen 'Kulturschock' darstellt, zwei 
Beispiele wie man mit einem Arduino Uno zwei Schrittmotore unabhängig 
voneinander ansteuern kann: 
http://mino-elektronik.de/Generator/takte_impulse.htm#bsp3a

Man kann es ggf. auch schlichter anstellen, stößt dann vermutlich bald 
wieder auf Probleme.

von S. Landolt (Gast)


Lesenswert?

Es sieht irgendwie nach AVR8 aus, aber welcher Typ in dieser Reihe hat 
einen 16-bit-Timer2?

von Stefan F. (Gast)


Lesenswert?

Damit ein Computer zwei Funktionen (Interrupt-Routinen) gleichzeitig 
ausführen kann, braucht er zwei CPU Kerne. Ich nehme mal an, dass deine 
Hardware das nicht bietet.

Vermutlich liegt dein eigentliches Problem darin, dass deine 
Motor-Funktionen blockierende Warteschleifen enthalten und somit 
Multitasking verhindern.

Für kleine Single-Core Prozessoren sind Zustandsautomaten eine gute 
Methode, blockierende Warteschleifen zu umgehen und dadurch Multitasking 
in der Hauptschleife zu ermöglichen.

Ich empfehle dazu http://stefanfrings.de/multitasking_arduino/index.html

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:

> Es sieht irgendwie nach AVR8 aus, aber welcher Typ in dieser Reihe hat
> einen 16-bit-Timer2?

Nur sehr wenige Tinys. Konkret fallen mir im Moment nur 441/841 ein.

Bei den Megas ist Timer2 immer nur 8 Bit und die meisten Tinys haben 
überhaupt keinen Timer2.

von S. Landolt (Gast)


Lesenswert?

> Konkret fallen mir im Moment nur 441/841 ein.
Danke für die Auskunft.
Es wäre schon sinnvoll gewesen, sicajo hätte gleich geschrieben, dass 
er einen solchen hat.

von sicajo (Gast)


Lesenswert?

Danke erstmal für die vielen Antworten

Also der µC ist ein Atmega328P der besitzt 3 Timer.
0 und 2 sind 8Bit und 1 ist ein 16Bit. Schon mal ein Fehler im Code 
entdeckt Schwellwert1 muss uint8_t heißen wobei das denke ich kein 
unterschied macht oder?

wenn die Schrittmotor Routinen in einen Code mache ist der eine 
geringfügig langsamer und mir ist keine Methode eingefallen die troztdem 
gleichzeitig laufen zu lassen.

Ich weiß gar nicht ob der Schrittmotor oder Der Treiber so empfindlich 
ist.

Meinen kompletten Code kann ich gerne Posten wenn ich zu Hause bin dann 
schau ich mir auch mal den Link von m.n. an

also kann ich hieraus erstmal mitnehmen das ich keine zwei Interrupts 
gleichzeitig laufen lassen kann ?

So hoffe hab niemanden übersehen

Mfg

von S. Landolt (Gast)


Lesenswert?

> Also der µC ist ein Atmega328P
Und dann bringt der Compiler keine Warnung bei
1
  TCNT2 = Schwellwert1;
?

> Schwellwert1 muss uint8_t heißen wobei das denke ich kein unterschied macht 
oder?
Bei
1
Schwellwert1 = 65400;
?

von S. Landolt (Gast)


Lesenswert?

... der Timer2 läuft doch viel zu schnell.

von Stefan F. (Gast)


Lesenswert?

sicajo schrieb:
> kann ich hieraus erstmal mitnehmen das ich keine zwei Interrupts
> gleichzeitig laufen lassen kann ?

Du kannst überhaupt nicht zwei Sachen gleichzeitig laufen lassen. Der 
Mikrocontroller hat nämlich nur eine CPU. Ich dachte, ich hätte mich da 
klar ausgedrückt.

von S. Landolt (Gast)


Lesenswert?

Spielt das eine Rolle, wenn die Timer-Interrupts leicht versetzt 
synchron laufen?

von Stefan F. (Gast)


Lesenswert?

So wie er die programmiert hat, ist aus dem "leicht versetzt" wohl zu 
viel Versatz geworden.

von S. Landolt (Gast)


Lesenswert?

> der Timer2 läuft doch viel zu schnell.
Um es korrekt zu formulieren: der Timer2-Interrupt erfolgt viel zu oft.

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:

> Es wäre schon sinnvoll gewesen, sicajo hätte gleich geschrieben, dass
> er einen solchen hat.

Nunja, inzwischen wissen wir ja: hat er nicht.

Und damit hat er dann auch gleich unmißverständlich klargestellt: er hat 
auch sonst keinerlei Ahnung. Ein typischer C&P-"Programmierer" halt...

von sicajo (Gast)


Lesenswert?

klar 8 Bit sind ja nur 256. Ja gut blöd hab nichts gesagt. warum hat er 
denn bitte nicht gemeckert ?
ja ich kann natürlich nicht etwas gleichzeitig laufen lassen. Das ist 
alles nacheinander.

Und ne solange es nicht Sekunden unterschied ist können die ruhig 
versetzt laufen Hauptsache Syncron. Hast du eine Idee S.Landold?

von S. Landolt (Gast)


Lesenswert?

> ... Idee ...
Für beide Timer die Vorteiler so wählen, dass 8 bit reichen. Und den 
Compiler auf die höchste Stufe für Warnungen stellen.

von Stefan F. (Gast)


Lesenswert?

sicajo schrieb:
> warum hat er denn bitte nicht gemeckert ?

Wer ist er? Und warum sollte er meckern?

> ja ich kann natürlich nicht etwas gleichzeitig laufen lassen. Das ist
> alles nacheinander.

> Und ne solange es nicht Sekunden unterschied ist können die ruhig
> versetzt laufen Hauptsache Syncron.

Synchron ist aber das Gegenteil von Versetzt. Erst wenn die Aufgabe klar 
ist, kann man ein Lösungskonzept erstellen.

von S. Landolt (Gast)


Lesenswert?

an c-hater:
> ... inzwischen wissen wir ja ...
Zwar hatte ich es gleich vermutet, wollte aber nicht mit der Tür ins 
Haus fallen.

von sicajo (Gast)


Lesenswert?

sorry blöd formuliert. Vielleicht braucht ihr auch ein paar mehr Infos.
also die Schrittmotoren sind zwei Räder ( Roboter ). Also es wäre gut 
wenn Die, so weit es möglich ist, beiden Synchron laufen. Wenn Motor 2 
10ms (oder was auch immer ) später startet ist das absolut kein Problem. 
Sollte halt nur nicht zu viel Verzögerung sein möchte ja nicht, dass der 
Roboter nach Rechts oder Links Zieht.

naja Er sollte doch meckern wenn ich bei einem 8 Bit Register eine Zahl 
von 65000 angebe.

Mfg

von Stefan F. (Gast)


Lesenswert?

sicajo schrieb:
> Er sollte doch meckern wenn ich bei einem 8 Bit Register eine Zahl
> von 65000 angebe.

Wer ist "er"? Du meinst vielleicht den Compiler. Der meckert 
tatsächlich, es sei denn, man unterdrückt alle Warnungen, wie es die 
Arduino IDE standardmäßig tut. Kann man aber einstellen.

Um zwei Motoren synchron anzusteuern, braucht man in der Regel gar keine 
Interrupts. Höchstens vielleicht einen Systemtimer 
(Millisekunden-Counter). Wir wissen nicht, was deine Interrupthandler 
machen und warum du überhaupt Interrupts verwendet hast. Sogar dein 
Quelltext ist geheim, ebenso der Schaltplan und die Aufgabenstellung.

Also können wir Dir auch nicht helfen, außer die Info, dass dein Ansatz 
mit sehr hoher Wahrscheinlichkeit ungeeignet ist und dass du dich mit 
Zustandsautomaten beschäftigen sollst.

von Falk B. (falk)


Lesenswert?

sicajo schrieb:

> wenn die Schrittmotor Routinen in einen Code mache ist der eine
> geringfügig langsamer und mir ist keine Methode eingefallen die troztdem
> gleichzeitig laufen zu lassen.

Das Zauberwort lautet Multitasking und ist gar nicht so schwer, wenn 
man das Konzept erst einmal verstanden hat. Dann reicht ein Timer und 
das Ergebnis ist trotzdem deutlich besser ;-)

> also kann ich hieraus erstmal mitnehmen das ich keine zwei Interrupts
> gleichzeitig laufen lassen kann ?

Falsch. Man kann schon, aber daraus wird noch lange kein gescheites 
Konzept. Vor allem dann, wenn deine Funktionen

 Motor_Rueckwaerts_Rechts();
 Motor_Rueckwaerts_Links();

blockierend bzw. mit eher langen Delays arbeiten.

von Falk B. (falk)


Lesenswert?

Stefanus F. schrieb:

> Synchron ist aber das Gegenteil von Versetzt.

SCHWACHSINN! Auch versetzt laufende Abläufe bzw. hier Timer sind 
synchron! Ebenso Vielfache von Takten etc., wie die PLLs und ähnliche 
Schaltungen erzeugen.

Synchron heißt NICHT gleichzeitig oder mit Phasenlage 0°!!!

https://de.wikipedia.org/wiki/Synchronit%C3%A4t

Es heißt vielmehr "zeitlich genau definiert". Dazu gehören auch 
phasenverschobene Signale mit gleicher Frequenz.

> Erst wenn die Aufgabe klar
> ist, kann man ein Lösungskonzept erstellen.

Die IST klar! Der OP will 2 Schrittmotoren unabhängig voneinander in der 
Geschwindigkeit steuern.

von c-hater (Gast)


Lesenswert?

sicajo schrieb:

> naja Er sollte doch meckern wenn ich bei einem 8 Bit Register eine Zahl
> von 65000 angebe.

Das würde "Er" auch tun, wenn nicht irgendwelche Wichser beschlossen 
hätten, dass man zarte User standardmäßig nicht mit "unnötigen" 
Fehlermeldungen oder Warnungen gängeln sollte...

Die sollen doch softwaremäßig nur Wichsvorlagen zusammenkopieren und vor 
allem die völlig überteuerte Systemhardware kaufen.

Darin besteht im Kern das Arduino-Konzept.

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> keinerlei Ahnung. Ein typischer C&P-"Programmierer"

Falk B. schrieb:
> SCHWACHSINN!

c-hater schrieb:
> Wichsvorlagen

Sind wir wieder ganz unten angekommen?

von c-hater (Gast)


Lesenswert?

Stefanus F. schrieb:
> c-hater schrieb:
>> keinerlei Ahnung. Ein typischer C&P-"Programmierer"
>
> Falk B. schrieb:
>> SCHWACHSINN!
>
> c-hater schrieb:
>> Wichsvorlagen
>
> Sind wir wieder ganz unten angekommen?

Zarter User? Heul' doch!

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> Zarter User? Heul' doch!

pfffft

von Holger (Gast)


Lesenswert?

c-hater schrieb:
> Zarter User? Heul' doch!

Großkotziger Hasser? Schäm dich!

von sicajo (Gast)


Lesenswert?

Oje ich wollte kein Streit auslösen...

von Holger (Gast)


Lesenswert?

sicajo schrieb:
> Oje ich wollte kein Streit auslösen...

Keine Bange. Der c-hater kann nicht anders. Der ist im Tiefflug durch 
die Kinderstube geflogen und seine Mutter hat bei seiner Erziehung auf 
ganzer Linie versagt.
Nicht deine Schuld...

von Falk B. (falk)


Lesenswert?

sicajo schrieb:

> Meinen kompletten Code kann ich gerne Posten wenn ich zu Hause bin dann

Mach das.

von Stefan F. (Gast)


Lesenswert?

Falk B. schrieb:
> Die IST klar! Der OP will 2 Schrittmotoren unabhängig voneinander in der
> Geschwindigkeit steuern.

Na, dann wirst du ihm sicher gerne eine passende Lösung präsentieren, 
die uns alle in deinen Schatten stellt.

von Falk B. (falk)


Lesenswert?

Stefanus F. schrieb:
> Falk B. schrieb:
>> Die IST klar! Der OP will 2 Schrittmotoren unabhängig voneinander in der
>> Geschwindigkeit steuern.
>
> Na, dann wirst du ihm sicher gerne eine passende Lösung präsentieren,
> die uns alle in deinen Schatten stellt.

Hast du Komplexe? Oder einen kleinen . . . .  Schatten? ;-)

von Stefan F. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Erst wenn die Aufgabe klar
> ist, kann man ein Lösungskonzept erstellen.

Falk B. schrieb:
> Die IST klar! Der OP will 2 Schrittmotoren unabhängig voneinander in der
> Geschwindigkeit steuern.

Stefanus F. schrieb:
> Na, dann wirst du ihm sicher gerne eine passende Lösung präsentieren,
> die uns alle in deinen Schatten stellt.

Falk B. schrieb:
> Hast du Komplexe? Oder einen kleinen . . . .  Schatten?

Ich habe tatsächlich einen Vogel, nicht mehr alle Tassen im Schrank und 
manchmal einen neben mir her laufen. Aber sonst ist alles Ok.

Zurück zum Thema: War das nun so falsch von mir, weitere Infos zur 
Aufgabe anzufordern? Anscheinend bist auch du doch nicht in der Lage, 
eine Lösung anzubieten.

von Falk B. (falk)


Lesenswert?

Stefanus F. schrieb:
> Zurück zum Thema: War das nun so falsch von mir, weitere Infos zur
> Aufgabe anzufordern? Anscheinend bist auch du doch nicht in der Lage,
> eine Lösung anzubieten.

Du hast schon wieder einen akuten Anfall von Helfersyndrom. Und einem 
Minderwertigkeitskomplex.

von man oh man (Gast)


Lesenswert?

Falk B. schrieb:
> einem
> Minderwertigkeitskomplex.

+++ ja, so ist er.

von man oh man (Gast)


Lesenswert?

@sicajo
wo ist der code???

von Stefan F. (Gast)


Lesenswert?

Falk B. schrieb:
> Du hast schon wieder einen akuten Anfall von Helfersyndrom.

Falk, das musst du mir nicht immer wieder vorwerfen, denn jedes mal 
offenbarst du damit, was für eine Sorte Mensch du bist. Auf jeden Fall 
nicht die Sorte von Mensch, mit der ich zu tun haben möchte. In sofern 
darfst du mich gerne mal am ...

Wenn ich helfen möchte, dann lass mich das tun. Sag Du mir nicht, was 
ich zu tun habe. Wenn hier mehr geholfen wird, als Dir zusagt, dann 
halte dich bitte einfach raus!

Deine Nummer von vor kurzem habe ich nicht vergessen. Da hast du mich 
und andere aufgefordert, das Helfen sein zu lassen. Als der Fragende 
dann ganz kurz davor war, mir einen Entwicklungsauftrag zu erteilen, 
hast du ihn mir weg geschnappt und das fertige Programm präsentiert. So 
viel dazu, du hast selber auch ein Helfersyndrom, aber du willst ganz 
alleine der Held sein, der hier hilft. Merkst du eigentlich nicht, wie 
rücksichtslos dieses Verhalten ist?

von man oh man (Gast)


Lesenswert?

Stefanus F. schrieb im Beitrag #5839
> Als der Fragende
> dann ganz kurz davor war, mir einen Entwicklungsauftrag zu erteilen,
> hast du ihn mir weg geschnappt

Tja, falscher Stolz und Eitelkeit sind deine Attribute, Stefan. Jetzt 
ist es endlich raus!

von Falk B. (falk)


Lesenswert?

Was für ein Kindergartentheater ;-)

von Norbert S. (norberts)


Lesenswert?

Moin,

Vielleicht mal zum Verständtnis für sicajo, wie Interupts funktionieren, 
denn ich denke da fehlt noch der Durchblick:
Der Controller macht immer eins nach dem anderen. Gleichzeitig geht da 
gar nichts. (Abgesehen von Hardware, es klappert ein Byte auf Uart, SPI, 
I2C rein/raus o.ä.)
Wenn ein Int zuschlägt, wird die Main unterbrochen und sofort die ISR 
ausgeführt. Alle anderen Ints sind dann erstmal gesperrt. Es wird das 
abgearbeitet was in der ISR steht. Kommt in der Zeit ein anderer Int, 
bleibt das Flag stehen und der wird dann abgearbeitet, wenn die erste 
ISR fertig ist.
Kommt ein anderer Int zweimal, geht der zweite verloren. Das Flag kann 
nur einmal gesetzt werden. Kommt der gleiche Int nochmal, während seine 
ISR abgearbeitet wird, wird der danach gleich nochmal ausgeführt.
Es gibt da eine Reihenfolge der Ints (wenn also wähend einer ISR zwei 
Int zuschlagen, welche wird dann zuerst ausgeführt) aber wenn das eine 
Rolle spielt, sollte man das Konzept überdenken oder man weiß ganz genau 
was man tut.
man kann auch Ints zulassen in einer ISR. Wer sowas tut und auch 
beherrscht, fragt aber nicht hier im Forum.

Zuerst hast Du was von µs geschrieben. Du hast garantiert keine 
Schrittmotoren, bei denen das relevant ist.
Bei zwei Schrittmotoren kann man kaum so mies programmieren, daß diese 
nicht quasi synchron laufen. Da spielen selbst ein paar ms sicher keine 
Rolle. Zumindest nicht im Bastelbereich.

Gruß,
Norbert

von Falk B. (falk)


Lesenswert?

Norbert S. schrieb:
> Zuerst hast Du was von µs geschrieben. Du hast garantiert keine
> Schrittmotoren, bei denen das relevant ist.

Stimmt, aber . . .

> Bei zwei Schrittmotoren kann man kaum so mies programmieren, daß diese
> nicht quasi synchron laufen.

Wenn das mal kein Irrtum ist ;-)

von sicajo (Gast)


Lesenswert?

piep piep piep wir haben uns alle lieb.

Sorry etwas verspätet aber die der komplette Code :
1
 
2
/*   Schrittmotor Variablen deklaration   */
3
4
#define Rad_Links_I01 2
5
#define Rad_Links_I11 3
6
#define Rad_Links_PHASE1 4
7
#define Rad_Links_I02 7
8
#define Rad_Links_I12 6
9
#define Rad_Links_PHASE2 5
10
11
#define Rad_Rechts_I01 8
12
#define Rad_Rechts_I11 9
13
#define Rad_Rechts_PHASE1 10
14
#define Rad_Rechts_I02 13
15
#define Rad_Rechts_I12 12
16
#define Rad_Rechts_PHASE2 11
17
18
/*   Schrittmotor Variablen deklaration Ende   */
19
20
int zahl = 0;
21
22
uint16_t Schwellwert = 65200;  // Vergleichswert Für 16 Bit Register .
23
24
void setup() {
25
26
  Serial.begin(9600); // Serielle Verbingung Starten
27
28
  /*   Schrittmotor Pin konfiguration   */
29
30
  pinMode(Rad_Links_I01, OUTPUT);
31
  pinMode(Rad_Links_I11, OUTPUT);
32
  pinMode(Rad_Links_PHASE1, OUTPUT);
33
  pinMode(Rad_Links_I02, OUTPUT);
34
  pinMode(Rad_Links_I12, OUTPUT);
35
  pinMode(Rad_Links_PHASE2, OUTPUT);
36
37
  pinMode(Rad_Rechts_I01, OUTPUT);
38
  pinMode(Rad_Rechts_I11, OUTPUT);
39
  pinMode(Rad_Rechts_PHASE1, OUTPUT);
40
  pinMode(Rad_Rechts_I02, OUTPUT);
41
  pinMode(Rad_Rechts_I12, OUTPUT);
42
  pinMode(Rad_Rechts_PHASE2, OUTPUT);
43
44
  /*   Schrittmotor Pin konfiguration Ende   */
45
46
  noInterrupts(); // alle Interrupts löschen
47
48
  TCCR1A = 0; // TCCR1A Register auf null setzen
49
  TCCR1B = 0; // TCCR1B Register auf null setzen
50
51
  TCNT1 = Schwellwert;
52
  TCCR1B |= (1 << CS12);
53
  TIMSK1 |= (1 << TOIE1);
54
55
  interrupts(); // Interrupts Starten
56
57
}
58
void loop()
59
{
60
61
  if (zahl < 20)
62
  {
63
    zahl++;
64
    delay(500);
65
  }
66
  else
67
  {
68
69
    zahl = 0;
70
71
  }
72
73
  Serial.println(zahl);
74
75
76
  /*   Motor Ansteuerung zufuß   */
77
78
   //  Motor_Rueckwaerts_Links();
79
   //  Motor_Rueckwaerts_Rechts();
80
81
   //  Motor_Vorwaerts_Links();
82
   //  Motor_Vorwaerts_Rechts();
83
84
    // Motor_Aus();
85
86
        
87
88
89
}
90
91
/*   Interrupt Routine Rad Rechts   */
92
93
ISR(TIMER1_OVF_vect)
94
{
95
  TCNT1 = Schwellwert;
96
97
  if ( zahl >=  10 )
98
  {
99
100
    Motor_Vorwaerts_Rechts();
101
102
  } else
103
  {
104
105
    Motor_Rueckwaerts_Rechts();
106
107
  }
108
}
109
110
/*   Interrupt Routine Ende  */


und hier die Funktionen
1
 
2
3
4
static char Drehphase; //Static behält den Wert, auch wenn die Funktion beendet wurde -> permanent im Speicher wie globale Variable
5
6
void Motor_Vorwaerts_Links() {
7
8
  switch (Drehphase)
9
  {
10
    case 0:
11
      //Phase 1
12
      digitalWrite(Rad_Links_I01, HIGH);
13
      digitalWrite(Rad_Links_I11, LOW);
14
      digitalWrite(Rad_Links_PHASE1, HIGH);
15
      digitalWrite(Rad_Links_I02, HIGH);
16
      digitalWrite(Rad_Links_I12, LOW);
17
      digitalWrite(Rad_Links_PHASE2, LOW);
18
      break;
19
20
    case 1:
21
      //Phase 2
22
      digitalWrite(Rad_Links_I01, HIGH);
23
      digitalWrite(Rad_Links_I11, HIGH);
24
      digitalWrite(Rad_Links_PHASE1, HIGH);
25
      digitalWrite(Rad_Links_I02, LOW);
26
      digitalWrite(Rad_Links_I12, LOW);
27
      digitalWrite(Rad_Links_PHASE2, LOW);
28
      break;
29
30
    case 2:
31
      //Phase 3
32
      digitalWrite(Rad_Links_I01, HIGH);
33
      digitalWrite(Rad_Links_I11, LOW);
34
      digitalWrite(Rad_Links_PHASE1, LOW);
35
      digitalWrite(Rad_Links_I02, HIGH);
36
      digitalWrite(Rad_Links_I12, LOW);
37
      digitalWrite(Rad_Links_PHASE2, LOW);
38
      break;
39
40
    case 3:
41
      //Phase 4
42
      digitalWrite(Rad_Links_I01, LOW);
43
      digitalWrite(Rad_Links_I11, LOW);
44
      digitalWrite(Rad_Links_PHASE1, LOW);
45
      digitalWrite(Rad_Links_I02, HIGH);
46
      digitalWrite(Rad_Links_I12, HIGH);
47
      digitalWrite(Rad_Links_PHASE2, LOW);
48
      break;
49
50
    case 4:
51
      //Phase 5
52
      digitalWrite(Rad_Links_I01, HIGH);
53
      digitalWrite(Rad_Links_I11, LOW);
54
      digitalWrite(Rad_Links_PHASE1, LOW);
55
      digitalWrite(Rad_Links_I02, HIGH);
56
      digitalWrite(Rad_Links_I12, LOW);
57
      digitalWrite(Rad_Links_PHASE2, HIGH);
58
      break;
59
60
    case 5:
61
      //Phase 6
62
      digitalWrite(Rad_Links_I01, HIGH);
63
      digitalWrite(Rad_Links_I11, HIGH);
64
      digitalWrite(Rad_Links_PHASE1, LOW);
65
      digitalWrite(Rad_Links_I02, LOW);
66
      digitalWrite(Rad_Links_I12, LOW);
67
      digitalWrite(Rad_Links_PHASE2, HIGH);
68
      break;
69
70
    case 6:
71
      //Phase 7
72
      digitalWrite(Rad_Links_I01, HIGH);
73
      digitalWrite(Rad_Links_I11, LOW);
74
      digitalWrite(Rad_Links_PHASE1, HIGH);
75
      digitalWrite(Rad_Links_I02, HIGH);
76
      digitalWrite(Rad_Links_I12, LOW);
77
      digitalWrite(Rad_Links_PHASE2, HIGH);
78
      break;
79
80
    case 7:
81
      //Phase 8
82
      digitalWrite(Rad_Links_I01, LOW);
83
      digitalWrite(Rad_Links_I11, LOW);
84
      digitalWrite(Rad_Links_PHASE1, HIGH);
85
      digitalWrite(Rad_Links_I02, HIGH);
86
      digitalWrite(Rad_Links_I12, HIGH);
87
      digitalWrite(Rad_Links_PHASE2, HIGH);
88
      break;
89
90
91
  }
92
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
93
  {
94
    Drehphase++;
95
96
97
  }
98
  else
99
  {
100
    Drehphase = 0;
101
  }
102
103
104
}
105
106
107
void Motor_Vorwaerts_Rechts() {
108
109
  switch (Drehphase)
110
  {
111
112
    case 0:
113
      //Phase 9
114
      digitalWrite(Rad_Rechts_I01, LOW);
115
      digitalWrite(Rad_Rechts_I11, LOW);
116
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
117
      digitalWrite(Rad_Rechts_I02, HIGH);
118
      digitalWrite(Rad_Rechts_I12, HIGH);
119
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
120
      break;
121
122
    case 1:
123
      //Phase 10
124
      digitalWrite(Rad_Rechts_I01, HIGH);
125
      digitalWrite(Rad_Rechts_I11, LOW);
126
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
127
      digitalWrite(Rad_Rechts_I02, HIGH);
128
      digitalWrite(Rad_Rechts_I12, LOW);
129
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
130
      break;
131
132
    case 2:
133
      //Phase 12
134
      digitalWrite(Rad_Rechts_I01, HIGH);
135
      digitalWrite(Rad_Rechts_I11, HIGH);
136
      digitalWrite(Rad_Rechts_PHASE1, LOW);
137
      digitalWrite(Rad_Rechts_I02, LOW);
138
      digitalWrite(Rad_Rechts_I12, LOW);
139
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
140
      break;
141
142
    case 3:
143
      //Phase 13
144
      digitalWrite(Rad_Rechts_I01, HIGH);
145
      digitalWrite(Rad_Rechts_I11, LOW);
146
      digitalWrite(Rad_Rechts_PHASE1, LOW);
147
      digitalWrite(Rad_Rechts_I02, HIGH);
148
      digitalWrite(Rad_Rechts_I12, LOW);
149
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
150
      break;
151
152
    case 4:
153
      //Phase 14
154
      digitalWrite(Rad_Rechts_I01, LOW);
155
      digitalWrite(Rad_Rechts_I11, LOW);
156
      digitalWrite(Rad_Rechts_PHASE1, LOW);
157
      digitalWrite(Rad_Rechts_I02, HIGH);
158
      digitalWrite(Rad_Rechts_I12, HIGH);
159
      digitalWrite(Rad_Rechts_PHASE2, LOW);
160
      break;
161
162
    case 5:
163
      //Phase 15
164
      digitalWrite(Rad_Rechts_I01, HIGH);
165
      digitalWrite(Rad_Rechts_I11, LOW);
166
      digitalWrite(Rad_Rechts_PHASE1, LOW);
167
      digitalWrite(Rad_Rechts_I02, HIGH);
168
      digitalWrite(Rad_Rechts_I12, LOW);
169
      digitalWrite(Rad_Rechts_PHASE2, LOW);
170
      break;
171
172
    case 6:
173
      //Phase 16
174
      digitalWrite(Rad_Rechts_I01, HIGH);
175
      digitalWrite(Rad_Rechts_I11, HIGH);
176
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
177
      digitalWrite(Rad_Rechts_I02, LOW);
178
      digitalWrite(Rad_Rechts_I12, LOW);
179
      digitalWrite(Rad_Rechts_PHASE2, LOW);
180
      break;
181
182
    case 7:
183
      //Phase 17
184
      digitalWrite(Rad_Rechts_I01, HIGH);
185
      digitalWrite(Rad_Rechts_I11, LOW);
186
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
187
      digitalWrite(Rad_Rechts_I02, HIGH);
188
      digitalWrite(Rad_Rechts_I12, LOW);
189
      digitalWrite(Rad_Rechts_PHASE2, LOW);
190
      break;
191
192
193
194
  }
195
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
196
  {
197
    Drehphase++;
198
199
200
  }
201
  else
202
  {
203
    Drehphase = 0;
204
  }
205
206
207
}
208
209
void Motor_Rueckwaerts_Links() {
210
211
  switch (Drehphase)
212
  {
213
    case 0:
214
      //Phase 1
215
      digitalWrite(Rad_Links_I01, LOW);
216
      digitalWrite(Rad_Links_I11, LOW);
217
      digitalWrite(Rad_Links_PHASE1, HIGH);
218
      digitalWrite(Rad_Links_I02, HIGH);
219
      digitalWrite(Rad_Links_I12, HIGH);
220
      digitalWrite(Rad_Links_PHASE2, HIGH);
221
      break;
222
223
    case 1:
224
      //Phase 2
225
      digitalWrite(Rad_Links_I01, HIGH);
226
      digitalWrite(Rad_Links_I11, LOW);
227
      digitalWrite(Rad_Links_PHASE1, HIGH);
228
      digitalWrite(Rad_Links_I02, HIGH);
229
      digitalWrite(Rad_Links_I12, LOW);
230
      digitalWrite(Rad_Links_PHASE2, HIGH);
231
      break;
232
233
    case 2:
234
      //Phase 3
235
      digitalWrite(Rad_Links_I01, HIGH);
236
      digitalWrite(Rad_Links_I11, HIGH);
237
      digitalWrite(Rad_Links_PHASE1, LOW);
238
      digitalWrite(Rad_Links_I02, LOW);
239
      digitalWrite(Rad_Links_I12, LOW);
240
      digitalWrite(Rad_Links_PHASE2, HIGH);
241
      break;
242
243
    case 3:
244
      //Phase 4
245
      digitalWrite(Rad_Links_I01, HIGH);
246
      digitalWrite(Rad_Links_I11, LOW);
247
      digitalWrite(Rad_Links_PHASE1, LOW);
248
      digitalWrite(Rad_Links_I02, HIGH);
249
      digitalWrite(Rad_Links_I12, LOW);
250
      digitalWrite(Rad_Links_PHASE2, HIGH);
251
      break;
252
253
    case 4:
254
      //Phase 5
255
      digitalWrite(Rad_Links_I01, LOW);
256
      digitalWrite(Rad_Links_I11, LOW);
257
      digitalWrite(Rad_Links_PHASE1, LOW);
258
      digitalWrite(Rad_Links_I02, HIGH);
259
      digitalWrite(Rad_Links_I12, HIGH);
260
      digitalWrite(Rad_Links_PHASE2, LOW);
261
      break;
262
263
    case 5:
264
      //Phase 6
265
      digitalWrite(Rad_Links_I01, HIGH);
266
      digitalWrite(Rad_Links_I11, LOW);
267
      digitalWrite(Rad_Links_PHASE1, LOW);
268
      digitalWrite(Rad_Links_I02, HIGH);
269
      digitalWrite(Rad_Links_I12, LOW);
270
      digitalWrite(Rad_Links_PHASE2, LOW);
271
      break;
272
273
    case 6:
274
      //Phase 7
275
      digitalWrite(Rad_Links_I01, HIGH);
276
      digitalWrite(Rad_Links_I11, HIGH);
277
      digitalWrite(Rad_Links_PHASE1, HIGH);
278
      digitalWrite(Rad_Links_I02, LOW);
279
      digitalWrite(Rad_Links_I12, LOW);
280
      digitalWrite(Rad_Links_PHASE2, LOW);
281
      break;
282
283
    case 7:
284
      //Phase 8
285
      digitalWrite(Rad_Links_I01, HIGH);
286
      digitalWrite(Rad_Links_I11, LOW);
287
      digitalWrite(Rad_Links_PHASE1, HIGH);
288
      digitalWrite(Rad_Links_I02, HIGH);
289
      digitalWrite(Rad_Links_I12, LOW);
290
      digitalWrite(Rad_Links_PHASE2, LOW);
291
      break;
292
293
  }
294
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
295
  {
296
    Drehphase++;
297
  }
298
  else
299
  {
300
    Drehphase = 0;
301
  }
302
303
}
304
305
void Motor_Rueckwaerts_Rechts() {
306
307
  switch (Drehphase)
308
  {
309
    case 0:
310
      //Phase 9
311
      digitalWrite(Rad_Rechts_I01, HIGH);
312
      digitalWrite(Rad_Rechts_I11, LOW);
313
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
314
      digitalWrite(Rad_Rechts_I02, HIGH);
315
      digitalWrite(Rad_Rechts_I12, LOW);
316
      digitalWrite(Rad_Rechts_PHASE2, LOW);
317
      break;
318
319
    case 1:
320
      //Phase 10
321
      digitalWrite(Rad_Rechts_I01, HIGH);
322
      digitalWrite(Rad_Rechts_I11, HIGH);
323
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
324
      digitalWrite(Rad_Rechts_I02, LOW);
325
      digitalWrite(Rad_Rechts_I12, LOW);
326
      digitalWrite(Rad_Rechts_PHASE2, LOW);
327
      break;
328
329
    case 2:
330
      //Phase 11
331
      digitalWrite(Rad_Rechts_I01, HIGH);
332
      digitalWrite(Rad_Rechts_I11, LOW);
333
      digitalWrite(Rad_Rechts_PHASE1, LOW);
334
      digitalWrite(Rad_Rechts_I02, HIGH);
335
      digitalWrite(Rad_Rechts_I12, LOW);
336
      digitalWrite(Rad_Rechts_PHASE2, LOW);
337
      break;
338
339
    case 3:
340
      //Phase 12
341
      digitalWrite(Rad_Rechts_I01, LOW);
342
      digitalWrite(Rad_Rechts_I11, LOW);
343
      digitalWrite(Rad_Rechts_PHASE1, LOW);
344
      digitalWrite(Rad_Rechts_I02, HIGH);
345
      digitalWrite(Rad_Rechts_I12, HIGH);
346
      digitalWrite(Rad_Rechts_PHASE2, LOW);
347
      break;
348
349
    case 4:
350
      //Phase 13
351
      digitalWrite(Rad_Rechts_I01, HIGH);
352
      digitalWrite(Rad_Rechts_I11, LOW);
353
      digitalWrite(Rad_Rechts_PHASE1, LOW);
354
      digitalWrite(Rad_Rechts_I02, HIGH);
355
      digitalWrite(Rad_Rechts_I12, LOW);
356
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
357
      break;
358
359
    case 5:
360
      //Phase 14
361
      digitalWrite(Rad_Rechts_I01, HIGH);
362
      digitalWrite(Rad_Rechts_I11, HIGH);
363
      digitalWrite(Rad_Rechts_PHASE1, LOW);
364
      digitalWrite(Rad_Rechts_I02, LOW);
365
      digitalWrite(Rad_Rechts_I12, LOW);
366
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
367
      break;
368
369
    case 6:
370
      //Phase 15
371
      digitalWrite(Rad_Rechts_I01, HIGH);
372
      digitalWrite(Rad_Rechts_I11, LOW);
373
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
374
      digitalWrite(Rad_Rechts_I02, HIGH);
375
      digitalWrite(Rad_Rechts_I12, LOW);
376
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
377
      break;
378
379
    case 7:
380
      //Phase 16
381
      digitalWrite(Rad_Rechts_I01, LOW);
382
      digitalWrite(Rad_Rechts_I11, LOW);
383
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
384
      digitalWrite(Rad_Rechts_I02, HIGH);
385
      digitalWrite(Rad_Rechts_I12, HIGH);
386
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
387
      break;
388
389
390
391
  }
392
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
393
  {
394
    Drehphase++;
395
  }
396
  else
397
  {
398
    Drehphase = 0;
399
  }
400
401
}
402
403
404
void Motor_Aus() {
405
406
  digitalWrite(Rad_Links_I01, HIGH);
407
  digitalWrite(Rad_Links_I11, HIGH);
408
  digitalWrite(Rad_Links_I02, HIGH);
409
  digitalWrite(Rad_Links_I12, HIGH);
410
  digitalWrite(Rad_Links_PHASE1, HIGH);
411
  digitalWrite(Rad_Links_PHASE2, HIGH);
412
413
  digitalWrite(Rad_Rechts_I01, HIGH);
414
  digitalWrite(Rad_Rechts_I11, HIGH);
415
  digitalWrite(Rad_Rechts_I02, HIGH);
416
  digitalWrite(Rad_Rechts_I12, HIGH);
417
  digitalWrite(Rad_Rechts_PHASE1, HIGH);
418
  digitalWrite(Rad_Rechts_PHASE2, HIGH);
419
  
420
}


So nicht wundern ich habe den zweiten Timer erstmal Rausgenommen und im 
Main einen Zähler eingefügt und zu schauen wie dich der Interrupt 
verhält wenn er einfach so Veränderd wird.

Also wie gesagt die Hauptsache ist die Laufen synchron, da habe ich mich 
villeicht etwas Falsch ausgedrückt. Die idee mit dem Motor versetzt 
Laufen lassen hatte ich auch schon wusste nur nicht wie

Mfg

von m.n. (Gast)


Lesenswert?

Oh!

Welchen Motor verwendest Du und mit welchem Treiber?

von sicajo (Gast)


Lesenswert?

der Motor hat keine beschreibung drauf ist aber ein ganz normaler mit 
zwei spulen und 4 eingänge also hab an dem gleichen Treiber ein paar 
andere angeschlossen. treiber ist ein MTS2916a

Datenblatt :

http://ww1.microchip.com/downloads/en/devicedoc/22259c.pdf

von STK500-Besitzer (Gast)


Lesenswert?

Die Arduino-PinOut-Funktion auf der einen Seite und der direkte Zugriff 
auf die Timer-Register widerspricht sich etwas.
Für die GPIO-Ausgabe solltest du auch direkt mit den Registern "reden", 
und dabei das ganze "Schaltwort" (das, was du auf drei DigitalWrites 
verteilst) in einem Rutsch übertragen. Das würde die Sache schon mal 
beschleunigen.

Das ganze Gehampel mit den Switch-Case-Abfragen könnte man auch mit 
Arrays verringern. Hat aber nichts mit dem eigentlichen Problem zu tun, 
würde es aber erleichtern, und das Programm übersichtler machen.

Du brauchst eigentlich nur einen Timer mit dessen ISR.
In der ISR werden beide Motoren getaktet. Dann sind sie schon mal 
synchron.
Da du aber auch Kurven fahren willst, brauchst du für jeden Motor eine 
eigene  Drehphasen-Variable (sofern ich deinen Programmkot richtig 
interpretiert habe).

Du müüstest also einfach die Drehphasen-Variablen je nach Richtung in 
der ISR hoch oder runterzählen (jetzt zählst du ja nur hoch...) und dann 
die Ausgänge setzen.
Du hast einfach einen Fehler bei der Modularisierung gemacht.

von Rohrzange (Gast)


Lesenswert?

Was hälst Du eigentlich davon, erstmal in die Grundlagen einzusteigen?

https://www.mikrocontroller.net/articles/Schrittmotoren

Du wirst Dich, wenn Du Positionen einigermaßen flott "anfahren" willst 
sowieso mit Rampen etc. beschäftigen müssen.

Lass erstmal einen Schrittmotor nach Deinen Wünschen laufen, dann 
beziehe einen 2. ein. Ich sehe auch keinen Grund, die nicht parallel für 
eine Achse (mit gleichen Impulsen) anzusteuern, wenn Du immer wieder 
"Referenzfahrten" zur Synchronisierung (mit Endschaltern) durchführst.

von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

sicajo schrieb:
> treiber ist ein MTS2916a

Der ist funktionskompatibel zum L6219 von STM. Dazu läßt sich vielleicht 
Arduino-Code im Netz finden.
Selber habe ich auch Routinen, aber damit kommst Du womöglich nicht 
klar, da Deine Programmiererfahrungen noch sehr klein sind.

Wenn Du irgendeinmal Land sehen willst, vergiss diese "digital_write()" 
Aufrufe und lege alle Pins eines Motors auf einen gemeinsamen Port. Das 
Ausgabemuster wird dann aus einer Tabelle entnommen.

Ich hänge trotzdem ein Beipiel für einen ATmega8 mit einem Motor an 
PortB an, nur damit Du siehst, wie es gemacht werden könnte. Mit dabei 
ist nach eine Rampe und Stromabsenkung für den Stillstand.

Deutlich einfacher dürfte es für Dich sein, spezielle Controller für 
jeden Motor zu nehmen, die nur mit Richtung und Takt angesteuert werden 
müssen. Damit geht auch eine exakte Gleichzeitigkeit der Schritte, da 
die Hardware der Timer für die Taktausgabe zuständig ist. Beispiele: 
A4982, A4988 oder was es sonst noch als "Ramsch-Ware" mit ungenügender 
Kühlung gibt.

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> piep piep piep wir haben uns alle lieb.
>
> Sorry etwas verspätet aber die der komplette Code :

Schon mal gelesen, was di in dem Fenster steht?

"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

Dein Code ist der übliche Arduino-Overkill, naja. Aber prinzipiell gibt 
es da erstmal kein Problem mit Delays etc. D.h. auch mit 2 Timern sollte 
das laufen, auch wenn man nur einen braucht.


Deine Timerinitialisierung stimmt nicht. Der Timer läuft normal im Mode 
0 mit normalem Overflow bei 0xFFFF. Das manuelle Nachladen in der ISR 
macht man beim AVR meistens nicht, schon gar nicht beim Vorteiler 1. 
Dafür gibt es den CTC-Modus, der kann das automatisch.
1
static char Drehphase; //Static behält den Wert, auch wenn die Funktion beendet wurde -> permanent im Speicher wie globale Variable

Der Kommentar ist richtig, die Lage der Variablen aber nicht ;-)
Denn nur wenn sie innerhalb einer Funktion deklariert wird, ist es auch 
eine lokale, statische Variable. Du hast sie aber außerhalb einer 
Funktion geschrieben, damit ist sie eine globale Variable, welche nur 
innerhalb der Datei sichtbar ist. Das ist was anderes.

von Peter D. (peda)


Lesenswert?

digitalWrite() ist eine recht komplexe Unterfunktion, d.h. mit sehr 
langer Laufzeit. Und dann noch 6 Aufrufe, da kann dem AVR leicht die 
Puste ausgehen.
Besser ist es, die beiden Motoren auf jeweils 2 Ports zu legen und diese 
dann mit einem direkten Zugriff zu laden.

von Rohrzange (Gast)


Lesenswert?

Falk B. schrieb:
> D.h. auch mit 2 Timern sollte
> das laufen, auch wenn man nur einen braucht.

Du hast schon bemerkt, dass ein 500 ms Delay eingebaut ist? (Milli nicht 
Mikro).

O.K., zu Test-Zwecken - aber was soll das. Dann versuche ich aber nicht 
die Schritt-Motore per bit-banging mit CPU-Takt zu bewegen - oder habe 
ich da etwas übersehen?

von Falk B. (falk)


Lesenswert?

Peter D. schrieb:
> digitalWrite() ist eine recht komplexe Unterfunktion, d.h. mit sehr
> langer Laufzeit.

Jaja, es leben die Legenden! Wahrscheinlich mehrere Millisekunden, was?

Beitrag "Re: Suche jemanden mit Oszilloskop zum Optimieren von Signalleitungen"

7us sind nicht das Ende der AVR-Welt!

> Und dann noch 6 Aufrufe, da kann dem AVR leicht die
> Puste ausgehen.

Käse^3!

Ich zitier mal den Herrn Nuhr "Wenn man keine Ahnung hat,  . . ."

> Besser ist es, die beiden Motoren auf jeweils 2 Ports zu legen und diese
> dann mit einem direkten Zugriff zu laden.

WOW! Da bist du ja schon der 2. oder 3. mit dem Expertentipp!

von Rohrzange (Gast)


Lesenswert?

Falk B. schrieb:
> Ich zitier mal den Herrn Nuhr "Wenn man keine Ahnung hat,  . . ."

Ack.

von Falk B. (falk)


Lesenswert?

Rohrzange schrieb:
> Falk B. schrieb:
>> D.h. auch mit 2 Timern sollte
>> das laufen, auch wenn man nur einen braucht.
>
> Du hast schon bemerkt, dass ein 500 ms Delay eingebaut ist? (Milli nicht
> Mikro).

Das ist an der Stelle vollkommen unkritisch.

Allerdings ist der nichtatomare Zugriff auf die nicht volatile Variable 
zahl viel kritischer 8-0

> O.K., zu Test-Zwecken - aber was soll das. Dann versuche ich aber nicht
> die Schritt-Motore per bit-banging mit CPU-Takt zu bewegen

Tut er nicht.

>- oder habe
> ich da etwas übersehen?

Ja. Timer 1 läuft mit Prescaler 256 und zählt von 65200 bis 65535, macht 
85760 CPU-Takte bzw. eine Periodendauer von 5,3ms. Geht so, ist aber 
schon recht flott.

von Rohrzange (Gast)


Lesenswert?

Falk B. schrieb:
> Tut er nicht.

Was denn?

Falk B. schrieb:
> Ja. Timer 1 läuft mit Prescaler 256 und zählt von 65200 bis 65535, macht
> 85760 CPU-Takte bzw. eine Periodendauer von 5,3ms. Geht so, ist aber
> schon recht flott.

Sicher?

sicajo schrieb:
> TCNT1 = Schwellwert;

O.K. Du bist der Experte.

von Falk B. (falk)


Lesenswert?

Rohrzange schrieb:
> Falk B. schrieb:
>> Tut er nicht.
>
> Was denn?

Er taktet den Schrittmotor nicht mit Dutzenden kHz oder gar MHz, wie 
dein Satz vermutete.


> Falk B. schrieb:
>> Ja. Timer 1 läuft mit Prescaler 256 und zählt von 65200 bis 65535, macht
>> 85760 CPU-Takte bzw. eine Periodendauer von 5,3ms. Geht so, ist aber
>> schon recht flott.
>
> Sicher?

Ja, wenn der gezeigte Code auf dem Controller läuft.

> sicajo schrieb:
>> TCNT1 = Schwellwert;
>
> O.K. Du bist der Experte.

Sieht so aus ;-)

von Rohrzange (Gast)


Lesenswert?

Rohrzange schrieb:
> 5,3ms. Geht so, ist aber
>> schon recht flott.

Ohne Rampe sicher sportlich.

Beitrag #5840298 wurde vom Autor gelöscht.
von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Soo, ich hab das Konstrukt mal aufgeräumt.

1.) Variablen zur Kommunikation zwischen Hauptprogramm (loop()) und ISR 
müssen volatile und atomar zugreifbar sein, siehe Interrupt.

2.) Timer 1 im CTC Mode ist bequemer und einfacher nutzbar.

3.) Lokale Variablen müssen lokal definiert werden!

4.) Zur Ansteuerung der Motoren nimmt man je nur eine Funktion und 
übergibt die Richtung mit einem Parameter. Das spart Tipparbeit, 
Quelltext (Übersicht) und vermeidet Fehler in doppelten Funktionen.

5.) Das Hauptprogramm übergibt an die ISR einen Schrittbefehl über die 
Variablen schrittM1 und SchrittM2. Dann muss es entweder ausreichend 
warten oder prüfen, ob die Variablen schon wieder 0 sind. Dann sind die 
Schritte ausgeführt.

von Rohrzange (Gast)


Lesenswert?

Falk B. schrieb:
> Soo, ich hab das Konstrukt mal aufgeräumt

Brav, s'gibt a Wurschti (lt. irgendeiner Werbung :-) )

von sicajo (Gast)


Lesenswert?

Hi,

ich weiß nicht ob ihr gegen mich oder euch gegenseitig schießt.


Falk B. schrieb:
> Soo, ich hab das Konstrukt mal aufgeräumt.

Der Code ist super vielen dank dafür.
hab mich da mal Reingefuchst, habe aber noch ein paar fragen:

- wozu wurden die Funktionen vor dem Setup noch mal deklariert?
- in den Funktionen den schritt mit dem Phase + Step habe ich nicht ganz 
verstanden
- wozu genau ist die variable flag_timer ?

Mfg

von sicajo (Gast)


Lesenswert?

achso das habe ich auch nicht ganz verstanden

1
 if ( schrittM2 ) {
2
    Motor2(schrittM2);
3
    schrittM2 = 0;
4
  }

von Falk B. (falk)


Lesenswert?

sicajo schrieb:

> - wozu wurden die Funktionen vor dem Setup noch mal deklariert?

Genau darum. Weil eine Funktion entweder vor der ersten Verwendung 
definiert sein muss (Die echte Funktion mit Inhalt) oder wenigstens 
deklariert werden muss (Nur der Funktionskopf mit Parametern).

> - in den Funktionen den schritt mit dem Phase + Step habe ich nicht ganz
> verstanden

Steht das nicht im Kommentar?
1
phase = (phase + step) & 7;    // Schritte addieren und Modulo 8 bilden

Man addiert den step und berechnet dann den Modulo Wert. D.h. wenn phase 
+ step >7 oder <0 werden, gibt es einen Über/Unterlauf auf 0 oder 7. 
Damit ist phase immer im Bereich 0-7. Die bitweise UND-Verknüpfung (&) 
ist deutlich einfacher und schneller als eine echte Modulo Operation 
(%), funktioniert aber nur bei 2er Potenzen. Man könnte es auch mit If 
machen, das ist aber mehr Schreibarbeit.
1
phase = phase + step;
2
if (phase > 7) phase -= 7;
3
if (phase < 0) phase += 7;

Hier müßte man phase dann aber als vorzeichenbehaftete Variable 
definieren.

> - wozu genau ist die variable flag_timer ?

Für später ;-) Ich wollte da was anderes machen, hab mich dann aber 
dagegen entschieden.

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> achso das habe ich auch nicht ganz verstanden
>
>  if ( schrittM2 ) {

wenn man eine Variable "einfach so" hinschreibt, ist das die Kurzform in 
C für

schrittM2 != 0

Siehe ein C-Buch deiner Wahl, Auswertung logischer Ausdrücke.

>     Motor2(schrittM2);
>     schrittM2 = 0;
>   }

Also nur wenn schrittM2 != 0 ist, wird die Motorfunktion aufgerufen und 
anschließend die Variable gelöscht.

von sicajo (Gast)


Lesenswert?

Ah okay. Ich merk schon ich muss noch einiges lernen.

zwei fragen hätte ich zum Schluss noch

1. In den Funktionen ist die Variable "Step" was tut die und warum wird 
sie zur Phase addiert ?

2. Warum laufen die Beiden Motoren jetzt synchron ? Ist das speziell 
dein Code oder hatte ich das nicht richtig verstanden mit dem 
gleichzeitig laufen lassen ?

Danke :)

Mfg

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> Ah okay. Ich merk schon ich muss noch einiges lernen.

In der Tat.

> 1. In den Funktionen ist die Variable "Step"

Das ist ein Funktionsparameter, deswegen steht die ja auch im 
Funktionskopf!

> was tut die

Ja was wohl? Sie sagt der Funktion, ob der Motor einen Schritt vor oder 
zurück laufen soll.

>und warum wird
> sie zur Phase addiert ?

Weil das der aktuelle Stand des Motors ist?

> 2. Warum laufen die Beiden Motoren jetzt synchron ?

War das nicht das Ziel?

> Ist das speziell
> dein Code

Sieht so aus.

> oder hatte ich das nicht richtig verstanden mit dem
> gleichzeitig laufen lassen ?

Keine Ahnung.

von sicajo (Gast)


Lesenswert?

Hi,

ich meinte weil die Variable Im Kopf der Funktion deklariert und dannach 
direkt addiert wurde ohne einen wert. Das verwirrt mich etwas. Aber da 
Sie ja auch farblich hinterlegt ist muss sie ja auch schon von selber 
eine Funktion haben oder ?

Mfg

von Stefan F. (Gast)


Lesenswert?

Wenn die Funktion mit step=+1 aufgerufen wird, erhöht sie die Phase bei 
jedem Aufruf. Wobei der Modulus bewirkt, das nach 7 wieder die 0 kommt 
(wie bei ein Zählwerk, dass überläuft).

Wenn sie mit step=-1 aufgerufen wird, verringert sich die Phase bei 
jedem Aufruf. Wobei der Modulus bewirkt, das nach 0 wieder die 7 kommt 
(wie bei ein Zählwerk, dass rückwärts überläuft).

Step bestimmt also, ob der Motor einen Schritt vorwärts oder Rückwärts 
machen soll.

von Holger (Gast)


Lesenswert?

Stefanus F. schrieb:
> step=+1

step += 1

bzw. weiter unten

step -= 1

:-)

von Stefan F. (Gast)


Lesenswert?

Holger schrieb:
> Stefanus F. schrieb:
>> step=+1
>
> step += 1
>
> bzw. weiter unten
>
> step -= 1
>
> :-)

Nein Holger, das habe ich schon ganz genau so gemeint, wie ich es 
hingeschrieben habe. Ich denke nicht, dass die Motor-Funktionen von Falk 
für andere Schrittweiten als +1 und -1 vorgesehen sind.

von sicajo (Gast)


Lesenswert?

ich steh grad bissel auf dem schlauch. Verstehe ich das richtig dass, 
phase + step immer der case ist in dem das Programm sich gerade 
befindet. Wenn ja wozu brauche ich dann step

von Stefan F. (Gast)


Lesenswert?

sicajo schrieb:
> ich steh grad bissel auf dem schlauch. Verstehe ich das richtig
> dass,
> phase + step immer der case ist in dem das Programm sich gerade
> befindet. Wenn ja wozu brauche ich dann step

Es gibt acht Phasen, mit denen der Motor angesteuert wird, also ach 
unterschiedliche Kombinationen von Signalen. Diese müssen der Reihe nach 
vorwärts oder Rückwärts durchlaufen werden, damit sich der Motor dreht.

Der step Parameter bestimmt, ob der nächste Schritt diese Phasen 
vorwärts oder rückwärts durchläuft.

In Falks Code ist sehr deutlich zu sehen, dass die Phase in der 
switch-case Anweisung ausgewertet wird und dass es acht Phasen gibt.

Step wird zur Phase addiert. Da Step nur die Werte 1 oder -1 haben darf, 
wird beim nächsten Schritt die Phase um eins erhöht oder verringert. 
Step bestimmt also die Laufrichtung des Motors.

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> Hi,
>
> ich meinte weil die Variable Im Kopf der Funktion deklariert und dannach
> direkt addiert wurde ohne einen wert. Das verwirrt mich etwas.

Ja, weil du nicht mal eine hauchdünne Ahnung von C hast. Das kann man 
aber durch lesen und verstehen eines C-Buches ändern.

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> ich steh grad bissel auf dem schlauch. Verstehe ich das richtig dass,
> phase + step immer der case ist in dem das Programm sich gerade
> befindet. Wenn ja wozu brauche ich dann step

Bist du so merkbefreit oder ein Troll?

von Sicajo (Gast)


Lesenswert?

Wieso bist du denn jetzt so gemein?
Bist du mit Profi Programmierkenntnissen geboren ? Wage ich stark zu 
bezweifeln. Nichts desto trotz danke für die Hilfe.

von Stefan F. (Gast)


Lesenswert?

Sicajo schrieb:
> Wieso bist du denn jetzt so gemein?

Ich glaube, er hat das nicht böse gemeint. Aber es dich damit wach 
rütteln und dir klar machen, dass du dich mit diesem Projekt übernommen 
hast. In Zeiten, wo alle im Internet immer "so einfach geht das" 
präsentieren, ist das leider ein zunehmendes Problem.

Mir war es zuerst bei Koch-Rezepten im TV aufgefallen. O-Ton "Ich habe 
da mal etwas vorbereitet". Danach griff es auf die Bücher über und jetzt 
eben auch aufs Internet. Alle wollen nur noch behaupten "schau mal, ich 
bin ein Superheld, ich kann das ganz schnell und für mich ist das ganz 
einfach". Die Leute lügen, was das Zeug hält. Sie wollen damit nur 
Klicks sammeln bzw. ihre Bücher verkaufen.

(Falls du ein ehrliches Kochbuch suchst: Das Dr. Ötker Schulkochbuch)

Fang klein an und arbeite ein Grundlagenbuch für C durch.

Wenn du 3 LED's unabhängig voneinander in unterschiedlichen Rythmen 
blinken lassen kannst (ohne Quellcode zu kopieren) bist du schon einen 
großen Schritt weiter. Danach fragst du zuerst einzelne Tasten (später 
eine Tastenmatrix) ab, die das Blinkmuster umschaltet.

Aber bilde Dir nicht ein, dass du das mit 2-3 Programmen an drei 
Wochenenden hinbekommen wirst. Da tastet man sich schrittweise heran. 
Wenn du dafür letztendlich 50 Programme schreibst, ist das durchaus 
normal.

von sicajo (Gast)


Lesenswert?

Hi

kennst du denn ein gutes C Buch?

Mfg

von Stefan F. (Gast)


Lesenswert?

sicajo schrieb:
> kennst du denn ein gutes C Buch?

Leider nein. Das Buch das ich lange empfohlen hatte bekommt man nicht 
einmal mehr im Antiquariat. Was da aktuell gut ist, weiß ich nicht.

von Frank (Gast)


Lesenswert?

sicajo schrieb:
> ich meinte weil die Variable Im Kopf der Funktion deklariert und dannach
> direkt addiert wurde ohne einen wert. Das verwirrt mich etwas. Aber da
> Sie ja auch farblich hinterlegt ist muss sie ja auch schon von selber
> eine Funktion haben oder ?

Falls Du damit die Variable 'phase' in den Funktionen Motor1()/Motor2() 
meinst: die wird sehr wohl initialisiert - und zwar automatisch mit dem 
Wert 0 (wegen der 'storage class' 'static')

static uint8_t phase;
ist also dasselbe wie
static uint8_t phase = 0;

von Falk B. (falk)


Lesenswert?


von sicajo (Gast)


Lesenswert?

Hi
Werde ich mal Rum stöbern, ob ich ein passables finde. Ich würde zwar 
nicht behaupten ich bin Anfänger, habe mich aber jedoch nie wirklich 
richtig damit befasst, sondern nur das was ich gerade gebraucht habe. 
Denke das ist das Problem und wird mal Zeit. Mal was anderes. Trau mich 
gar nicht zu fragen aber der OCR Wert "Timer_period" liegt bei 20000. Im 
Datenblatt Das Register hat 16Bit sprich 65536. Wie verhält sich der 
Wert zum Motor ? Da ich merke dass bei weitem nicht die ganze Kraft vom 
Motor benutzt wird. Sobald ich an diesem wert drehe passiert nicht 
wirklich was bis auf das der Motor Wackelt und Vibriert

Mfg

von sicajo (Gast)


Lesenswert?

Ich hoffe ihr könnt das aus euer Position sagen, da ihr den Motor ja 
nicht kennt

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> Hi
> Werde ich mal Rum stöbern, ob ich ein passables finde. Ich würde zwar
> nicht behaupten ich bin Anfänger,

Wer nicht mal die Grundzüge von Funktionen und deren Parametern 
verstanden hat, IST totaler Anfänger!

> habe mich aber jedoch nie wirklich
> richtig damit befasst, sondern nur das was ich gerade gebraucht habe.

So sieht's aus. Nie auch nur ansatzweise ein paar elementare Grundlagen 
verstanden und mit mehr Glück als Verstand irgendwie irgendwas zustande 
bekommen. Vor allem mit Copy & Paste.

> Denke das ist das Problem und wird mal Zeit.

Genau.

> Mal was anderes. Trau mich
> gar nicht zu fragen aber der OCR Wert "Timer_period" liegt bei 20000. Im
> Datenblatt Das Register hat 16Bit sprich 65536.

Das ist der mögliche Maximalwert! Man darf da auch kleinere Zahlen 
reinschreiben!

> Wie verhält sich der
> Wert zum Motor ?

Er bestimmt die Frequenz der Timer-ISR. Der Timer zählt diese Anzahl von 
Takten und löst dann einen Interrupt aus. Kleinerer Wert, kleinere 
Periodendauer, größere Frequenz. Pro Interrupt macht der Motor maximal 
einen Schritt, so ist es im Moment programmiert.

> Da ich merke dass bei weitem nicht die ganze Kraft vom
> Motor benutzt wird.

Wieso? Wie stellst du das fest?

> Sobald ich an diesem wert drehe passiert nicht

Was drehst du denn da? Auf welchen Wert verstellst du das? Wenn der Wert 
und damit die Periodendauer zu klein wird, verschluckt der Motor 
Schritte und wird schwächer.

von sicajo (Gast)


Lesenswert?

Falk B. schrieb:

> Das ist der mögliche Maximalwert! Man darf da auch kleinere Zahlen
> reinschreiben!

wäre der Maximalwert bei einem 16Bit Register nicht 65000?



> Wieso? Wie stellst du das fest?

der Code den ich vorher hatte, hat mehr Kraft am Motor bewirkt und war 
auch schneller


> Was drehst du denn da? Auf welchen Wert verstellst du das? Wenn der Wert
> und damit die Periodendauer zu klein wird, verschluckt der Motor
> Schritte und wird schwächer.

hab den wert erhöht.Wird wohl der Fehler sein wie du gesagt hast, wenn 
20000 der Maximalwert ist.

von Karl M. (Gast)


Lesenswert?

sicajo schrieb:
> wäre der Maximalwert bei einem 16Bit Register nicht 65000?

Nein - Kopfschüttel !

Die Zahl ist: 2^16-1 für einen uint16_t

von Falk B. (falk)


Lesenswert?

sicajo schrieb:
> Falk B. schrieb:
>
>> Das ist der mögliche Maximalwert! Man darf da auch kleinere Zahlen
>> reinschreiben!
>
> wäre der Maximalwert bei einem 16Bit Register nicht 65000?

Das Troll-O-Meter schläglt schon wieder mächtig aus!

>> Wieso? Wie stellst du das fest?
>
> der Code den ich vorher hatte, hat mehr Kraft am Motor bewirkt und war
> auch schneller

Glaub ich eher nicht.

> hab den wert erhöht.Wird wohl der Fehler sein wie du gesagt hast, wenn
> 20000 der Maximalwert ist.

OK, jetzt bist du endgültig bei 100% Trollfaktor angekommen. 
Glückwunsch! Und noch viel Spaß dabei.

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.