mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Impulslängenmessung mit AT Mega 8535


Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leutz,

ich möchte eine Pulsweite (konstante Periodendauer) mit dem AT Mega8535
messen. Lt. Beschreibung des 16Bit - Timers gibt es da eine Möglichkeit,
dass der Timer automatisch so lange läuft, wie der Impuls anliegt.
Leider steige ich durch die Doku da nicht ganz durch...

Hat jemand so etwas schon mal programmiert und könnte mir helfen ?


Greetz,
tho

Autor: Tobias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die Timer sind eigentlich dazu da die PWM (Pulsweitenmodulation) zu
erzeugen.  Du kannst allerdings das so lösen, indem du den Pin (wo das
PWM signal anliegt) in einer schleife abfragst, und wenn der Impuls
anliegt, startest du den Timer, sobald impuls aufhört stopst du den
timer. Danach timerinhalt auslesen, einfacher geht es nun wirklich
nicht.

Andere Lösung du benutzt einen einfachen Tiefpass (evtl. aktiven
Tiefpaß mittels OPV zur erzeugung einer gleichspannung aus dem PWM
signal) und benutzt den ADC des Atmega. Anhand der gemessenen
Gleichspannung rechnest du dir dann das Tastverhältniss aus. Da du ja
weisst, dass die Periodenlänge konstant ist, wie du uns mitgeteilt
hast, kannst du dir die Pulsweite ausrechen.

Tast = Umess/Umax
Pulsweite = T_PWMPeriod * Tast

T_PWMPeriod : konstante Periodenlänge des PWM signals
Umess       : am ADC gemessene Spg.
Umax        : Spannung des High- Impulses deines PWM Signals

G. Tobias

Autor: gerd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das scheint mir nun doch arg von hinten durch die Brust ins Auge.
Impulse detektiert man gemeinhin mit dem INT0- oder dem INT1-Eingang,
woraufhin die Interrupt Service Routine den Timer abfragt, den Wert
ablegt, den Timer Null setzt und erneut startet.

Ist aus praktischer Erfahrung eine recht zuverlässige und genaue
Methode, wenn man nicht mit Mikrosekunden geizen muss.

mfg
gerd

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das scheint mir nun doch arg von hinten durch die Brust ins Auge.
> Impulse detektiert man gemeinhin mit dem INT0- oder dem
> INT1-Eingang, woraufhin die Interrupt Service Routine den Timer
> abfragt, den Wert ablegt, den Timer Null setzt und erneut startet.

Das scheint mir nun doch arg von hinten durch die Brust ins Auge. ;-)
Für sowas ist beim 8535 die Input-Capture-Unit des 16bit-Timers da.
Damit geht's dann auch taktzyklengenau.

Autor: gerd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rolf
Ja, das wäre schön. Wenn nur ATMEL vorgesehen hätte, nicht nur entweder
positive oder negative Flanken, aber keinesfalls beide, sowie ein
automatisches Rücksetzen des Timers beim Match mit als Option dazu zu
geben. Dann wäre das eine brauchbare, genaue und fast vollautomatische
Sache.

Wer nur entweder active low oder active high oder sogar abwechselnd
beide messen will (z.B. um ein Pulsweitenverhältnis daraus
auszurechnen), muss sich da in der Interrupt-Service-Routine ganz schön
verrenken. Die Beschreibung der Input-Capture-Unit strotzt nur so von
wenn's und aber's, z.B. wenn man die zu detektierende Flanke
wechselt.

mfg
gerd

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leutz,

eigendlich hatte ich gehofft, man könnte über einen mit dem CLK-Signal
ver-UNDeden Eingang messen ... aber das scheint so nicht zu gehen.
Zumindest nicht so einfach, und ich brauch das ganze auch 2 mal (2 PWMs
zu messen).

Ich schalte den INT jetzt zwischen rising und falling um. Zeitasis ist
der 8Bit Timer / 1024 und Overflow, der 16Bit Timer wird vom Int
gestartet und gestoppt. Die Messergebnisse sind schon ziemlich gut vgl.
mit Scope.

Latürnich möchte ich euch den Code nicht vorenthalten. Da gibtz sicher
noch was zu verbessern. Wer das selber sucht: Hier isses, wer
Verbessungsvorschläge hat, her damit gg


btw:
Debugging mache ich mit dem Scope (Tektronix Digiscope), PORTB = 1 bzw.
0 ist zum Debuggen der Software ;-)


INTERRUPT(SIG_INTERRUPT0)
{


  if(xrising)    //Timer starten
  {
    //PORTB=1;


    bit_on(TCCR1B, CS10);    // clk/1, Timer start

    bit_on(MCUCR, ISC01);    //Int0 falling edge
    bit_off(MCUCR, ISC00);    //Int0 falling edge

    xrising=0;

  }


  else              //Timer stoppen
  {
    //PORTB=0;
    bit_off(TCCR1B, CS10);    // timer stop
    xhigh = TCNT1/10;

    bit_off(GICR,INT0);      //Int0 inaktiv

    xrising=1;
    xmess=1;
  }
}

INTERRUPT(SIG_OVERFLOW0)
{

  /*
  if(out)              //Rechteck am PORTB erzeugen
    out=0;
  else
    out=1;

  PORTB = out;
  */

  bit_on(MCUCR, ISC01);      //Int0 rising edge
  bit_on(MCUCR, ISC00);


  bit_on(GIFR, INTF0);      //INT0 - Flag löschen
  TCNT1 = 0;            //Zählerstand löschen
  bit_on(GICR,INT0);        //Int0 aktiv
}


int main()
{

  //Timer 16Bit als Zähler interner Impulse
  bit_off(TCCR1A, COM1A0);  //normal port operation, OC1A/B disconnected
  bit_off(TCCR1A, COM1A1);
  bit_off(TCCR1A, COM1B0);
  bit_off(TCCR1A, COM1B1);

  bit_off(TCCR1A, WGM10);    //Timer / Counter Mode normal
  bit_off(TCCR1A, WGM11);
  bit_off(TCCR1B, WGM12);
  bit_off(TCCR1B, WGM13);

  TCNT1 = 0x00;        //Timer-Reg. löschen

  //bit_on(TIMSK, TOIE1);    //Overflow INT enable

  bit_off(TCCR1B, CS10);    // timer stop
  bit_off(TCCR1B, CS11);
  bit_off(TCCR1B, CS12);



   //Timer 8Bit setup
   bit_off(TCCR0, WGM00);    //Waveform Generation mode: Normal (off)
   bit_off(TCCR0, WGM01);

   bit_off(TCCR0, COM00);    //normal Port Operation, OC0 disconnected
   bit_off(TCCR0, COM01);

   bit_on(TCCR0, CS00);    //Int. CLK/1024
   bit_off(TCCR0, CS01);
   bit_on(TCCR0, CS02);

   TCNT0 = 0x00;        //Timer-Reg. löschen

   bit_on(TIMSK, TOIE0);    //Overflow-Int. enable



   //Interrupt 0
  DDRD = 0x00;


  DDRB = 0xff;
  PORTB = 0x00;
...

bit_on(MCUCR, ISC01);      //Int0 rising edge
  bit_on(MCUCR, ISC00);

    bit_off(GICR,INT0);        //Int0 inaktiv

  sei();        //Globale Interrupt enable
...
}

Greetz,
Th. de Buhr

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.