-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Pulsweite messen

  1. #1
    Erfahrener Benutzer Begeisterter Techniker Avatar von Chypsylon
    Registriert seit
    02.02.2011
    Ort
    Graz/Österreich
    Beiträge
    256

    Frage Pulsweite messen

    Anzeige

    Hallo

    Ich möchte gerne die Länge der rot markierten Stellen (also der low-pegel) von folgendem Signal messen:

    Ich habe das ganze auf einem atmega128@16mhz mit der input capture funktion probiert doch irgendwie funktioniert es nicht so recht. So wie der code jetzt ist funktioniert nicht einmal die displayausgabe im while-loop. Habt ihr einen Tipp was ich anders machen sollte und/oder wo der/die Fehler sind?

    Das ist das erste Mal das ich timer/interrupts benutze also seid bitte gnädig mit mir falls ich einen echt dummen anfängerfehler gemacht habe

    Schon im Vorraus danke für eure Hilfe!

    Code:
     
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include "lib.h"
     
    uint16_t duration_low=0;
    ISR(TIMER3_CAPT_vect)
    {
      //was rising edge
      if((TCCR3B & (1<<ICES3))==0) duration_low=ICR3;
      //switch edge detection mode
      TCCR3B ^=(1<<ICES3); 
      //deactivate interrupts
      cli();
      //set timer to 0
      TCNT3=0;
      //activate Interrupts
      sei();
    }
     
     
    int main(void)
    {
      char Zahl[4];
     
      // Initialization  
      INIT();
     
      //set ICP3/PE7 as input
      DDRE &= ~(1<<PE7);
     
      //deactivate pwm output
      TCCR3A = 0; 
      //Enable Input Capture Interrupt + Overflow Interrupt
      ETIMSK = (1<<TICIE3)|(1<<TOIE3); 
      //Set Prescaler to cpu clock + Edge detection to falling edge + Input capture noise canceler
      TCCR3B |=(0<<CS32)|(0<<CS31)|(1<<CS30)|(0<<ICES3)|(1<<ICNC3);  
      // Clear Input Capture Flag + clear pending interrupts
      ETIFR = (1<<ICF3)|(1<<TOV3);
      //activate global interrupts
      sei();
     
     
      while(1)
      {
     
     //Displayausgabe
     sprintf(Zahl,"%3d",duration_low);
     for (uint8_t i=0; i<=10; i++) LINE_2[i]=Zahl[i];
     SHOW_LINES();
      }
     
      return 0;
    }
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken signal.PNG  
    Geändert von Chypsylon (04.04.2011 um 18:31 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    26
    Beiträge
    1.192
    Hallo,
    ich würde das einfacher lösen. Ohne Interrupts und Timer/Counter.
    Vom Prinzip:
    Code:
    void messung()
    {
     while(PIN_AUF_HIGH)
     {
      //do nothing
     }
     unsigned int counter=0;
     while(PIN_AUF_LOW)
     {
      counter++;
      warte_wenige_mikrosekunden();
     }
     return counter;
    }
    Da müsste man halt noch einen Sicherheitszähler o.ä. rein machen, damit das Programm bei zeitlich konstantem High oder Low-Pegel das Programm nicht hängen bleibt!

    Grüße, Bernhard

    PS: Die Zeiten kommen mir bekannt vor Robocupjunior neuer Ball (RCJ-05) - Auswertung mit einem TSOP?

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Für eine genaue Messung der Zeiten sollte man den Timer durch laufen lassen, und die Differenzen zwischen den Zeiten für die fallende und steigende Flanke bilden.

    Das CLI und SEI in der ISR ist überflüssig, bzw, sogar fehlerträchtig. Das Interrupt-Bit ist in der ISR ohnehin schon gelöscht - CLI macht also nicht. Und am Ende wird das Bit wieder gesetzt - das SEI ist überflüssig und in aller Regel eher schädlich.

  4. #4
    Erfahrener Benutzer Begeisterter Techniker Avatar von Chypsylon
    Registriert seit
    02.02.2011
    Ort
    Graz/Österreich
    Beiträge
    256
    @BMS: Sowas habe ich mir auch schon überlegt aber dabei wird das Programm ziemlich verlangsamt da er in der zähler-whileschleife "hängen bleibt". Außerdem sind einige delays von ein paar ms im Hauptloop eingebaut (z.b. displayausgabe, Tasterentprellung usw..)
    [OT]
    Zitat Zitat von BMS Beitrag anzeigen
    PS: Die Zeiten kommen mir bekannt vor Robocupjunior neuer Ball (RCJ-05) - Auswertung mit einem TSOP?
    Exakt Bist du eigentlich noch dabei? [/OT]

    Zitat Zitat von Besserwessi Beitrag anzeigen
    Für eine genaue Messung der Zeiten sollte man den Timer durch laufen lassen, und die Differenzen zwischen den Zeiten für die fallende und steigende Flanke bilden.
    Aber was ist wenn der Timer während der Messung überlauft und wieder bei 0 beginnt? Dann habe ich ja ein falsches negatives Ergebnis?
    EDIT: Bin selber draufgekommen - if(erste_messung>zweite messung) zeit= 65536-erste_messung + zweite_messung;

    Werde ich dann mal probieren...

    Zitat Zitat von Besserwessi Beitrag anzeigen
    Das CLI und SEI in der ISR ist überflüssig, bzw., sogar fehlerträchtig. Das Interrupt-Bit ist in der ISR ohnehin schon gelöscht - CLI macht also nicht. Und am Ende wird das Bit wieder gesetzt - das SEI ist überflüssig und in aller Regel eher schädlich.
    Danke für den Hinweis, ich habe irgendwo gelesen das vor Zugriff auf dieses Register alle Interrupts deaktiviert sein sollen - hab wohl im "Eifer des Gefechts" vergessen das diese in der ISR sowieso in die "Warteschlange" gereiht werden
    Geändert von Chypsylon (04.04.2011 um 21:12 Uhr)

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Aber was ist wenn der Timer während der Messung überlauft und wieder bei 0 beginnt? Dann habe ich ja ein falsches negatives Ergebnis?
    Du nimmst die passenden Datentypen (uint16_t) und schon regelt sich das von alleine.

    EDIT: Bin selber draufgekommen - if(erste_messung>zweite messung) zeit= 65536-erste_messung + zweite_messung;
    Einfaches Abziehen reicht, wenn erste_messung und zweite_messung uint16_t sind.
    MfG
    Stefan

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Ich würde es schon mit dem Input Capture Interrupt machen, weil das praktisch im Hintergrund läuft.

    Der Trick dabei ist, das Sensing, also ob der Interrupt auf steigende oder fallende Flanke reagiert in der Interruptroutine umgeschaltet wird.

    Das Sensing wird also zunächst auf fallende Flanke eingestellt.
    Tritt dieser Interrupt dann auf wird das Input Capture Register ausgelesen und in einer Variable zwischengespeichert.
    Zusätzlich wird das Interrupt Sensing auf steigende Flanke umgestellt.

    Wird nun irgendwann durch die steigende Flanke der ICP Interrupt ausgelöst, wird das Input Capture Register ausgelesen und der vorher abgespeicherte Wert abgezogen.
    Der Unterschied ist das Mass für die gemessene Pausenlänge, also Dein gewünschtes Ergebnis.
    Sogleich wird das Interrupt Sensing wieder auf fallende Flanke für die nächste Messung eingestellt.

    Ob es dabei zu Überläufen bzw. Fehlberechnungen bei der Subtraktion, kommt wird vom Compiler abhängig sein.
    Üblicherweise kommt es bei der reinen Subtraktion von 2 16Bit Unsigned Int Variablen zu keinen Rechenfehlern.
    Ich nehm da immer gerne einen 8MHz Quarz und einen Vorteiler von 8, weil dann das errechnete Ergebnis direkt in µs rauskommt.
    Die maximal mögliche Messlänge ist dabei 65535µs. Sonst ist ja der Timer ( 16Bit ) bereits einmal komplett durchgelaufen.

    Günstig ist es auch, wenn in der Interruptroutine ein Flag ( Bit Variable ) nach einer neuen Berechnung gesetzt wird, damit das Hauptprogramm weiß, das es wieder was zu tun hat.
    Wenn das Hauptprogramm den gemessenen Wert verarbeitet hat, wird dieses Flag einfach wieder gelöscht.

  7. #7
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Ob es dabei zu Überläufen bzw. Fehlberechnungen bei der Subtraktion, kommt wird vom Compiler abhängig sein.
    Nein, es sei denn der Compiler ist fehlerhaft. Über-/Unterläufe bei Unsigned-Integer-Arithmetik sind im C Standard eindeutig definiert.
    MfG
    Stefan

  8. #8
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    26
    Beiträge
    1.192
    [OT]PS: Die Zeiten kommen mir bekannt vor Robocupjunior neuer Ball (RCJ-05) - Auswertung mit einem TSOP?
    Exakt Bist du eigentlich noch dabei? [/OT]
    Bin nicht mehr dabei, studiere jetzt Elektrotechnik, 2.Semester

    Wie viele TSOP wertest du denn aus? Weil es gibt nur relativ wenige Pins, an denen du mit Input Capture arbeiten kannst.

    Grüße, Bernhard

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Wie viele TSOP wertest du denn aus? Weil es gibt nur relativ wenige Pins, an denen du mit Input Capture arbeiten kannst.
    Man kann auch noch die Interrupt Quellen INTx verwenden, da sich da auch das Sensing einstellen lässt.
    Allerdings produziert man da einen kleinen Fehler, weil man dabei ja nur das TCNT Register auslesen kann, das ja immer weiter hochzählt.

  10. #10
    Erfahrener Benutzer Begeisterter Techniker Avatar von Chypsylon
    Registriert seit
    02.02.2011
    Ort
    Graz/Österreich
    Beiträge
    256
    Danke für die Tipps ich werde sie wenn ich wieder mal zeit habe umsetzen und mich bei event. Problemen wieder an euch wenden

    Zitat Zitat von sternst Beitrag anzeigen
    Nein, es sei denn der Compiler ist fehlerhaft. Über-/Unterläufe bei Unsigned-Integer-Arithmetik sind im C Standard eindeutig definiert.
    Zumindest in dieser Hinsicht funktioniert avr-gcc einwandfrei

    Zitat Zitat von BMS Beitrag anzeigen
    Bin nicht mehr dabei, studiere jetzt Elektrotechnik, 2.Semester

    Wie viele TSOP wertest du denn aus? Weil es gibt nur relativ wenige Pins, an denen du mit Input Capture arbeiten kannst.

    Grüße, Bernhard
    Eigentlich habe ich vorgehabt 16 Sensoren auszuwerten, pro 16bit timer gibt es nur einen icp-pin was aber kein weiteres problem sein sollte wenn ich die Sensoren mit einem 5041 (oder ähnlichem) abwechselnd auf den icp-pin durchschalte

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. 24V mit AVR ADC messen
    Von dwod im Forum AVR Hardwarethemen
    Antworten: 3
    Letzter Beitrag: 01.09.2006, 14:03
  2. Servo MinMax Pulsweite ermitteln
    Von plusminus im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 26.07.2006, 17:08
  3. Problem mit Pulsweite messen ( DCF-77 Signal )
    Von ASIC im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 18.02.2006, 21:59
  4. Pulsweite
    Von bertl100 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 06.06.2005, 12:56
  5. Pulsweite messen mit Mega 128
    Von bertl100 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 08.04.2005, 07:08

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •