Forum: Mikrocontroller und Digitale Elektronik Ansteuerung Schrittmotor mit ATmega8 macht Probleme


von Daniel L. (dannynrw)


Lesenswert?

Hi Leutz,
hatte ja vor kurzem angefangen, meine ersten Erfahrungen mit der 
Schrittmotoransteuerung + L293D zu machen. Hatte schon ein fertiges 
Programm auf dem AVR-Testboard geschrieben, welches ja mit dem externen 
Quarz auf 3,68MHz lief. Nun sollte der ATmega8 in eine Schaltung 
eingesetzt werden, welche natürlich ohne diesen Quarz läuft. Habe also 
die Fusebits gesetzt und den ATmega8 auf 8Mhz eingestellt. Nun 
funktioniert zwar die Ansteuerung des Schrittmotors noch (mit Anpassung 
der Ansteuerungszeiten), nur leider die IF-Schleife (diese zählt 132 
Schritte), die den Schrittmotor an einem bestimmten Punkt anhalten soll, 
nicht mehr.
Es ist als würde es diese Schleife überhaupt nicht mehr geben.
Ist der ATmega8 ohne externen Quarz so schnell überfordert?
Was kann ich vielleicht noch tun, damit ich die schöne fertige Platine 
nicht in die Tonne treten kann?

Beste Grüße.
Daniel

von Stryker (Gast)


Lesenswert?

Daniel Lo schrieb:
> IF-Schleife

Siehe: http://www.if-schleife.de/

Div8 Fusebit möglicherweise übersehen?
Ansonsten kann man zu deiner "Schleife" ohne Code nichts sagen...

von Daniel L. (dannynrw)


Lesenswert?

Das Fusebit Div8 wird mir beim ATmega8 gar nicht angeboten, habe ich 
auch schon nach gesucht. Schalte ich um auf z.B. den ATTiny13, ist 
dieses Bit wieder sichtbar.
Hier mal ein Auszug des Quellcodes...
Die Variablen sind alle global deklariert worden und wie schon gesagt, 
MIT dem Quarz lief das Programm einwandfrei ab.

if (w<132)
{

  PORTB=0b00000101;        //1.Schritt
    for (a=0;(a<130);a++)
    {
    }

      PORTB=0b00000001;    //1.Halbschritt
      for (a2=0;(a2<130);a2++)
      {
      }

  PORTB=0b00001001;        //2.Schritt
    for (b=0;(b<130);b++)
    {
    }

      PORTB=0b0001000;    //2.Halbschritt
      for (b2=0;(b2<130);b2++)
      {
      }

  PORTB=0b00001010;        //3.Schritt
    for (c=0;(c<130);c++)
    {
    }

      PORTB=0b00000010;    //3.Halbschritt
      for (c2=0;(c2<130);c2++)
      {
      }

  PORTB=0b00000110;        //4.Schritt
    for (d=0;(d<130);d++)
    {
    }

      PORTB=0b00000100;    //4.Halbschritt
      for (d2=0;(d2<130);d2++)
      {
      }


  w++;
  }

von Dietrich L. (dietrichl)


Lesenswert?

Vermutlich ist das Timing falsch!
Mess mal die Zeiten am Port (mit Oszi) und vergleiche sie mit den Zeiten 
bei der 3,68MHz-Quarz-Version. Dann kannst Du auf den tatsächlichen Takt 
"ohne diesen Quarz" schließen und die Warteschleifen (oder den Takt) 
entsprechend anpassen.

Gruß Dietrich

von Daniel L. (dannynrw)


Lesenswert?

Das Problem sind ja anscheinend nicht einmal die Zeiten... Ich habe 
probeweise mal den Wert der IF-Abfrage auf <1 heruntergesetzt. Der Motor 
dreht durch bis in den mechanischen Anschlag und stoppt gar nicht mehr.
Eben so als gäbe es diese IF-Abfrage überhaupt nicht. Setze ich hingegen 
die IF-Abfrage auf >1, so tut sich gar nichts (was ja auch in diesem 
Falle richtig wäre). Es sieht für mich so aus als würde die Anweisung 
w++; überhaupt nicht mehr richtig bearbeitet...

von Udo S. (urschmitt)


Lesenswert?

Hmm, meine Glaskugel sagt mir du hast R12 falsch herum eingelötet und 
bei C3 Kapazitäts und Spannungswert vertauscht.
Aber diese modernen Murmeln haben inzwischen so hohe Auflösungen bei 
kleinem Durchmesser. Vieleicht sehe ich das ohne meine Brille nicht so 
richtig?

Ach ja die Variable k muss volatile sein.

von Hartmut W. (killozap)


Lesenswert?

Kannst du das Programm nicht in den Simulator packen und dort mal 
Schritt für Schritt abarbeiten lassen?

Ich hatte ein sehr ähnliches Problem, es wurde verzweigt, obwohl die 
abgefragte Variable den Wert gar nicht hatte.

die Abfrage war:

cpi r16,1
breq Label1

Variable r16 war 0, aber es wurde trotzdem nach Label 1 gesprungen ...

Das Problem war eine Interrupt-Routine, die auch mal zwischen dem 
CPI-Befehl und dem BREQ-Befehl eigeschoben wurde und die Statusregister 
verändert hatte ...

von Stryker (Gast)


Lesenswert?

Daniel Lo schrieb:
> for (d2=0;(d2<130);d2++)
>       {
>       }

wurde möglicherweise "wegoptimiet"... steht da wirklich nichts drin? 
Kein Delay etc? Falls dem so ist "flackert" wömöglich die Pins einmal 
kurz durch und der L293 denkt sich seinen teil...

von Daniel L. (dannynrw)


Lesenswert?

In der For-Schleife steht nichts drin, da dort ja nur Zeit verbraten 
werden soll. Der Ausdruck ist also quasi das Delay. Die Ansteuerung 
selbst ist sowohl mit als auch ohne Quarz (mit anderen Werten in den 
jeweiligen FOR-Schleifen) möglich, nur die IF-Abfrage funktioniert nicht 
mehr!

von Karl H. (kbuchegg)


Lesenswert?

Daniel Lo schrieb:
> In der For-Schleife steht nichts drin, da dort ja nur Zeit verbraten
> werden soll. Der Ausdruck ist also quasi das Delay.

Und das ist, mit Verlaub gesagt, einfach nur Scheisse.

Wenn du tatsächlich einfach nur Zeit verbraten willst, gibt es die 
Funktionen _delay_ms() bzw. _delay_us()


F_CPU eintragen, die gewünschte Zeit beim Aufruf angeben, sicher 
stellen, dass die Compiler-Optimierungen an sind und die Zeiten stimmen. 
Egal bei welcher Taktfrequenz.


 >>> AVR-GCC-Tutorial <<<

1
#define F_CPU 8000000UL
2
3
#include <util/delay.h>
4
5
#define STEP_DELAY  10
6
7
....
8
9
  while( 1 ) {
10
11
    ...
12
13
    if (w<132)
14
    {
15
      PORTB = 0b00000101;        //1.Schritt
16
      _delay_ms( STEP_DELAY );
17
      PORTB = 0b00000001;    //1.Halbschritt
18
      _delay_ms( STEP_DELAY );
19
      PORTB = 0b00001001;        //2.Schritt
20
      _delay_ms( STEP_DELAY );
21
      PORTB = 0b0001000;    //2.Halbschritt
22
      _delay_ms( STEP_DELAY );
23
      PORTB = 0b00001010;        //3.Schritt
24
      _delay_ms( STEP_DELAY );
25
      PORTB = 0b00000010;    //3.Halbschritt
26
      _delay_ms( STEP_DELAY );
27
      PORTB = 0b00000110;        //4.Schritt
28
      _delay_ms( STEP_DELAY );
29
      PORTB = 0b00000100;    //4.Halbschritt
30
31
      w++;
32
    }
33
    ....
34
  }

von Stryker (Gast)


Lesenswert?

Kannst du ausschließen, dass der Compiler diese Schleifen nicht 
auslässt, da er erkennt, das darin nichts passiert?

Toggel in den Schleifen doch einmal einen Pin, falls du noch einen 
unbenutzen frei hast...

Alternativ ersetze die For-Schleifen doch mal durch die delay()...

Ansonsten können wir schlecht erkennen, warum er ggf. die IF auslässt 
ohne kompletten Code... w ist zu Beginn 0 oder 1, denke ich?

von Ben _. (burning_silicon)


Lesenswert?

> Das Problem war eine Interrupt-Routine, die auch mal zwischen dem
> CPI-Befehl und dem BREQ-Befehl eigeschoben wurde und die
> Statusregister verändert hatte ...
Tjo, deswegen sollten Interruptroutinen IMMER das Statusregister mit den 
Flags sichern. Schade, daß der AVR dafür keinen einzelnen Befehl hat wie 
der x86 (der kennt PUSHF/POPF).

von Dietrich L. (dietrichl)


Lesenswert?

Daniel Lo:
Hast Du die Optimierung des Compilers schon mal abgeschaltet? Stryker 
hat schon mehrmals darauf hingewiesen!

Gruß Dietrich

von Daniel L. (dannynrw)


Lesenswert?

So, hab's jetzt einfach mal mit der Delay-Variante probiert. Das 
Ergebnis ist leider dasselbe wie bei der FOR-Variante. Die Variable w 
habe ich ganz zu anfangs einmalig auf den Startwert 0 gesetzt. Gibt es 
eine Möglichkeit, die Compileroptimierung abzuschalten beim 
MyAVR-Workpad Plus?

von Stryker (Gast)


Lesenswert?

Daniel Lo schrieb:
> Gibt es
> eine Möglichkeit, die Compileroptimierung abzuschalten beim
> MyAVR-Workpad Plus?

Siehe myavr.info/myforum/viewtopic.php?p=5048

Wie aber nun die Parameter sind hängt von deinem verwendeten Compiler ab 
- hier ist Google dein Freund.

Aber falls das delay das tut, was es sollte hilft dir das hier leider 
nicht.
Teste das Delay doch am besten einmal mit einer LED die nach 1Sek. 
angeht. Ich bin mir ziemlich sicher, dass es am Timing in Kombination 
mit dem "durchflitzen" der If-Anweisung liegt.

Das wird schon noch ;-)

von Karl H. (kbuchegg)


Lesenswert?

Daniel Lo schrieb:
> So, hab's jetzt einfach mal mit der Delay-Variante probiert. Das
> Ergebnis ist leider dasselbe wie bei der FOR-Variante. Die Variable w
> habe ich ganz zu anfangs einmalig auf den Startwert 0 gesetzt.

Zeig deinen Code. Beschreib ihn nicht.

> Gibt es
> eine Möglichkeit, die Compileroptimierung abzuschalten beim
> MyAVR-Workpad Plus?

Das ist kontraproduktiv.
Wenn du richtig programmierst, brauchst du die Optimierung nicht 
abzuschalten.
Du willst die Optimierung behalten! Also musst du richtig programmieren.

von Daniel L. (dannynrw)


Lesenswert?

So...
nach Stunden über Stunden der Sucherei hab ich nun einfach die Fusebits 
mit MyAVR-Progtool nochmals geschrieben anstatt mit MyAVR-Workpad Plus. 
Und siehe da... es läuft!!! (ich könnt kotzen...)
Habe ihn jetzt auf 2 MHz zum Test laufen lassen und nun funktionert er 
auch in der Schaltung, wenn auch langsamer.
Werde jetzt nochmal die Taktrate umstellen und die Zeiten anpassen.
Mal ne Frage in die Runde. Sind Fehler bezüglich der Fusebits in 
Verbindung mit dem MyAVR Workpad Plus bekannt?
Habe die Version 1.5 (Build 3304).

Danke für die vielen Tipps!
Daniel

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.