Forum: Mikrocontroller und Digitale Elektronik Schrittmotor Steuerung Atmega16 Interrupt Problem


von M. G. (elch)


Angehängte Dateien:

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 ;)

von M. G. (elch)


Lesenswert?

Ich habe auch schon Versucht die komplette Ansteuerung de Motors in das 
Interrupt zu schreiben, auch wenn man das vielleicht nicht unbedingt 
machen sollte.
Aber das hat auch nicht funktioniert.

von M. G. (elch)


Lesenswert?

Hat keiner eine Idee was das Problem sein koennte ?

von M. G. (elch)


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
}

von holger (Gast)


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?

von M. G. (elch)


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?

von Leo Pard (Gast)


Lesenswert?

volatile vergessen?

von M. G. (elch)


Lesenswert?

1
volatile int xstepin=0;

Das volatile ist da. Aber es klappt trotzdem nicht.

von Paul (Gast)


Lesenswert?

Ich hab das selbe Problem.
Das kann doch nur eine Kleinigkeit sein.

von M. G. (elch)


Lesenswert?

Hi,
Das Thema beschaeftigt mich immernoch xD
Und deshalb bin ich auf diesen Artikel gestossen:
Beitrag "WINAVR, Optimierung, Globale Variable, Volatile"
Verstehe ich das richtig das ich um auf die Variable "xstepin" 
ausserhalb des Interrupts zuzugreifen die Interrupts deaktivieren muss?
Mfg und Danke ;)

von Karl H. (kbuchegg)


Lesenswert?

@M. G.

Hab ich was an den AUgen, oder hast du in deinem main() tatsächlich 
keine while-Hauptschleife.

PS: Deine { } Klammersetzung ist das unübersichtlichste, was ich in den 
letzten 10 Jahren gesehen habe. Damit würde ich auch Unmengen von 
logischen Fehlern machen.

von Karl H. (kbuchegg)


Lesenswert?

Der Code würde von einer Restrukturierung und Aufteilung in einzelne 
Funktionen nur profitieren. So wie er jetzt ist, ist er einfach nur 
eines: eine lange Wurscht, bei der man nicht sieht, wie die Dinge 
zusammengehören bzw. voneinander abhängen.

von Karl H. (kbuchegg)


Lesenswert?

Wo sind deine Behandlungsfunktionen für den INT1 und INT2?

Man gibt keine Interrupts frei, für die man keinen Handler hat!
Tut man es trotzdem und tritt ein derartiger Interrupt auf, dann löst 
das einen Prozessorreset aus.

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:

 Verstehe ich das richtig das ich um auf die Variable "xstepin"
> ausserhalb des Interrupts zuzugreifen die Interrupts deaktivieren muss?

Du solltest dich lieber fragen, warum diese Variable ein int (also 16 
Bit) sein muss. Machst du sie als uint8_t dann hast du das Problem des 
atomaren Zugriffs erst gar nicht.

von Karl H. (kbuchegg)


Lesenswert?

Paul schrieb:
> Ich hab das selbe Problem.

Wie kannst du dasselbe Problem haben?
Dein Programm sieht doch ganz anders aus!
Du magst vielleicht dieselben Symptome sehen, aber ob dafür dasselbe 
Problem verantwortlich ist, ist eine ganz andere Geschichte.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Angehängte Dateien:

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

von Karl H. (kbuchegg)


Angehängte Dateien:

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.

von M. G. (elch)


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!

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:

> Allerdings liegt an PC0 nie Spannung an. Aber das muss jetzt ja an
> meinem Controller liegen nehme ich an.

Kann ich nicht bestätigen.
An meinem Mega16 läuft die leuchtende LED definitiv durch PC0-PC3 durch. 
Und dreht auch brav um, wenn PD5 auf 1 liegt.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von M. G. (elch)


Lesenswert?

Ok, hab das Problem geloest. Es war tatsaechlich ein Hardwarefehler.
Jetzt klappt es wunderbar :)
Y und Z einzufuegen sollte wohl auch noch klappen ;)
Den code hab ich ja verstanden . Nur ihn selbst zu schreiben ist was 
anderes.
Danke!

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.