Schrittmotor Steuerung Atmega16 Interrupt Problem

OP #2365976
Lesenswert?

Hallo,
Ich will drei Schrittmotoren ueber den Druckerausgang meines Computers 
steuern.
Das Signal aus dem Druckerausgang kommt auch am Atmega16 an, und loest 
dort auch das Interrupt aus (Die LED an PB4 blinkt). Allerdings wird 
"xstepin" anscheinend nicht gesetzt , da die IF Anweisung unter "//X 
Step Direction 0" anscheinend nicht ausgeloest wird (Die LED an PC4 
blinkt nicht).
Reicht es nicht das "xstepin" global als Volatile int deklariert ist?
Tut mit leid das ich euch einfach den ganzen Code vor die Fuesse werfe, 
aber so kann es nicht passieren das der Fehler vielleicht doch wo anders 
ist ;)
Falls ihr allerdings Fehler bei Y und Z findet koennt ihr diese 
ersteinmal ignorieren. Im Moment beschraenke ich mich nur auf X um dort 
den Fehler zu finden.
Vielen Dank schonmal fuer die Hilfe ;)
Angehängte Dateien:
OP #2369604
Lesenswert?

Das Problem muss irgendwo in diesem Bereich liegen:
Ich hab es leider immernoch nicht gefunden.

1
#ifndef F_CPU
2
#define F_CPU 4000000 
3
#endif
4

5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <avr/interrupt.h>
8

9
//Globale Variablen
10
volatile int xstepin=0;
11

12

13
////////////////////////////////INT0 Interrpt////////////////////////////////////////////
14
ISR(INT0_vect)
15
  {
16
  xstepin=1; // xstep ausloesen
17
  PORTB|=(1<<PB4);//StatusLED Controllerboard
18
  _delay_ms(50);
19
  reti();
20
  }
21

22

23
////////////////////////////////MAIN////////////////////////////////////////////////////////////
24
int main()
25
{  
26
  
27
  DDRA=0xFF; //Ausgang A
28
  DDRC=0xFF; //Ausgang C
29
  DDRB=0xFF; //Ausgang B  
30

31
  DDRD=0x00; //Eingang D
32
  DDRB&=~(1<<PINB2); //Eingang Pin B2 (INT2)
33
  PORTC=0x00;
34

35
  //lokale Variablen
36
  int xdir=0,xstep=0;
37

38

39
/////////////////////////////////////INTERRUPTS/////////////////////////////////////////////////////        
40
  //interrups deaktivieren
41
  cli();
42

43

44
////////////////INT0///////////////////////////////////////
45
  // interrupt bei steigender flanke an INT0 
46
  MCUCR |= ((1<<ISC01) | (1<<ISC00));
47

48
  // INT0 als Interrupt Pin aktivieren 
49
    GICR |= (1<<INT0);
50
////////////////INT1//////////////////////////////////////
51
  //Interrupt bei steibender Flanke an INT1
52
    MCUCR |=((1<<ISC11) | (1<<ISC10));
53
  
54
  //INT1 als Interrupt Pin aktivieren
55
  GICR |=(1<<INT1);
56

57
///////////////INT2////////////////////////////////////////
58
  //Interrupt bei steigender Flanke an INT2
59
  MCUCSR|=(1<<ISC2);
60
  
61
  //INT 2 als Interript Pin aktivieren
62
  GICR |=(1<<INT2);
63
///////////////////////////////////////////////////////////
64

65
  // Interrupts aktivieren
66
    sei();
67

68
///////////////////////////////////WHILE SCHLEIFE/////////////////////////////////////////////////
69

70
      PORTB&=~(1<<PB4);
71

72
/////////////////////////////////////////////X///////////////////////////////////////////////////////////////////
73
      
74
    ////////////////X direction //////////////////////////////////
75
    if(PIND&(1<<PIND5))
76
      {
77
      xdir=1;
78
      
79
      }
80
      else
81
      {
82
      xdir=0;
83
      
84
      
85
      }
86
      ///////////////////////////X Step Direction 0/////////////////////////////////// 
87
    if(xstepin==1&&xdir==0)
88
      {
89
      if(xstep==0&&xstepin==1)
90
        {
91
        PORTC|=(1<<PC0);
92
        _delay_ms(50);//Pause
93
        xstep++;
94
        xstepin=0;
95
        PORTC&=~(1<<PC0);
96
        }
97
      else
98
      if(xstep==1&&xstepin==1)
99
        {
100
        PORTC|=(1<<PC1);
101
        _delay_ms(50);//Pause
102
        xstep++;
103
        xstepin=0;
104
        PORTC&=~(1<<PC1);
105
        }
106
      else
107
      if(xstep==2&&xstepin==1)
108
        {
109
        PORTC|=(1<<PC2);
110
        _delay_ms(50);//Pause
111
        xstep++;
112
        xstepin=0;
113
        PORTC&=~(1<<PC2);
114
        }
115
      else
116
      if(xstep==3&&xstepin==1)
117
          {
118
        PORTC|=(1<<PC3);
119
        PORTC|=(1<<PC4);// StatusLED stepperdriverboard X
120
        _delay_ms(50);//Pause
121
        PORTC&=~(1<<PC4);
122
        xstep=0;
123
        xstepin=0;
124
        PORTC&=~(1<<PC3);
125
        }
126
            
127
      }
128
        
129
////////////////////////////////Xstep Direction 1/////////////////////////////////////////////
130
       
131
      if(xstepin==1&&xdir==1)
132
      {
133
      if(xstep==3&&xstepin==1)
134
        {
135
        PORTC|=(1<<PC0);
136
        _delay_ms(100);//Pause
137
        xstep=0;
138
        xstepin=0;
139
        PORTC&=~(1<<PC0);
140
        }
141
      else
142
      if(xstep==2&&xstepin==1)
143
        {
144
        PORTC|=(1<<PC1);
145
        _delay_ms(100);//Pause
146
        xstep++;
147
        xstepin=0;
148
        PORTC&=~(1<<PC1);
149
        }
150
      else
151
      if(xstep==1&&xstepin==1)
152
        {
153
        PORTC|=(1<<PC2);
154
        _delay_ms(100);//Pause
155
        xstep++;
156
        xstepin=0;
157
        PORTC&=~(1<<PC2);
158
        }
159
      else
160
      if(xstep==0&&xstepin==1)
161
          {
162
        PORTC|=(1<<PC3);
163
        PORTC|=(1<<PC4);// StatusLED stepperdriverboard X
164
        PORTC&=~(1<<PC4);
165
        xstep++;
166
        _delay_ms(100);//Pause 
167
        xstepin=0;
168
        PORTC&=~(1<<PC3);
169
        }
170
            
171
      }
172

173

174

175
//////////////////////////////////////////////////////////////////////////////////////////////////////////
176
    
177
  } 
178
  return 0;
179

180
}
Gast #2369641
Lesenswert?

>Das Problem muss irgendwo in diesem Bereich liegen:
>Ich hab es leider immernoch nicht gefunden.

Code weiter reduzieren bis das Problem nicht mehr auftritt.
1
////////////////////////////////INT0 Interrpt////////////////////////////////////////////
2
ISR(INT0_vect)
3
  {
4
  xstepin=1; // xstep ausloesen
5
  PORTB|=(1<<PB4);//StatusLED Controllerboard
6

7
// Pfui bäh. 
8
  _delay_ms(50); 
9

10
// Sofort entsorgen
11
  reti();
12
  }
1
      if(xstepin==1&&xdir==0)
2
      {
3
//xstepin ist hier 1. Eine weitere Abfrage ist überflüssig.
4
      if(xstep==3)
5
        {
6
        }.....
1
// xdir konstant auf 0 setzen bis das Problem gefunden ist
2
// Code für xdir=1; entfernen
3
      xdir=0;

INT 1 und 2 nicht aktivieren!

JTAG Fuse abgeschaltet?
OP #2400700
Lesenswert?

Hi,
Ich habe das Problem glaube ich gefunden, weiss aber nicht wie ich es 
beseitigen kann.
Obwohl xstepin global ist, wird es in der main Funktion nicht als "1" 
erkannt.
Allerdings bin ich mir sicher das das Interrupt ausgeloest wird und 
xstepin=1 gesetzt wird.
Woran liegt das?
#2442873
Lesenswert?

@MG

Ich nehme Teile zurück. Ich hab mich nur auf die weiter unten geposteten 
COdeteile konzentriert und nicht gesehen, dass du ganz am Anfang den 
kmkopletten Code gepostet hast.

Allerdings trifft für den das Argument des Restrukturierens noch mehr zu 
als, für den Ausschnitt.
#2442938
Lesenswert?

Probier das mal aus


Ich musste das so gut es ging, auf einer Mega16 Hardware nachstellen. 
Soweit funktioniert das auch alles.
Puls an PD2 schaltet den Motor 1 Schritt weiter. Der Pegel an PD5 
bestimmt ob vorwärts oder rückwärts.

PS: Bist du sicher, dass deine Schrittmotoren mit Pulsen zufrieden sind? 
Die haben ja dann gar kein Haltemoment mehr! Bei einem Schrittmotor 
steht immer 1 (im Vollschrittbetrieb) Wicklung unter Strom. Ein Puls 
alleine reicht da nicht. Ich hab das mal auf Dauerbestromung einer 
Wicklung umgebaut.

Den _delay_ms in der ISR hab ich drinnen gelassen, damit du deine LED 
flackern siehst. Die wird dann ja sowieso rausfallen und mit ihr der 
_delay
Angehängte Dateien:
#2442987
Lesenswert?

Ich hab den Code noch ein bischen weiter aufgeräumt und angedeutet wie 
er jetzt auf die restlichen beiden Achsen verallgemeinert.

Man könnte da noch mehr einsparen, und den Code noch kürzer formulieren. 
Zb. in dem man die Motoranschlüsse in Arrays legt, dann braucht man 
keine 3 gerennten Motor Funktionen mehr, sondern 1 Funktion erledigt das 
für alle 3 Motoren. X, Y und Z Ansteuerung könnte man als Indizes in 
Arrays auffassen usw. usw. Mit ein bischen guten Willen könnte man den 
Code in Summe auf leicht unter 100 Zeilen bringen ohne dass er 
unübersichtlich oder besonders trickreich wird.
Im Moment hab ich mich aber dagegen entschieden, damit du ihn noch 
durchschauen kannst.
Angehängte Dateien:
OP #2443017
Lesenswert?

WOOW!
Danke das du dich so umfassend mit meinem Problem beschaeftigt hast !
Tut mir leid das das Programm so unleserlich und fehlerhaft geworden 
ist.
Leider bin ich (noch) kein guter Programmierer.
Ich hab dein Programm mit einem Lauflicht und mit dem Schrittmotor 
ausprobiert und es scheint zu funktionieren.
Allerdings liegt an PC0 nie Spannung an. Aber das muss jetzt ja an 
meinem Controller liegen nehme ich an.
Vielein Dank nochmal!
#2443025
Lesenswert?

> Leider bin ich (noch) kein guter Programmierer.

Drum mach ich mir ja auch die Arbeit, damit du siehst wie man solche 
Dinge machen kann, ohne dass alles gleich in eine if-else Orgie über 8 
Seiten ausartet.

Bischen nachdenken, bischen Planung, ein paar Hilfsfunktionen und schon 
dampft der Code in der Länge ordentlich ein. Was dann auch der Übersicht 
zu gute kommt.
#2443030
Lesenswert?

Hast du Y und Z schon aktiv?

Da hab ich einen COpy&Paste Fehler.
(ICh hätte doch die Variante mit einer Funktion für alle Motoren machen 
sollen :-)
1
void MotorZ( uint8_t Nr )
2
{
3
  MOTOR_X_PORT &= ~( (1<<PHASE_Z_0) | (1<<PHASE_Z_1) |
4
                     (1<<PHASE_Z_2) | (1<<PHASE_Z_3) );

Muss natürlich MOTOR_Z_PORT heissen und nicht MOTOR_X_PORT

Überhaupt: Wenn du dann die Dinge für Y und Z einkommentierst, nicht 
blind darauf vertrauen, dass ich alles richtig gemacht habe. Ich hab das 
grossteils nur kopiert und X gegen Y resp. Z ausgetauscht. Da passiert 
es schon mal, dass man was übersieht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren