mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zwei Interrupts gleichzeitig Laufen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 
:)
 

uint16_t Schwellwert = 65400;
uint16_t Schwellwert1 = 65400;

void setup() 
{ 
 noInterrupts();
  
  TCCR1A = 0;
  TCCR1B = 0;

  TCCR2A = 0;
  TCCR2B = 0;

  TCNT1 = Schwellwert;
  TCCR1B |= (1 << CS12);
  TIMSK1 |= (1 << TOIE1);

  TCNT2 = Schwellwert1;
  TCCR2B |= (1 << CS12);
  TIMSK2 |= (1 << TOIE1);
  
  interrupts();


}
void loop()
{

  // Motor_Rueckwaerts_Links();
  // Motor_Rueckwaerts_Rechts();

  // Motor_Vorwaerts_Links();
  // Motor_Vorwaerts_Rechts();

  // Motor_Aus();

}


ISR(TIMER1_OVF_vect)
{
  TCNT1 = Schwellwert;
  
  Motor_Rueckwaerts_Rechts();

}


ISR(TIMER2_OVF_vect)
{
  TCNT2 = Schwellwert1;

  Motor_Rueckwaerts_Links();
} 

Autor: man oh man (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sicajo schrieb:
> Motor_Rueckwaerts_Rechts();

sicajo schrieb:
> Motor_Rueckwaerts_Links();

zeig bitte den code der funktionen

Autor: Viktor B. (coldlogic)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Horst (Gast)
Datum:

Bewertung
-3 lesenswert
nicht 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.

Autor: man oh man (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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. 
:->>>

Autor: DEELAY (Gast)
Datum:

Bewertung
3 lesenswert
nicht 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...

Autor: Jim M. (turboj)
Datum:

Bewertung
2 lesenswert
nicht 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.

Autor: malsehen (Gast)
Datum:

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

Autor: m.n. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: S. Landolt (Gast)
Datum:

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

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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

: Bearbeitet durch User
Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: S. Landolt (Gast)
Datum:

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

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

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... der Timer2 läuft doch viel zu schnell.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spielt das eine Rolle, wenn die Timer-Interrupts leicht versetzt 
synchron laufen?

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
So wie er die programmiert hat, ist aus dem "leicht versetzt" wohl zu 
viel Versatz geworden.

Autor: S. Landolt (Gast)
Datum:

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

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-1 lesenswert
nicht 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.

Autor: S. Landolt (Gast)
Datum:

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

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-1 lesenswert
nicht 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.

: Bearbeitet durch User
Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
2 lesenswert
nicht 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.

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: c-hater (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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!

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
c-hater schrieb:
> Zarter User? Heul' doch!

pfffft

Autor: Holger (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
c-hater schrieb:
> Zarter User? Heul' doch!

Großkotziger Hasser? Schäm dich!

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oje ich wollte kein Streit auslösen...

Autor: Holger (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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...

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sicajo schrieb:

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

Mach das.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-3 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
2 lesenswert
nicht 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? ;-)

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-3 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
2 lesenswert
nicht 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.

Autor: man oh man (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Falk B. schrieb:
> einem
> Minderwertigkeitskomplex.

+++ ja, so ist er.

Autor: man oh man (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@sicajo
wo ist der code???

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
-2 lesenswert
nicht 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?

: Bearbeitet durch User
Autor: man oh man (Gast)
Datum:

Bewertung
1 lesenswert
nicht 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!

Autor: Falk B. (falk)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Was für ein Kindergartentheater ;-)

Autor: Norbert S. (norberts)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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 ;-)

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
piep piep piep wir haben uns alle lieb.

Sorry etwas verspätet aber die der komplette Code :
 
/*   Schrittmotor Variablen deklaration   */

#define Rad_Links_I01 2
#define Rad_Links_I11 3
#define Rad_Links_PHASE1 4
#define Rad_Links_I02 7
#define Rad_Links_I12 6
#define Rad_Links_PHASE2 5

#define Rad_Rechts_I01 8
#define Rad_Rechts_I11 9
#define Rad_Rechts_PHASE1 10
#define Rad_Rechts_I02 13
#define Rad_Rechts_I12 12
#define Rad_Rechts_PHASE2 11

/*   Schrittmotor Variablen deklaration Ende   */

int zahl = 0;

uint16_t Schwellwert = 65200;  // Vergleichswert Für 16 Bit Register .

void setup() {

  Serial.begin(9600); // Serielle Verbingung Starten

  /*   Schrittmotor Pin konfiguration   */

  pinMode(Rad_Links_I01, OUTPUT);
  pinMode(Rad_Links_I11, OUTPUT);
  pinMode(Rad_Links_PHASE1, OUTPUT);
  pinMode(Rad_Links_I02, OUTPUT);
  pinMode(Rad_Links_I12, OUTPUT);
  pinMode(Rad_Links_PHASE2, OUTPUT);

  pinMode(Rad_Rechts_I01, OUTPUT);
  pinMode(Rad_Rechts_I11, OUTPUT);
  pinMode(Rad_Rechts_PHASE1, OUTPUT);
  pinMode(Rad_Rechts_I02, OUTPUT);
  pinMode(Rad_Rechts_I12, OUTPUT);
  pinMode(Rad_Rechts_PHASE2, OUTPUT);

  /*   Schrittmotor Pin konfiguration Ende   */

  noInterrupts(); // alle Interrupts löschen

  TCCR1A = 0; // TCCR1A Register auf null setzen
  TCCR1B = 0; // TCCR1B Register auf null setzen

  TCNT1 = Schwellwert;
  TCCR1B |= (1 << CS12);
  TIMSK1 |= (1 << TOIE1);

  interrupts(); // Interrupts Starten

}
void loop()
{

  if (zahl < 20)
  {
    zahl++;
    delay(500);
  }
  else
  {

    zahl = 0;

  }

  Serial.println(zahl);


  /*   Motor Ansteuerung zufuß   */

   //  Motor_Rueckwaerts_Links();
   //  Motor_Rueckwaerts_Rechts();

   //  Motor_Vorwaerts_Links();
   //  Motor_Vorwaerts_Rechts();

    // Motor_Aus();

        


}

/*   Interrupt Routine Rad Rechts   */

ISR(TIMER1_OVF_vect)
{
  TCNT1 = Schwellwert;

  if ( zahl >=  10 )
  {

    Motor_Vorwaerts_Rechts();

  } else
  {

    Motor_Rueckwaerts_Rechts();

  }
}

/*   Interrupt Routine Ende  */ 


und hier die Funktionen
 


static char Drehphase; //Static behält den Wert, auch wenn die Funktion beendet wurde -> permanent im Speicher wie globale Variable

void Motor_Vorwaerts_Links() {

  switch (Drehphase)
  {
    case 0:
      //Phase 1
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 1:
      //Phase 2
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, HIGH);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, LOW);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 2:
      //Phase 3
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 3:
      //Phase 4
      digitalWrite(Rad_Links_I01, LOW);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, HIGH);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 4:
      //Phase 5
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 5:
      //Phase 6
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, HIGH);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, LOW);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 6:
      //Phase 7
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 7:
      //Phase 8
      digitalWrite(Rad_Links_I01, LOW);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, HIGH);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;


  }
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
  {
    Drehphase++;


  }
  else
  {
    Drehphase = 0;
  }


}


void Motor_Vorwaerts_Rechts() {

  switch (Drehphase)
  {

    case 0:
      //Phase 9
      digitalWrite(Rad_Rechts_I01, LOW);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, HIGH);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 1:
      //Phase 10
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 2:
      //Phase 12
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, HIGH);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, LOW);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 3:
      //Phase 13
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 4:
      //Phase 14
      digitalWrite(Rad_Rechts_I01, LOW);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, HIGH);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 5:
      //Phase 15
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 6:
      //Phase 16
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, HIGH);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, LOW);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 7:
      //Phase 17
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;



  }
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
  {
    Drehphase++;


  }
  else
  {
    Drehphase = 0;
  }


}

void Motor_Rueckwaerts_Links() {

  switch (Drehphase)
  {
    case 0:
      //Phase 1
      digitalWrite(Rad_Links_I01, LOW);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, HIGH);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 1:
      //Phase 2
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 2:
      //Phase 3
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, HIGH);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, LOW);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 3:
      //Phase 4
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, HIGH);
      break;

    case 4:
      //Phase 5
      digitalWrite(Rad_Links_I01, LOW);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, HIGH);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 5:
      //Phase 6
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, LOW);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 6:
      //Phase 7
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, HIGH);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, LOW);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

    case 7:
      //Phase 8
      digitalWrite(Rad_Links_I01, HIGH);
      digitalWrite(Rad_Links_I11, LOW);
      digitalWrite(Rad_Links_PHASE1, HIGH);
      digitalWrite(Rad_Links_I02, HIGH);
      digitalWrite(Rad_Links_I12, LOW);
      digitalWrite(Rad_Links_PHASE2, LOW);
      break;

  }
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
  {
    Drehphase++;
  }
  else
  {
    Drehphase = 0;
  }

}

void Motor_Rueckwaerts_Rechts() {

  switch (Drehphase)
  {
    case 0:
      //Phase 9
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 1:
      //Phase 10
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, HIGH);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, LOW);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 2:
      //Phase 11
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 3:
      //Phase 12
      digitalWrite(Rad_Rechts_I01, LOW);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, HIGH);
      digitalWrite(Rad_Rechts_PHASE2, LOW);
      break;

    case 4:
      //Phase 13
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 5:
      //Phase 14
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, HIGH);
      digitalWrite(Rad_Rechts_PHASE1, LOW);
      digitalWrite(Rad_Rechts_I02, LOW);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 6:
      //Phase 15
      digitalWrite(Rad_Rechts_I01, HIGH);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, LOW);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;

    case 7:
      //Phase 16
      digitalWrite(Rad_Rechts_I01, LOW);
      digitalWrite(Rad_Rechts_I11, LOW);
      digitalWrite(Rad_Rechts_PHASE1, HIGH);
      digitalWrite(Rad_Rechts_I02, HIGH);
      digitalWrite(Rad_Rechts_I12, HIGH);
      digitalWrite(Rad_Rechts_PHASE2, HIGH);
      break;



  }
  if (Drehphase < 7)  //Position im Zeitverlaufdiagramm mit Halbschrittbetrieb
  {
    Drehphase++;
  }
  else
  {
    Drehphase = 0;
  }

}


void Motor_Aus() {

  digitalWrite(Rad_Links_I01, HIGH);
  digitalWrite(Rad_Links_I11, HIGH);
  digitalWrite(Rad_Links_I02, HIGH);
  digitalWrite(Rad_Links_I12, HIGH);
  digitalWrite(Rad_Links_PHASE1, HIGH);
  digitalWrite(Rad_Links_PHASE2, HIGH);

  digitalWrite(Rad_Rechts_I01, HIGH);
  digitalWrite(Rad_Rechts_I11, HIGH);
  digitalWrite(Rad_Rechts_I02, HIGH);
  digitalWrite(Rad_Rechts_I12, HIGH);
  digitalWrite(Rad_Rechts_PHASE1, HIGH);
  digitalWrite(Rad_Rechts_PHASE2, HIGH);
  
} 


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

Autor: m.n. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh!

Welchen Motor verwendest Du und mit welchem Treiber?

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rohrzange (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: m.n. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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.
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.

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: Rohrzange (Gast)
Datum:

Bewertung
1 lesenswert
nicht 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?

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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!

Autor: Rohrzange (Gast)
Datum:

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

Ack.

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rohrzange (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Rohrzange (Gast)
Datum:

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

Ohne Rampe sicher sportlich.

Beitrag #5840298 wurde vom Autor gelöscht.
Autor: Falk B. (falk)
Datum:
Angehängte Dateien:

Bewertung
1 lesenswert
nicht 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.

Autor: Rohrzange (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Falk B. schrieb:
> Soo, ich hab das Konstrukt mal aufgeräumt

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

Autor: sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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

Autor: sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
achso das habe ich auch nicht ganz verstanden

 if ( schrittM2 ) {
    Motor2(schrittM2);
    schrittM2 = 0;
  } 

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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?
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.
phase = phase + step;
if (phase > 7) phase -= 7;
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.

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Holger (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> step=+1

step += 1

bzw. weiter unten

step -= 1

:-)

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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.

: Bearbeitet durch User
Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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?

Autor: Sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
1 lesenswert
nicht 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.

: Bearbeitet durch User
Autor: sicajo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

kennst du denn ein gutes C Buch?

Mfg

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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

Autor: sicajo (Gast)
Datum:

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

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: sicajo (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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.

Autor: Karl M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk B. (falk)
Datum:

Bewertung
1 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.