Forum: Mikrocontroller und Digitale Elektronik Schrittmotor ansteuern über Timerinterrupt


von cyberfoxx (Gast)


Lesenswert?

Hallo,
ich steuere einen Schrittmotor über einen L297 und 2x L6203 an. Über 
einen Timerinterrupt (Timer0 eines ATmega2561) toggle ich den CLK-Pin 
des L297. Bei einem Prescaler von 64 funktioniert dies noch problemlos. 
Bei einem Prescaler von 8 auch, sofern ich nur bei jedem 8. Timeraufruf 
das Signal toggle (--> theoretisch wieder ein Prescaler von 8x8=64). 
Wenn ich allerdings den Prescaler auf 1 setze und das Signal nur jeden 
64. Aufruf toggle ruckelt der Schrittmotor und lauft nicht mehr ruhig. 
Außerdem steigt auch der Stromverbrauch von ca 0.65A auf 2.5A.

Kann sich jemand von euch das Phänomen erklären?
danke, cyberfoxx

PS:
so sieht die Interruppt-Routine aus:
1
ISR(TIMER0_OVF_vect)
2
  {
3
  cnt_t0++;
4
  if(cnt_t0>=64)
5
    {
6
    if(PORTC%2) PORTC&=0xFE; //auf PC0 befindet sich der CLK-Pin des L297
7
    else PORTC|=0x01;
8
    }
9
  }

von Willi (Gast)


Lesenswert?

Togglen und Ruckeln ist so eine Sache.
Irgendwie müßte man wissen, um welche Frequenzen es geht oder gehen 
soll.
Aber laß Dir Zeit, wir raten gerne.

von cyberfoxx (Gast)


Lesenswert?

ich verwende einen 16MHz Quarz aber ich bin mir nicht sicher ob ich 
schon alles richtig eingestellt habe (Hab bei den fuses CLKDIV8 
deaktiviert und "Ext. Crystal Osc.; Frequency 8.0- MHz; Start-up time: 
16K CK + 65 ms" eingestellt. Muss man sonst noch was machen?). Aber 
unabhängig von der Frequenz müsste F_CPU/1/64 gleich F_CPU/8/8 und 
F_CPU/64/1 sein.

von Julian B. (julinho)


Lesenswert?

wie ist cnt_t0 deklariert, volatile?
wann wird cnt_t0 auf null gesetzt?
Codeschnipsel sind oft nicht sehr hilfreich, da der fehler auch wo andes 
versteckt sein kann.

von cyberfoxx (Gast)


Lesenswert?

ja direkt nach den defines
1
volatile unsigned int cnt_t0=0;
und in der main-Funktion vor der Endlosschleife wird die Funktion 
init_timer() aufgerufen in der die Variable 0 gesetzt wird.

von Julian B. (julinho)


Lesenswert?

muß nicht cnt_t0 nach erreichen von 64 auf 0 gesetzt werden??

von cyberfoxx (Gast)


Lesenswert?

upc.. habe ich vergessen zu kopieren... steht auch noch in der Routine.
Aber danke für die Idee ;-)

von Julian B. (julinho)


Lesenswert?

welchen timermode verwendest du?
vielleicht steht in deiner icr-routine zu viel code, und das schafft er 
bei prescaler 1 nicht!
poste doch einfach den ganzen code, dann muß keiner in die glaskugel 
schauen :-)

von Cyberfoxx (Gast)


Lesenswert?

Habe jetzt einmal versucht auf das wichtigste zu minimieren und jetzt 
ist 64 endlich 64, egal wie ich den Prescaler erzeuge. Werde nun die 
einzelnen Code-Teile wieder einzeln ergänzen und hoffen dass es dann 
läuft. Falls es wieder Probleme gibt melde ich mich wieder hier. Danke 
euch allen für eure schnelle Hilfe

von Cyberfoxx (Gast)


Lesenswert?

So... Habe schon ein neues Problem an dem ich nun schon 2h hänge. Ich 
habe eine Rampe über die ich den Schrittmotor beschleunige. Wenn ich die 
Schaltung an die Versorgung anhänge läuft mir der Motor manchmal auf die 
Solldrehzahl an doch meistens Ruckelt er nur ein bischen, bleibt stehen 
und die Schaltung zieht um die 3A (über die Sens-Widerstände ist der 
Strom auf 1,5A/Windung begrenzt) und manchmal sogar 5A (max. Strom des 
Netzgerätes). Wenn man die Versorgungsspannung entfernt und neu 
anschließt und der Motor schafft seinen Start benötigt die Schaltung bei 
voller Drehzahl des Motors nur 0.15A. Weiß einer von euch woran das 
liegen könnte? Muss der Motor vor dem Start auf die Home-Position 
gebracht werden?

Ich verwende übrigens einen 23LM-C077-02V 
(http://www.mechapro.de/pdf/23LM-C077V.pdf) und einwen ATmega2561. Anbei 
ist auch noch der vollständige C-Code ;-) (Leider ein wenig 'Dirty' aber 
ich hoffe ihr kennt euch aus):
1
#include <util/delay.h> //(bei älteren Versionen avr/delay.h)
2
#include <stdbool.h>
3
4
#include "lcd-routines.h"
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <stdlib.h>  // for itoa() call
8
#include <stdio.h>  // for printf() call
9
10
11
//globale variablen
12
//=================
13
  //Timer interrupt
14
  volatile unsigned int cnt_t0=0;    //interrupt zähler für Timer0
15
  volatile unsigned int rampe=80;
16
  volatile unsigned int cnt_rampe=0;
17
18
ISR(TIMER0_OVF_vect)
19
  {  //Schrittmotor-Interrupt
20
  
21
  cnt_t0++;
22
  
23
  
24
  
25
  if(cnt_t0>=rampe)  
26
    {
27
    cnt_rampe++;
28
    if(cnt_rampe>=200 && rampe>18) 
29
      {
30
      rampe--;
31
      cnt_rampe=0;
32
      }
33
34
    cnt_t0=0;
35
    //Schrittmotor ansteuern
36
    //######################  
37
    if(PORTC%2)
38
      {
39
      PORTC&=0xFE;
40
      }
41
    else
42
      {
43
      PORTC|=0x01;
44
      }
45
46
    }  
47
  }
48
49
void init_timer(void)
50
  {
51
  cli();             //Interrupt generell sperren
52
  
53
  //Timer0 initialisieren
54
  //=====================
55
  cnt_t0 = 0;
56
  cnt_rampe=0;
57
  rampe=80;
58
  TCCR0B=(1<<CS00); //CS0: no Prescaler=256;
59
  TIMSK0|=(1<<TOIE0);           //Overflow Interrupt einschalten
60
    
61
  sei();               //Interrupt generell zulassen
62
  }
63
    
64
void init_io(void)
65
  {
66
  //Ein/ Ausgänge setzen
67
  //====================
68
  
69
  DDRA =0xFF;      //PortA als ausgang Setzen
70
  DDRD|=0x03;     //PD0 und PD1 als ausgang setzen
71
  DDRC=0x0F;       //PC0 - PC3 als ausgang setzen, PC4-PC7 als eingang
72
  
73
  DDRG|=0x02;    //PG1 als Ausgang definieren
74
  PORTG&=0xFD;  //PG1 0 setzen --> immer write
75
  }
76
  
77
void init_stepmotor(void)
78
  {
79
  //PC1...CW/~CCW...   0 --> im Uhrzeigersinn
80
  //PC2...HALF/~FULL...0 --> ganzer schritt
81
  //PC3...CTL...       1 --> für ABCD
82
  PORTC=0x08;
83
  }
84
  
85
int main(void)
86
  {
87
  init_timer();
88
  init_io();
89
  lcd_init();
90
  init_stepmotor();
91
  
92
93
  lcd_write2pos(0,2,"Motor           ");
94
  lcd_write2pos(0,3,"startet!!       ");
95
  
96
  while(1)
97
    {
98
    //  auf interrupt warten
99
    }
100
return 0;    //never reach this!
101
}

von Julian B. (julinho)


Lesenswert?

mach deine rampe mal langsamer, vielleicht kommt der motor nicht mit?

von Cyberfoxx (Gast)


Lesenswert?

Nein nützt leider auch nichts

von Julian B. (julinho)


Lesenswert?

Cyberfoxx schrieb:
> if(PORTC%2)
>       {
>       PORTC&=0xFE;
>       }
>     else
>       {
>       PORTC|=0x01;
>       }

kann man auch so schreiben: PORTC ^=0xff

warum weden alle bits  von PORTC getoggelt?

von cyberfoxx (Gast)


Lesenswert?

werden sie doch nicht:
0xFE=0b11111110
und (0bxxxxxxxx)&(0b11111110)=(0bxxxxxxx0)

0x01=0b00000001
und(0bxxxxxxxx)|(0b00000001)=(0bxxxxxxx1)

somit wird nur PC0 getogglet

von Julian B. (julinho)


Lesenswert?

stimmt!
PORTC ^=0x01 wäre richtig!

von cyberfoxx (Gast)


Lesenswert?

So gehts natürlich einfacher (kürzer). Habe noch nie die 
bitweise-XOR-Funktion verwendet deswegen kam ich auch gar nicht auf die 
Idee nach soetwas zu suchen. Vielen dank für diese Verschönerung aber 
das Problem löst dies leider noch nicht ;-)

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.