Forum: Mikrocontroller und Digitale Elektronik Das InputCapure Mysterium, mal geht mal nicht?!


von Martin H. (Gast)


Lesenswert?

Hallo zusammen,

Ich habe eine Frage bzgl. des ICP beim Tiny24
Mein Timer läuft mit 1MHz takt und am InputCapturePin ist das signal 
eines RC-Empfängers angeschlossen. (20ms Periodendauer, 1-2ms 
high-pegel, 18-19ms low-pegel)
Nun das will ich in meinen Tiny 24 einlesen. Dazu hab ich den Timer wie 
folgt kunfiguriert:
1
  //  clk/8 (1MHz), Normal-Mode, no PWM
2
  TCCR1A  = (1<<COM1A1) | (1<<COM1B1);
3
  TCCR1B  = (1<<ICNC1) | (1<<ICES1) | (1<<CS11);
4
  TIMSK1  = (1<<ICIE1) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1);
5
6
  TIMSK1  = 0xFF;
7
  sei();
d.h. Noise-Canceler ist Aktiv, und es wird auf die steigende Flanke 
getriggert.
umd damit aber die dauer des High-pegels bestimmen zu können hab ich 
folgende ISR geschrieben
1
ISR ( TIM1_CAPT_vect ) {
2
  static uint16_t pos_edge = 0;
3
  uint16_t time = 0;
4
5
  
6
  if ( TCCR1B  & (1<<ICES1) ) {  // Wenn auf die steigende Flanke getriggert wurde
7
    TCCR1B  &= ~(1<<ICES1);    // Auf fallende Flanke Triggern
8
    pos_edge = ICR1;    // Merken wann die Flanke war
9
    led_an();  // nur zum debuggen
10
  }
11
  else {
12
    TCCR1B  |= (1<<ICES1);    // Wieder auf steigende Flanke Triggern
13
    time = ICR1 - pos_edge;    // +Pulsbreite berechnen
14
    if ( time > 900 && time < 2100 ) {  // Wenn gelesene Pulsbreite akzeptabel in globale Variablen übernehmen
15
      read_pos = time;
16
      sig_good_cnt = 0;
17
    }
18
    led_aus();  // nur zum debuggen
19
  }
20
}

So, ich denke in der Theorie sollte das funktionieren.
Nun stelle ich aber fest, dass das nur dann funktioniert, falls beim 
Programmieren das Empfängersignal anliegt. Sobald ich das Signal aber 
nur kurzzeitig vom AVR trenne oder den Strom von der Schaltung nehme 
triggert der Interrupt offensichtlich nicht mehr.
Interessant war auch, dass ich es geschafft habe den Stecker zu ziehen, 
als die LED gerade an war. Sie blieb dann an bis ich das Signal wieder 
an den AVR anlegt. Dann ging die LED aus und bleib wieder aus.
zusammenfassend, kann man sagen, dass mein Code also nur nach einem 
Reset funktioniert, während dem das Signal anlag, und auch nur solange 
das signal dann da ist, verschwindet es einmal wird es nicht mehr 
erkannt.

Woran könnte das liegen?!

von Oliver (Gast)


Lesenswert?

Da Atme nichts davon im Datenblatt schreibt, daß der ICP nur direkt nach 
einem Reset mit angeschlossenem Fernsteuerempfänger funktioniert, liegt 
es wohl an deiner Schaltung oder deinem Programm.

Also zeig mal her.
Was aber im Datenblatt steht, ist das hier:

>After a change of the edge, the Input Capture Flag (ICF1) must be
>cleared by software (writing a logical one to the I/O bit location).

Das du das nicht machst, erklärt zwar nicht unbedingt den von dir 
beobachteten Effekt, aber machen solltest du das trotzdem.


Martin H. schrieb:
> TIMSK1  = (1<<ICIE1) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1);
> TIMSK1  = 0xFF;

Das ist eher sinnlos.

Was machst du mit den beiden Compare- und dem Overflow-Interrupt? Gibt 
dafür auch ISR's?


Oliver
P.S. Warum brauchts du den noise-canceler?

von Peter D. (peda)


Lesenswert?

Martin H. schrieb:
> TIMSK1  = (1<<ICIE1) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1);

Du gibst 4 Interrupts frei, hast aber nur für einen einen Handler 
aufgesetzt. Das gibt Ärger.


Peter

von Martin H. (Gast)


Angehängte Dateien:

Lesenswert?

Oliver schrieb:
>>After a change of the edge, the Input Capture Flag (ICF1) must be
>>cleared by software (writing a logical one to the I/O bit location).
>
> Das du das nicht machst, erklärt zwar nicht unbedingt den von dir
> beobachteten Effekt, aber machen solltest du das trotzdem.

Hmm, ok, das hab ich nicht gelesen... muss ich wohl einfügen.
Mach ich auch gerade, nur kann ichs nicht testen weil jetzt mein 
Sernderakku leer ist... mist.
Allerdings hat mich das auf die Idee gebracht, welche mein Problem lösen 
könnte. Und war ist mein Netzteil auf 4,38V eingestellt gewesen, und wie 
ich gerade gesehen habe war der Brown-Out auf 4,3 eingestellt. Das 
könnte heißen, mein Empfänger löst beim anstecken den Brown-Out aus, und 
da der ja ne Hysterse hat...

Ja jetzt wird grad ein wenig geladen, dann meld ich mich nochmal.

Danke aber für deinen Hinweis.

Mein Ganzes Projekt häng ich auch mal in Anhang rein, vielleicht 
interessiert es jemanden, oder mir erklärt mal jemand wie man sinnvoll 
nicht allen Code in eine Datei quetscht. Ich hab immer das Gefühl recht 
unübersichtlich zu Programmieren. Naja ich selbst kanns wenigstens noch 
lesen...
Ich stelle euch auch alles zur freien Verfügung, solange ich nicht in 2 
Wochen meine Arbeit bei eBay oder einem Shop entdecke ^^

Danke jedenfalls und ich melde mich

von Martin H. (Gast)


Lesenswert?

PS:
> TIMSK1  = 0xFF;
das sollte TIFR1 = 0xFF; heißen und ist nur ein Angstlöschen der Flags. 
Wenn alles funktioniert wird auch diese Zeile wegoptimiert und dann 
nochmal alles gründlich getestet

von Oliver (Gast)


Lesenswert?

Ich würde in init() und auch sonst immmer erst das DDRx-Register setzen, 
und dann das zugehörige Portregister.

Oliver

von Martin H. (Gast)


Lesenswert?

OK. Also der Brown-Out-Detector war das Problem...
Somit läufts jetz.

Danke euch!

@Oliver: ist doch egal, ob ich erst die Pullups aktiviere und dann den 
Ausgangstreiber oder erst den Pin als Ausgang low und dann auf high.
Für mich kommt das aufs selbe raus!

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.