Hallo Leute,
mein Problem betrifft die Timer Interrupt Funktion meines
ArduinoMega2560 (ATmega2560).
Mein Schrittmotorprogramm berechnet die entsprechende Schrittweite vor
jedem Schritt neu. Bei einem Schritt erfolgt das Ausgabesignal dann
durch einen kurzen Puls (~20us). Anschließend wird überprüft wieviele
Mikrosekunden vergangen sind ,sodass der nächste Schritt ausgeführt
wird.
Ich möchte aber nun ein Rechtecksignal für den Schrittmotortreiber
erzeugen, das genau die Hälfte des Schrittes ein und die andere
ausgeschalten ist. Durchführen wollte ich es, in dem ich bei Beginn des
Schrittes die aktuelle Systemzeit des Mikrocontrollers einlese und die
Hälfte der Schrittdauer dazu addiere. Anschließend läuft ein
Timerinterrupt (alle 20us) und vergleicht die aktuelle Systemzeit mit
der "Halbzeit" und schaltet nach der "Halbzeit" das Signal aus, sodass
ein 50/50 Rechtecksignal entsteht.
Leider funktioniert das bis jetzt überhaupt nicht so, wie ich es mir
gedacht habe. In einem kleinen Programm habe ich einmal versucht meinen
Fehler zu finden. Da ich mit keiner delay Funktion (bei
Interruptverwendung) eine Frequenz für die SChrittweite vorgeben kann
mache ich es im Beispiel durch eine Vielzahl an Rechnungen. Der Code
generiert ein Rechtecksignal mit 0,5Hz. Das funktioniert aber nur wenn
ich eine Funktion wie delayMicroseconds(1) in der Whileschleife
mitaufrufe.
Sieht hier jemand den Fehler, wieso die delayFunktion unbedingt in die
While-Schleife gehört? Mache ich einen Grundsätzlichen Fehler bei der
Verwendung des Interrupts?
1 | unsigned long zeit=0;
|
2 | float rechenwert;
|
3 | unsigned long messzeit=0;
|
4 | unsigned long endzeit=0;
|
5 |
|
6 | void setup()
|
7 | {
|
8 | Serial.begin(9600); // open the serial port at 9600 bps:
|
9 | pinMode(3, OUTPUT);
|
10 | digitalWrite(3, LOW);
|
11 | pinMode(2, OUTPUT);
|
12 | digitalWrite(2, LOW);
|
13 | }
|
14 |
|
15 |
|
16 | void loop()
|
17 | {
|
18 | Inter1();
|
19 | while(zeit==0)
|
20 | {
|
21 |
|
22 | endzeit=3000000; ////neuer Wert mit einer Sekunde Wartezeit
|
23 |
|
24 | delayMicroseconds(1);
|
25 |
|
26 | for(long i=0;i<1223258;i++)
|
27 | {
|
28 | rechenwert=sqrt(987651);
|
29 | }
|
30 |
|
31 | endzeit=0; /////neuer Wert mit einer Sekunde Wartezeit
|
32 | for(long i=0;i<1223258;i++)
|
33 | {
|
34 | rechenwert=sqrt(987651);
|
35 | }
|
36 |
|
37 | //endzeit=micros()+halbeschrittweite;
|
38 |
|
39 | }
|
40 | }
|
41 |
|
42 |
|
43 |
|
44 | void Inter1() //Interrupt Funktion Einschalten
|
45 | {
|
46 |
|
47 | // initialize timer1
|
48 | noInterrupts(); // disable all interrupts
|
49 | TCCR4A = 0;
|
50 | TCCR4B = 0;
|
51 | TCNT4 = 0;
|
52 |
|
53 | OCR4A = 1600; // compare match register 16MHz/256/2Hz 160
|
54 | TCCR4B |= (1 << WGM42); // CTC mode
|
55 | TCCR4B |= (0<<CS42)|(1<<CS41)|(0<<CS40); // 256 prescaler 8
|
56 | TIMSK4 |= (1 << OCIE4A); // enable timer compare interrupt -----> 10 us
|
57 | interrupts(); // enable all interrupts
|
58 |
|
59 | }
|
60 |
|
61 |
|
62 | void noInter1() //Interrupt Funktion Ausschalten
|
63 | {
|
64 | TCCR4B |= (0<<CS42)|(0<<CS41)|(0<<CS40); // 256 prescaler
|
65 | }
|
66 |
|
67 |
|
68 | ISR(TIMER4_COMPA_vect) // timer compare interrupt service routine
|
69 | {
|
70 | // if (micros()<endzeit)
|
71 | if (2000000<endzeit)
|
72 | {
|
73 | digitalWrite(3, HIGH);
|
74 | }
|
75 | else
|
76 | {
|
77 | digitalWrite(3, LOW);
|
78 | }
|
79 |
|
80 | }
|