- Akku Tests und Balkonkraftwerk Speicher         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 25

Thema: Programm zum Frequenzmessen

  1. #11
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Anzeige

    Powerstation Test
    Zum messen eine eternen Zit gibts die ISP Funktion. Wenn man aber den Weg mit dem Zählen wählt, wegen der hohen Frequezn, muß man eine definierte Zeit warten. Das Warten geht z.B. so:
    Den Timer Starten, ggf. mit Startwert. In der ISR zu dem Timer dann ggf. noch einen Zähler runterzählen und dann wenn man 0 erreicht hat den anderen Timer anhalten. Für eine Wirklich extacte Zeit sollte das Hauptprogramm einfach ein den Idel mode gehen per Sleep-befehl.

    Das abfangen einen extra Überlaufs beim anderen Timer ist etwas komplizierter: dazu schaltet man kurz vor dem Enden der Torzeit den Interrupt ab, und ließt dann neben dem Timer noch das Interrupt flag aus. In der kurzen Zeit am Ende sollte höchstens ein Überlauf vorkommen können.

  2. #12
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.236
    Nimm doch für die Taktmessung den Timer 1.
    Mit deiner Konfiguration wird alle 256 Perioden des Signals ein Timer 0 Overflow Interrupt ausgelöst.
    Da der Timer 1 ein 16 Bit Timer ist passiert das dort nur alle 65536 Perioden.

    Ich hab nen anderen C-Compiler als Du, deshalb kann ich deinen Code nicht direkt bearbeiten.

    Ich würd mal so an die Sache rangehen.

    1. Du muss die Controller Taktfrequenz wissen, mit welcher Du arbeiten willst.
    Sagen wir mal 8 MHz.
    Der Timer 0 bekommt dann einen Prescaler von 8.
    Somit wird alle 2048 Takte ein Timer0 Overflow Interrupt ausgelöst.
    In diesem Interrupt wird nun eine 16Bit Int Variable hochgezählt.
    Wenn diese Variable den Wert 3906 hat ( >3906 ) wir der TCNT0 mit 192 vorgeladen. TCNT0=192;
    Weil die eine Sekunde nicht genau in den 2048 Takte passt ist das notwendig = (2048-0,25*204/8
    Die Int Variable wird wieder auf 0 gesetzt.
    Jetzt wird der Zähler TCNT1 und die dazugehörige Overflow Variable ausgelesen. Beide werden nun in Hilfsvariablen abgespeichert.
    Dann wird TCNT1 und die zugehörige Overflow Variable auf 0 gesetzt.
    Code:
    void int tim0overflow(void)
    {
    ui_ov0count++
    if(ui_ov0count>3906)
        {
        ui_counterlow=TCNT0;
        TCNT0=192;
        ui_counterhigh=ui_ov1count;
        ui_ov1count=0;
        ub_newflag=1;
        };
    };
    2. Das Flag teilt der Hauptroutine mit, das neue Messwerte vorliegen und verarbeitet werden müssen.
    Ist das in der Hauptroutine geschehen wird das Flag ub_newflag wieder auf 0 gesetzt.
    Damit wäre dann das Torzeitproblem erschlagen.
    Wie lange das Programm wirklich braucht, teste ich immer mit dem Simulator vom AVRSTUDIO aus.
    Eventuell müssen da Anpassungen gemacht werden, da der Timer ja ach während des Programmablaufes weiter läuft.
    Code:
    void int tim1overflow(void)
    {
    ui_ov1count++
    };
    Die Timer 1 Overflow Routine ist erfreulich kurz - es wird nur die Hilfsvariable hochgezählt.

    Code:
    void main (void)
    {......
    
    while(1)
    {
    if(ub_newflag>0)
    {li_frequenz=(ui_counterhigh*65536)+ui_counterlow;
    /*Es sollte auch li_frequenz=(ui_counterhigh<<16)|ui_couterlow; gehen*/
    displayout(li_frequenz);
    ub_newflag=0;
    }
    }
    }
    Die beiden Hilfsvariablen werden dann in der Hauptroutine weiter verarbeitet in eine Long Int Variable gepackt und ausgegeben.

    Du kannst natürlich auch mit anderen Quarzfrequenzen und Teilerfaktoren für den Timer0 arbeiten. Letztlich soll sich aber möglichst genau 1 Sekunde dabei rauskommen.

  3. #13
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    11.06.2004
    Ort
    Ulm
    Alter
    37
    Beiträge
    248
    Danke mal für die Antworten ich werde das probieren

  4. #14
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    11.06.2004
    Ort
    Ulm
    Alter
    37
    Beiträge
    248
    Ok... ich hatte heute irgendwie schon zu lange Vorlesung oder ich bin einfach zu doof.

    Kann mir jemand den 1. Schritt von wkrug nochmals erklären?

    Ich kann das doch auch auf 10ms verkürzen und wie müsste das dann sein?
    Und nachher einfach die Pulse mal 100 und dann hab ich die Frquenz oder?

  5. #15
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.236
    Ich kann das doch auch auf 10ms verkürzen und wie müsste das dann sein?
    Und nachher einfach die Pulse mal 100 und dann hab ich die Frquenz oder?
    Das geht natürlich auch.
    Allerdings kriegst Du dabei eine maximale Auflösung von 100Hz.
    Du hast nicht gepostet welche Auflösung Du haben willst.
    Ich bin da einfach mal von 1Hz ausgegangen.
    Und das geht mit dieser Methode halt nur mit Torzeiten von 1 Sekunde.

    Ein Kompromiss wäre eine Messdauer von 100ms, das ergäbe dann eine maximale Auflösung von 10Hz.
    Dein Display kannst Du ohnehin nicht viel öfter als 3...4x pro Sekunde refreschen, sonst wirds nervig.

  6. #16
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    11.06.2004
    Ort
    Ulm
    Alter
    37
    Beiträge
    248
    kann mal bitte noch jemand über den Code schaune, es geht nicht

    Code:
    /*-- Hauptprogramm ---------------------------------------------------------------------*/
    int main(void)
    { 
    	char buffer[20] ;
        
    
    	count = 0 ;
    	overflow1 = 0 ; overflow0 = 0 ; // Variable für Overflow  
    
        lcd_init() ;      // LCD aktivieren
    
    	//Timer0 auf Prescaler 8 stellen  --> S.86
        TCCR0 |= (1<<CS01) ; 
    
    	// Overflow Interrupt Enable --> S.87 
    	TIMSK |= (1<<TOIE0) ;
    
    	// Timer1 auf Externen Clock Source T1 mit Rising Edge setzen --> S.115
        TCCR1B |= (1<<CS12) | (1<<CS11) | (1<<CS10) ;
    
        // Overflow Interrupt Enable --> S.117
        TIMSK |= (1<<TOIE1) ;
    
    	sei() ;
    	
    	while(1)
    	{
    	   utoa(overflow1,buffer,10) ;
           set_cursor(0,1) ;
           lcd_string(buffer) ;	
    	   set_cursor(0,2) ; 
    
    	   if(newflag > 0)
    	   {
    	   frequenz=(high*65536)+low;
    	   lcd_data(frequenz) ;
           newflag=0; 
    	   }  
    	}                      
    
    }
    
    /*-- Timer0 Overflow Interrupt ---------------------------------------------------------*/
    SIGNAL (SIG_OVERFLOW0) 
    {
      overflow0 ++ ;
      if(overflow0 > 3906)
        {
    	low = TCNT0 ;
    	TCNT0 = 192 ;
    	high = overflow1 ;
    	overflow1 = 0 ;
    	newflag = 1 ;   
    	}    
    } 
    
    
    /*-- Timer1 Overflow Interrupt ---------------------------------------------------------*/
    SIGNAL (SIG_OVERFLOW1) 
    {
      overflow1 ++ ;
    }

  7. #17
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Einge der variablen müßten noch als volative gekennzeichent werden. Wenigstens overflow0, overflow1, low und high.

    Für die weiteren Messungen ist auch das zurücksetzen der Timer noch nicht ganz in Ordnung. overflow0 und timer 1 müssen auch wieder bei 0 starten. Als ein kleines Detail sollte man auch den Prescaler wieder zurücksetzen. Es kann auch immer noch zu ein paar glitches kommen durch einen eher seltenen Überlauf von timer1 gerade wenn die Messzeit zu ende geht. Wenigstens einen Teil davon könnte man abfangen: Wenn der Timer1 einen kleinen Wert hat und das Overflow Bit von timer1 gesetzt ist, fehlt da wohl noch eine Overflow interrupt.

  8. #18
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    11.06.2004
    Ort
    Ulm
    Alter
    37
    Beiträge
    248
    Die variablen sind alle volative;

    Ich gebs heute auf es läuft nicht....

  9. #19
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.236
    if(overflow0 > 3906)
    {
    low = TCNT0 ;
    TCNT0 = 192 ;
    high = overflow1 ;
    overflow1 = 0 ;
    newflag = 1 ;
    }
    low = TCNT0 ist falsch.
    Da muß low = TCNT1 hin.
    Danach sollte man TCNT1 gleich wieder auf 0 setzen
    TCNT1=0;
    Der "SEI" Befehl soll einen Overflow Interrupt des Zählers vor der Abfrage ermöglichen.
    Mit dem "CLI" Befehl wird diese Möglichkeit wieder verhindert.
    Wenn der Controller die Interrupt Routine verlässt sollte SEI automatisch ausgeführt werden.
    Man könnte auch das Timer 1 Overflow Flag abfragen und entsprechend darauf reagieren.
    Das sind aber erstmal Future Optionen. Erstmal muß das Ding laufen.
    Code:
    if(overflow0 > 3906)
        {
       #asm("sei");
       low = TCNT1 ;
       #asm("cli");
       TCNT0 = 192 ;
       TCNT1=0;
       high = overflow1 ;
       overflow1 = 0 ;
       newflag = 1 ;   
       }
    Hast Du deinen Code schon mal im Simulator vom AVR Studio laufen lassen ? Ist wirklich hilfreich!

  10. #20
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    11.06.2004
    Ort
    Ulm
    Alter
    37
    Beiträge
    248
    Hmm... sehr ich das richtig das soll einmal das zählregister im Low sein (TCNT0) und dann der obere Teil (TCNT1) oder?

    Wenn ja müsste es TCNT1L und TCNT1H sein...

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Berechtigungen

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

12V Akku bauen