Forum: Mikrocontroller und Digitale Elektronik Input Capture Atmega16


von Micha S. (e-tec)


Lesenswert?

Hallo zusammen,

nach langer Zeit mal wieder melde ich mich zurück :)

Ich habe ein kleines Problem mit dem Input Capture.
Irgendwie will er nicht so richtig funktionieren... Ich versuche eine 
komplette PWM zu messen, die erste steigende Flanke, dann schalte ich 
den Input um, warte auf die fallende Flanke und zum Schluß warte ich auf 
die nächste steigende Flanke...
Variablen sind natürlich als volatile definiert... t1_counter8 ist der 
Überlauf Zähler vom 16Bit Timer... wenn ich was vergessen habe einfach 
fragen :)

Hier mal der Code für den Input Capture:
1
// Timer/Counter1 Capture Event (IPC)
2
ISR(TIMER1_CAPT_vect)
3
{  //===========================
4
   //capture first positive edge
5
   if( (!bit_is_set(IPC_ISR_flag, timer1_capt_1st_edge))
6
    && (!bit_is_set(IPC_ISR_flag, ipc_messure_complete)) )
7
   {
8
      IRQ_disable();            // Interrupts deaktivieren
9
      first_pos_edge  = ICR1;   // 16Bit Register auslesen
10
      IRQ_enable();             // Interrupts aktivieren
11
12
      t1_counter8     = 0;
13
14
      clrbit(TCCR1B, ICES1);    // Auf negative Flanke umschalten
15
      setbit(IPC_ISR_flag, timer1_capt_1st_edge);
16
17
      togbit(PORTC, PIN0);
18
   }
19
   //=====================
20
   // capture falling edge
21
   else
22
   if( ( bit_is_set(IPC_ISR_flag, timer1_capt_1st_edge))
23
    && (!bit_is_set(IPC_ISR_flag, ipc_messure_complete)) )
24
   {
25
      IRQ_disable();            // Interrupts deaktivieren
26
      first_neg_edge  = ICR1;   // 16Bit Register auslesen
27
      IRQ_enable();             // Interrupts aktivieren
28
29
      first_neg_t1cnt = t1_counter8;
30
      setbit(TCCR1B, ICES1);   // Wieder auf positive Flanke umschalten
31
32
      clrbit(IPC_ISR_flag, timer1_capt_1st_edge);
33
      setbit(IPC_ISR_flag, ipc_messure_complete);
34
   }
35
   //===========================
36
   // capture second rising edge
37
   else
38
   if( (!bit_is_set(IPC_ISR_flag, timer1_capt_1st_edge))
39
    && ( bit_is_set(IPC_ISR_flag, ipc_messure_complete)) )
40
   {
41
      IRQ_disable();            // Interrupts deaktivieren
42
      second_pos_edge = ICR1;   // 16Bit Register auslesen
43
       IRQ_enable();             // Interrupts aktivieren
44
45
      second_pos_t1cnt=t1_counter8;
46
47
    // Berechnungen
48
      period_time     = (t1_counter8 * 65535);
49
      period_time    += ((second_pos_t1cnt * 65535) + second_pos_edge);
50
      period_time    -= first_pos_edge;
51
      tastverhaeltnis = (ui32)((ui64)(100 * first_neg_edge + first_neg_t1cnt * 65535) / period_time);
52
      clrbit(IPC_ISR_flag, ipc_messure_complete);
53
   }
54
}

von Karl H. (kbuchegg)


Lesenswert?

Kommt der µC überhaupt in die ISR?

Die Berechnung hat da drinn auch nichts verloren!
Lass dir halt mal die Einzelwerte ausgeben. Dich interessieren die 
Timerticks, die du für die High-Phase gemessen hast und die Timer Ticks, 
die du für die Low Phase gemessen hast. Dann sieht man auch schon mal, 
ob man sich bei den Flags vertan hat, und die Werte dauernd die Plätze 
wechseln. Wenn man ganz hinten in einer Berechnung Blödsinn rauskriegt, 
dann schaut man sich halt mal die Eingangswerte in diese Berechnung an. 
Denn wenn die schon falsch sind, dann ist klar, dass hinten nichts 
richtiges rauskommen kann. Diese Binsenweisheit scheint aber zu einfach 
zu sein, interessanterweise muss man das den Leuten immer wieder 
beibringen.

Du solltest auch bedenken, dass dir die Umschaltung der Flankenrichtung 
einen Interrupt bescheren kann. Wenn man sich die gemessenen Timerticks 
ansehen würde, könnte man das in den Zahlenwerten sehen, wenn die 
Differenzen lächerlich unrealistisch gering sind.

In einer ISR sind die Interrupts sowieso ausgeschaltet. Du brauchst da 
nichs aktivieren oder deaktivieren. Ganz im Gegenteil: in einer iSR die 
Interrupts wieder zu aktivieren, kann gefährlich sein.

Stell den ganzen Timer auch so, dass du Overflows im Zählbereich erst 
mal ignorieren kannst. Eine PWM ändert sich ja normalerweise nicht in 
der Frequenz. d.h. das kann man so einstellen, dass ein kompletter PWM 
Zyklus nicht länger als 65535 Timertakte dauert. Dann bist du das 
Problem der fast (aber doch nicht) gleichzeitigen Capture und Overflow 
Interrupts fürs erst mal los (was nicht heisst, dass man sich nicht 
später doch noch drum kümmert).

Alles in allem wieder mal Kardinalfehler Nummero Uno: zuviel auf einmal 
geschrieben ohne zwischendurch zu testen. Nichts geht und in dem ganzen 
Wust weiss man nicht wo man mit der Fehlersuche anfangen soll. Alles was 
man weiss ist, dass ganz hinten am Ende einer längeren Kette von 
Ereignissen nicht das richtige rauskommt - Hilfe!
1
volatile Variable 'Begin'    // Timerstand bei der ersten steigenden Flanke
2
volatile Variable 'EndPuls'  // Timerstand am Ende des Highpulses
3
volatile Variable 'Ende'     // Timerstand nach der Low-Phase (beendet durch steigende Flanke)
4
volatile Variable 'Wertetriplett ist komplett'
5
6
ISR( ... )
7
{
8
  if( steigende Flanke ) {
9
    if( ersteFlanke ) {
10
      if( Wertetriplet nicht komplett ) {   // Sicherung, dass die main mit
11
                                             // der Auswertung hinterher gekommen ist
12
        Wert für Begin merken
13
        umschalten auf fallend
14
        merken, dass erste Flanke durch
15
      }
16
    }
17
    else {
18
      Wert für komplett Ende merken
19
      nächste steigende Flanke ist wieder erste Flanke
20
      signalisieren, dass das Wertetriplet komplett ist
21
    }
22
  }
23
24
  else {   // muss eine fallende Flanke gewesen sein
25
    (sicherheitshalber könnte man überprüfen, dass die erste Flanke
26
     bereits gekommen sein muss. Denn 1 fallende Flanke muss ja
27
     ausgelassen werden)
28
    Wert für EndPuls merken
29
    umschalten auf steigend
30
  }
31
}
32
33
main
34
{
35
  ....
36
37
  while( 1 ) {
38
39
    if( Wertetriplet komplett ) {
40
      ausgeben ( Begin )
41
      ausgeben ( EndPuls )
42
      ausgeben ( Ende )
43
44
      Wertetriplet = nicht komplett
45
    }
46
  }
47
}

dann sieht man sich mal die gemessenen Timerwerte an.

Beachte auch, dass man sich die ganze Sache mit der ersten steigenden 
Flanke auch sparen könnte. Denn die steigende Flanke, die die Low-Phase 
beendet, ist ja auch gleichzeitig die steigende Flanke, die den nächsten 
Puls beginnt.

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.