- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 9 von 9

Thema: Problem bei Programmablauf mit Interrupts -> Frequenz mes

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    09.06.2004
    Beiträge
    38

    Problem bei Programmablauf mit Interrupts -> Frequenz mes

    Anzeige

    Powerstation Test
    Hallo!

    Ich habe mittlerweile mein Programm theoretisch soweit, dass es macht
    was es machen soll -> nur wie immer kommt es immer anders als man denkt.

    Die Programmteile einzeln (ADC-Auswertung (Interrupt);
    Frequenzauswertung (Interrupt); Menü, Ausgabe) funktionieren, dies hab
    ich getestet.

    Nur beim Zusammenspiel hapert es, wenn die beiden Interruptroutinen
    gleichzeitig im Programmablauf vorhanden sind.
    Prinzipieller Programmablauf ist folgender:
    (endlosschleife)

    wenn adc mehr als 8 mal ausgewertet wurde -> auswertung
    vornehmen,variable setzen, damit erst wieder Interrupt durchlaufen wird,
    wenn Ausgabe erfolgt ist und "Erlaubnis" für Display geben;

    wenn Frequenzmessung beendet -> auswertung vornehmen,variable setzen,
    damit erst wieder Interrupt durchlaufen wird, wenn Ausgabe erfolgt ist
    und "Erlaubnis" für Display geben;

    wenn Ausgabe erlaubt -> Schreibe werte auf Display, setze
    Interruptvariablen zurück;

    (ende)

    So als kurzer Auszug.(Teil des Quellcodes ist oben angehängt.)

    Mein Poblem ist jetzt, dass bei der Frequenzmessung ca. jedes 3. mal
    extrem falsche werte vorhanden sind -> und ich hab keine Ahnung warum?
    Wäre super wenn sich dasjemand mal ansehen könnte.

    MFG


    P.S. Die Variablen die nicht lokal in der main() deklariert sind, sidn
    alle global deklariert (ja, mit volatile )



    Code:
    ISR(ADC_vect){
    	if (adcbesch == 1){
    		return;
    	}
    	else{
    		adczaehler++;
    		adcspeicher += ADC;
    	}
    }
    //-------------------------------------------------------
    ISR(TIMER1_CAPT_vect)
    {
    	if( UpdateDisplay == 1 ) 	//auf vorherige Messung warten
        return;
    
    	if (x == 0)    // 1.High Flanke
    	{
    		ic_zp_A = ICR1;
    		overflow = 0;
    		x = 1;
    	}
    	else         	// 2.High Flanke
    	{
    		ic_zp_B = ICR1;
            // Messung ist fertig, Display kann neu geschrieben werden
    		UpdateDisplay = 1;
    		x = 0;
      }
    }
    //-------------------------------------------------------
    ISR(TIMER1_OVF_vect)
    {
    	overflow++;
    }
    
    
    int main(void){
    
    verz(20);
    
    
    
    
    //-------------------------------------------------------
    
    float drehzahlwert = 0;						//Speicherwert für Drehzahlwert
    float leistung = 0;
    long adcergebnis = 0;
    
    Start_EEPROMLesen();						//Werte aus EEPROM lesen und in Variablen schreiben
    LCD_Init(0);								//Initialisierung des Displays
    LCD_Clr();									//Display löschen
    verz(4);									//Pause fürs Display
    Init();									//Taster-Initialisierung, ADC-Initialisierung, RS232- Initialisierung
    Zaehler_EEPROM();							//Überprüfen der EEPROM Schreibzugriffe	
    
    
    
    TCCR1B = (1<<ICES1)  | (1<<CS10) ;			// Input Capture Edge, kein PreScale ->Taktfrequenz: 8MHz externer Quarz
    TIMSK = (1<<TICIE1) | (1<<TOIE1);			// Interrupts akivieren, Capture + Overflow
    DDRD = 0x00;
    verz(1);
    sei();
    drehmomentwert = drehmomentberechnung(700);
    while(1)
    {
    	if (adczaehler >= 8){
    		
    		adcbesch = 1;
    		adcergebnis = adcspeicher/adczaehler;
    		drehmomentwert = drehmomentberechnung(adcergebnis);
    		adczaehler = 0;
    		adcspeicher = 0;
    		write = 1;									//Display soll beschrieben werden
    		//UpdateDisplay = 1;
    		
    	}
    		
    	if( UpdateDisplay == 1 )
    		{
    			zw_Erg = ((overflow*65536) + ic_zp_B - ic_zp_A);	// Overflow berücksichtigen
    			Erg = 8000000 / zw_Erg;								//8MHz Quarz
    			drehzahlwert = drehzahlberechnung(Erg);
    			write = 1;								//Display soll bechrieben werden
    			
    			
    		}
    
    		
    		
    	if ( write == 1){					//Ausgabe der Werte, je nachdem ob write gesetzt oder nicht
    			
    			if ( ausgabemodus == 1){		//Ausgabe der Werte über LCD + RS232
    				leistung = leistungsberechnung(drehmomentwert,drehzahlwert);
    				Ausgabe_LCD();
    			}
    			else if (ausgabemodus == 2){	//Ausgabe der Werte nur über RS232 -> schnell !!Achtung!! Keine Leistungsberechnung/ausgabe
    				if (lcdbeschr == 0){
    					LCD_Clr();
    					verz(3);
    					LCD_WritePosString(0, 0,"RS232-Modus aktiv", 1);
    					LCD_WritePosString(1, 0,"Displayausgabe", 1);
    					LCD_WritePosString(2, 0,"ausgeschaltet", 1);
    					lcdbeschr = 1;
    				}
    				else if (lcdbeschr == 1){
    					Ausgabe_RS232();
    				}
    			}
    		write = 0;
    		adcbesch = 0;
    		UpdateDisplay = 0;
    	}
    	
    
    
    	if (PIND &(1 << MENUETASTE)){		//Bedingung für Menüaufruf -> Messung wird gestoppt!!
    		cli();
    		verz(8);
    		men();
    		sei();
    	}
    	
    	if (PIND &(1 << UEBERSICHTTASTE)){	//Bedingung für Aufruf der Übersicht -> Messung wird gestoppt!!
    		cli();
    		verz(8);
    		uebersicht();
    		sei();
    	}
    	
    }
    	
    return 0;
    
    }

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    09.06.2004
    Beiträge
    38
    niemand eine Idee?

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Es genügt nicht, die Variablen volatile zu machen. Die Zugriffe müssen atomar sein.
    Disclaimer: none. Sue me.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    09.06.2004
    Beiträge
    38
    -> atomar = ?

    das seltsame ist, dass die Auswertung des ADC und die Auswertung der Frequenz mittles ICP/Timer in jeweils separaten Programmen wunderbar funktioniert... - das ist das was mich stutzig macht.

    MFG

  5. #5
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Hallo Jericho_one!

    In multitasking Programms kann ich Dir aus eigener Erfahrung empfehlen keine Interrupts zu benutzen, sondern alle Unterprogramme in einer endlosen Schleife nacheinander aufzurufen. Sehr hilfreich sind selbst definierte Flags die nur nötige Tasks starten. Z.b. wenn Frequenz schon gemessen ist, startet Displayausgabe u.s.w.

    MfG

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    09.06.2004
    Beiträge
    38
    Hi!

    Genau so habe ich es gemacht -> Also wenn z.B. Frequenzmessung zu Ende, also ein neuer Messwert da ist, dann darf erst wieder eine Ausgabe erfolgen.

    Das andere Problem ist, dass ich ohne Interrupts wohl nicht auskomme, da ich einen Timer im Hintergrund laufen lassen muss.

    Aber ich werds jetzt noch mal ein wenig umstellen - mal sehn ob was verbünftiges rauskommt.

    Danke schon mal!

  7. #7
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    In dem Fall müsste man alle Unterprogramme, die der Timer aufruft duplizieren, damit er nichts in den von ihm unterbrochenen ändert.

    MfG

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    09.06.2004
    Beiträge
    38
    Hi!

    Also ich habs jetzt so gemacht dass nur noch die Frequenzmessung mit Interrupts läuft - der Rest durch Polling - und es scheint zu laufen.

    Danke für den Tip!

    MFG

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Zu "atomar" folgst du den Links in
    https://www.roboternetz.de/wissen/in...Programmierung

    Ich hab momentan keine Zeit, den Artikel auszutexten. Aber der Punkt "atomar" ist ein Fehler, den ich im Forum oft sehe und die Stellen, die das Thema im Wiki behandeln sind zugegebenermassen schwer zu finden...

    Bist du sicher, daß deine IRTs (Interrupt respond times) nicht zu lange werden? Du musst ja sicherstellen, daß nicht 2 InCapt geschehen und der vorheriger Wert überschrieben wird, bevor du ihn abholen konntest.

    Was geschieht, wenn der OVF in der CAPT getriggert wird?
    Was geschieht, wenn Overflow und InCapt zeitnah auftreten?
    Wodurch ist die maximale IRT in deiner Applikation gegeben, und wie hannst du diese minimieren?
    Disclaimer: none. Sue me.

Berechtigungen

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

Solar Speicher und Akkus Tests