Forum: Compiler & IDEs ATTiny25 Problem mit dem Timer


von Patrick (Gast)


Lesenswert?

Hallo,

ich versuche mit folgender Routine einen Impuls zu messen und wieder 
auszugeben

  //Timer0
  TIMSK = (1 << TOIE0 ) | (1 <<OCIE1A );       // enable overflow 
interrupt
    //TCCR0B = ( 1 << CS02 );     //prescale => cpu clock/256 bei 1Mhz = 
256us
  //TCNT0  = 217;         //255 - 217 = 39 x 256us = 9.984ms



  GIMSK = (1 << PCIE);
  PCMSK = (1 << PCINT0);
        sei();                       // enable interrupts


/*********************************************************************** 
***********************/
/*                                   SIGNAL Pin Change Interrupt 
*/
/*********************************************************************** 
***********************/
SIGNAL(SIG_PIN_CHANGE)
{

    if ( PINB & (1<<PINB0) ) {

  TCNT1 = 0; // Timer1 Reset
  TCCR1 = ( 1 << CS10 | 1 << CS12 );  // Timer1 cpu clock/16 MCU start

  }


    if ( !(PINB & (1<<PINB0)) ) {

  Pulsdauer = TCNT1; // Timer1 Wert = Pulsdauer
  TCNT1 = 0; // Timer1 Reset
  OCR1A = Pulsdauer;
  PORTB |= (1<<PB2); //High

  }
}


/*********************************************************************** 
***********************/
/*                                   Timer/Counter1 Compare Match A 
*/
/*********************************************************************** 
***********************/
SIGNAL(SIG_OUTPUT_COMPARE1A)
{

  TCCR1 = 0x00; // Timer1 Stoppen
  PORTB &= ~(1<<PB2);

}

Das Problem ist das mein Timer Wert TCNT1 nicht immer das richtig 
Ergebnis enthält. Um zu sehen ober der Puls richtig erkannt wird haben 
ich einfach mal OCR1A = 100; eingebaut, daran sieht man das der 
Ausgangspuls dann stabil bleibt, d.h irgendwie läuft der Timer1 nicht 
sauber?? was mache ich Falsch?

Gruss Patrick

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich habe da mal deinen Code ergänzt, so wie ich die Frage verstanden 
habe und so weit es für die Simulation im AVR Studio notwendig ist. Mit 
meinem AVR Studio Simulator (4.12 SP2) hatte ich mit Timer1 kein Glück, 
deshalb habe ich alles auf Timer0 umgeschrieben.

Timer0 und Timer1 nimmt sich bei dem Attiny25 nicht viel, denn beide 
sind nur 8-Bit breit. Allerdings kann man bei Timer0 keinen Prescaler 16 
einstellen. Ich habe willkürlich Prescaler 8 genommen. D.h. die maximale 
Dauer der Highphase, die gemessen werden kann, ist jetzt ca. 2ms statt 
vorher 4ms (1 MHz). Wenn man die Anzahl der Timer0 Interrupts zählt, 
könnte man auch längere Pulse verarbeiten.

Mich interessiert, warum du das programmierst, also was du damit machst. 
Darfst du das erzählen?

EDIT: Nur damit es gesagt ist :) Durch die Software-Anweisungen in den 
ISRs wird die Messung natürlich ungenau. Wenn es genauer werden soll, 
sollte man sich die Timestamps bei Pegelwechsel an Pins per Hardware 
geben lassen. Habe ich mal gelesen :)

von Patrick (Gast)


Lesenswert?

Hallo Stefen,

ich hab mir deinen Code mal angeschaut, im Prinzip ist ja nichts neues 
drin, das Problem ist bei mir dass aus irgend einem Grund der Timerwert 
TCNT1 nach dem Erkennen der fallenden Flanke sproadisch zu klein ist. 
Ich hab mal zum Testen folgendes eingefügt:

if ( !(TCNT1 <= 10)) {
    Pulsdauer = TCNT1; // Timer1 Wert = Pulsdauer
    }

mit dieser Zeile geht alles, nur frage ich mich war mir den Wert von 
TCNT1 verhagelt? Im Sim geht übrigens auch alles, aber real gibts die 
sporadischen Probleme. Daran sehe ich auch dass das Erkennen der beiden 
Flanken funktioniert..

Das ganze dient übrigens dazu einen Servoimpuls auszuwerten, ist als 
nicht Geheim ;-)

Gruss Patrick

von Karl H. (kbuchegg)


Lesenswert?

Patrick schrieb:
> Hallo Stefen,
>
> ich hab mir deinen Code mal angeschaut, im Prinzip ist ja nichts neues
> drin, das Problem ist bei mir dass aus irgend einem Grund der Timerwert
> TCNT1 nach dem Erkennen der fallenden Flanke sproadisch zu klein ist.

Timeroverflow in der Zwischenzeit?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@ Patrick

Wie sehen deine Servoimpulse denn aus? Ich habe da keine Vorstellung zu 
der Dauer der HIGH-Phase und der Dauer der LOW-Phase. Die Messung ist ja 
auf ca. 4ms HIGH-Phase (2 ms bei meiner Variante) beschränkt.

Und laut Programm wird ja zeitversetzt gemessen und ausgegeben. Wenn 
während der Ausgabe ein neuer Servoimpuls reinkommt, beeinflusst das 
auch TCNTx. D.h. die LOW-Phase muss länger sein als die HIGH-Phase. Ich 
habe u.a. deshalb beide Teile stärker getrennt als in deinem Quelltext.

Ist das Servosignal ein "sauberes" digitales Signal oder können da 
Prellen und Spikes die Messung stören?

von Patrick (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Timeroverflow in der Zwischenzeit?

eigendlich nicht? nach dem Erkennen der positiven Flanke wird der Timer 
gestartet, dann läuft er maximal 150 Ticks, d.h überlaufen dürfte er 
nicht.

Könnte mein PreScale nicht passen? der Tiny25 läuft mit dem RC Oszilator 
mit 8Mhz, der Standart Teiler ist 8 , dh. meine Basisfrequenz ist 1Mhz.

damit:
TCCR1 = ( 1 << CS10 | 1 << CS12 );  // Timer1 cpu clock/16 MCU start

sollte der Timer1 mit 16us laufen, d.h bei einer Pulslänge von 1ms hätte 
ich 63 Ticks bei 2ms 125Ticks, da kann eigendlich nix überlaufen.

Gruss Patrick

von Patrick (Gast)


Lesenswert?

Stefan B. schrieb:
> Wie sehen deine Servoimpulse denn aus?

im Prinzip immer 20ms lang mit Pulsen der Länge 1-2ms. Zwischendurch 
kommt da nichts.

Gruss Patrick

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.