- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 2 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 11 bis 20 von 32

Thema: Unerklärliche Programmfehler

  1. #11
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    21.05.2008
    Ort
    Oststeinbek
    Alter
    34
    Beiträge
    607
    Anzeige

    LiFePo4 Akku selber bauen - Video
    der "Data: 1366 bytes (66.7% Full) " bereich wird vom flash gleich zu beginn des Programms in der RAM geladen (soweit ich weiß).
    Wenn der Stack nun zu groß wird (was leicht vorkommen kann, vor allem bei verschachtelten Funktionen) dann kann es leicht sein, dass der Daten-Teil und der Stack sich treffen, und dann werden die Rücksprungadressen der Funktionen möglicherweise mit Daten überschrieben, und dann kommt der Controller in Teufels Küche.

    Versuch einen pin-kompatiblem Controller mit mehr Ram zu verwenden (z.B. ATmega64 oder 644) und du solltest keine Probleme mehr damit haben.

    Gruß, Yaro

  2. #12
    Das mit dem Stack ist in der Tat eine Möglichkeit. Allerdings sind ja noch ~400 Byte im RAM frei. Gehen wir mal davon aus, das bei jedem Funktionsaufruf alle 32 Register auf den Stack geschaufelt werden (was nicht der Fall sein dürfte, aber egal). Zusätzlich noch durchschnittlich 4 Byte Funkionsparameter. Macht 36 Byte pro Verschachtelungsebene. 400/36 ~ 11. Ob eine Software tatsächlich so oft eine Unterfunktion aufrufen kann, sollte man schon abschätzen können als Programmierer. Für einen Controller wäre das durch einiges.

    Verwendest du malloc oder ähnliches?

    Wenn ich mit solchen Problemen konfrontiert bin, sind sämtliche verwendeten Pointer das erste was ich prüfe. Dabei gibt es ein paar Möglichkeiten:

    - Array Zugriffe über die Array Grenzen hinaus?
    - Pointer versehentlich zu weit erhöht?
    - Bei String bearbeitenden Funktionen den Buffer evtl. doch nicht ausreichend dimensioniert?

    Auch beliebt: Über/Unterläufe irgendwelcher Variablen, die dann zu den genannten Fehlern führen können.

    Was ich auch schon hatte: Versehentlich einen externen Interrupt aktiviert, obwohl der zugehörige Pin nicht beschalten war. Das ging - zumindest fast immer. So lange bis die Spannung durch irgendwelchen eingefangenen Müll mal wieder einen Interrupt ausgelöst hat und der Controller ins Nirvana gesprungen ist. Da stand ich kurz vor einem Nervenzusammenbruch

  3. #13
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    Ich hab das Program etwas optimiert, braucht jetzt "nur" mehr 1350 Bytes Daten.
    Zusätzlich habe ich mir im laufenden Betrieb den freien Speicher anzeigen lassen, es waren immer mehr als 500 Bytes frei. Ist auch realistisch, da der Großteil schon in den 1350 Bytes enthalten ist, und in den Funktionen je 3-15 Byte dazukommen.

    Die Funktionen sind nicht extrem verschachtelt, ich komme auf 5 Ebenen. Davon einige inline, also 4 Ebenen?
    malloc wird nicht verwendet.

    Array passt, ich verwende ja ein sehr großes für die Navigation und das wurde ausreichend überprüft.

    Buffer für Stringfunktionen werde ich überprüfen.

    Momentan hab ich den Fehler ja nicht, aber ich will das Program noch erweitern, und bisher hatte ich für solche Fehler noch keine nachvollziehbare Ursache gefunden, deshalb danke für alle Ideen die mir in Zukunft weiterhelfen.

    Ich werde auch versuchen ob ich den Fehler von vorgestern mit der Drehzahlregelung reproduzieren kann.

    LG!
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  4. #14
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Hallo,

    ich hatte auch mal so ein Phänomen. Aber mein Programm war komplett in Assembler. Und die Lösung war, dass ich einen PUSH/POP des Statusregisters in einer Interrupt-Routine vergessen habe.

    Viele Grüße
    Andreas

  5. #15
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    So, konnte den Fehler wieder hervorufen:
    Das ist der normale Code der Wartefunktion
    Code:
    void Warten()
    {
    timecount=0;
    
    while (1) { if (timecount>=50) break;}
    }
    und hier ist die Drehzahlüberprüfung eingebaut:
    Code:
    void Warten()
    {
    char x;
    timecount=0;
    x=0;
    
    while (x<2) 
    	{ if (timecount>=25) 
    		{Messercheck();x++;} 
    	
    	}
    }
    (immer alle 0.25s, wie auch sonst im Programm)

    Der Robi führt die ersten 5 Sekunden richtig aus = blinken einer Led nach dem einschalten mit dieser Wartefunktion.
    Danach soll er auf GPS Empfang warten und zeigt dabei GPS Status, Uhrzeit und Datum an, erst wenn ein guter Empfang da ist werden die Motoren gestartet.

    Dabei hängt er sich auf, mal kommt er noch dazu Uhrzeit und Datum anzuzeigen, meistens kommt aber nur die Überschrift "Warten auf GPS" und es wird kein GPS Signal ausgewertet oder angezeigt. Oder die Uhrzeit udn Status ändern sich nicht mehr, daher sicher keine richtige Ausführung des Programmes mehr.

    In dieser Phase wird weder die Wartefunktion noch der Messercheck verwendet, die Wartefunktion wie gesagt nur vorher fürs blinken der LED.

    Messercheck ist als static inline definiert, wird schon oft im Programm verwendet, und ich hab es gerade an noch einer anderen Stelle im Programm eingefügt ohne dass es den normalen Ablauf stört.

    Warum stört es also ausgerechnet hier den kompletten Programmablauf und an anderer Stelle nicht?

    LG!
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  6. #16
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    21.05.2008
    Ort
    Oststeinbek
    Alter
    34
    Beiträge
    607
    1) wo wird timecount erhöht? In einem Interrupt? Poste diesen mal.

    2) Er hängt sich also auf, wenn die Motoren gestartet werden, richtig? versuch mal die motoren von der Versorgungsspannuung wegzunehmen. Es könnte sein, dass sie einen zu hohen Stromstoß verursachen, der den Controller kurzzeitig den Saft wegnimmt.

    3) überprüfe nochmal alle Pointer und Arrays... Ich hatte auch schonmal ähnlich mystische Probleme, die durch einen Array-Überlauf verursacht wurden.

    Gruß, Yaro

  7. #17
    Das riecht alles wahnsinnig nach Zeiger. Du glaubst gar nicht wie oft ich schon festgestellt habe, das meine Programme bisher mehr durch Zufall als durch durchdachten Code funktioniert haben

    Kannst du evtl. doch mal den gesamten Code (als Anhang) posten? Vielleicht fällt jemandem etwas auf. Mit der Zeit wird man ja für seine eigenen Fehler absolut blind. Und ich fürchte nur anhand einiger Codeschnipsel wird den Fehler niemand finden. Der sitzt wo anders.

  8. #18
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    Hier der Code für den Interrupt:
    Code:
    volatile unsigned char timecount;
    
    ISR(TIMER2_COMP_vect)
    {timecount++;}
    
    /*+++++++Timer2++++++++++++++++*/
    	TCCR2 = (1<<WGM21) | (1<<CS20) | (1<<CS21) | (1<<CS22); // CTC Mode, Prescaler 1024
    	TIMSK = (1<<OCIE2); 
    	OCR2=154;
    Er hängt schon lange bevor die Motoren gestartet werden, da er es nicht mal schafft den GPS Empfang abzuwarten, bzw man merkt das er hier hängt da oft nicht mal die Uhrzeit akutalisiert oder gar angezeigt wird (aus Funktion Datum).
    Das "Warte GPS" kommt immer.


    Es ist diese Schleife:
    Code:
    //***********************GPS Kalibrierung ****************************
    void GPS_kalib()
    {
    char x;
    char buffer[10];
    
    
    lcd_clrscr();
    lcd_gotoxy(0,0);lcd_puts_p(PSTR(" Warte GPS"));
    timecount=0;x=0;
    
    
    while (gps<5)	// auf Empfang warten
    	{
    	GPS();
    	rand(); // damit Zufall zufälliger wird, unbestimmt oft aufrufen
    	if (timecount >=25) 
    		{timecount=0;
    		Zeitnehmung();
    		
    		itoa(gps,buffer,10);lcd_gotoxy(11,0);lcd_puts(buffer);	// Anzeige GPS Daten nach Bedarf
    		lcd_gotoxy(13,0);lcd_puts(gpsstatus);
    		itoa(hd,buffer,10);lcd_gotoxy(15,0);lcd_puts(buffer);
    		itoa(satcount,buffer,10);lcd_gotoxy(19,0);lcd_puts(buffer);
    		
    		Datum();
    		
    		}
    	}
    }
    Die restlichen Funktionen dazu:
    Variablen die hier nicht deklariert sind, sind global.

    Code:
    static inline void Zeitnehmung() 
    {
    static char zeit_alt,zaehler;
    short temp;
    char zeit_t;
    
    
    temp=atoi(zeit);
    zeit_t=(char)(temp-(temp/100)*100);// Stunden rauswerfen
    
    
    if ((zeit_t>zeit_alt)) {zaehler++; zeit_alt=zeit_t;} // Änderung bei Minuten erkennen
    if ((zeit_t==0)&&(zeit_alt!=1)) {zaehler++;zaehler++; zeit_alt=1;} 
    													
    if (zaehler>=5) {zaehler=0;arbeitsstunden++;}//zaehler_x++;} 
    
    }
    
    
    /************************* GPS++++++++++++++++++++++++++++++++++++++*/	
    static inline void GPS()
    {
    char x_gps;
    
    x_gps=0;
    		
    	x_gps=USART_Receive(); 
    		if (x_gps=='$')
    		{
      			Getgps(','); 
    		  	if(strcmp(line,"GPGGA")==0) Gps_gga();
    			if(strcmp(line,"GPGLL")==0) Gps_gll();
    			if(strcmp(line,"GPZDA")==0) Gps_zda();
    		}
    	
    }
    
    /***************Position vom GPS***********************/
    static inline unsigned char Getgps(unsigned char end)
    {
    unsigned char c,i;
    char komma, stern;
    
    komma = ',';
    stern = '*';
    
     	line[0]=0; 
     	i=0;
    	c=0;
    
     do
      {
     	  c=USART_Receive(); 
     	  if(c==stern) return 0; 
     	  if(c==komma) return i; 
    	
     	  if(c!=end) //Buchstaben sammeln
     	   {
      	   line[i]=(char)c;
      	   i++;
       	   line[i]=0; //End of String updaten
    	   }
    
      }while(c!=end);
    
     return i;
    
    }
    
    
    void Gps_gga()  //$GPGGA Meldung -----------------------------------------
    {
    char num, hdop;
    char komma;
    short x,y;
    
    
    
    komma = ',';
    x=0;y=0;hdop=9;
    
    	satcount=0; //Anzahl benutzter Satelliten
    	num=0;
    
    
    	// Uhrzeit
     	Getgps('.'); strcpy(zeit,line); zeit[4]=0;// Sekunden raus
    	Getgps(komma); 
     	Getgps('.'); 
    	num=Getgps(komma); 
    	if(num!=0) {line[4]=0;y=atoi(line);} 
     	Getgps(komma);
     	Getgps('.'); 
    	num=Getgps(komma); 
    	if(num!=0) {line[4]=0;x=atoi(line);}
     	Getgps(komma); 
    
    //	//0=kein Empfang, 1=GPS, 2=DGPS
       num=Getgps(komma);
    	//Anzahl benutzter Satelliten
       num=Getgps(komma);
       if(num!=0) { satcount=(unsigned char)atoi(line); }
    
    	
    
     	Getgps('.');
    	hdop=(char)atoi(line);
    	hd= hdop; // für LCD
    	
    	// nur wenn Empfang gut ist die aktuellen Koordinaten verwenden
    	
    	if (satcount>=4)
    
    		{
    		gps=1; // globale Anzeige
    
    		x=(x-8534); 
    		y=(y-3388);
    	
    		x=(x*13);// Auflösung auf 1cm hochrechnen
    		y=(y*19)-250;
    
    
    		
    		if (hdop<=1) gps=5;
    		if (hdop>=4) gps=0;
    
    		if (x<0) x=0;
    		if (x>2300) x=2300;
    		if (y<0) y=0;
    		if (y>4200) y=4200;
    		
    
    		pos_x_gps_akt=x; 
    		pos_y_gps_akt=y;
    		}
    	else gps=0; // zurücksetzen
    }
    
    void Gps_gll()  //$GLL Meldung -----------------------------------------
    {
    char num,komma;
    komma = ',';
    
    Getgps(komma); 
    Getgps(komma); 
    Getgps(komma); 
    Getgps(komma); 
    Getgps(komma); 
    num=Getgps(komma);
    
    if (num!=0)	
    	{strcpy(gpsstatus,line);	
    	
    	}
    
    }
    void Gps_zda()  //$zda Meldung +Wochentagberechnung -----------------------------------------
    {
    char num,komma, tag, monat, jahr;
    short jahrx,xx;
    
    komma = ',';
    tag=0;monat=0;jahr=0;jahrx=0;
    
    Getgps(komma); //zeit
    
    num=Getgps(komma);
       if(num!=0) { tag=(char)atoi(line); }
    num=Getgps(komma);
       if(num!=0) { monat=(char)atoi(line); }
    num=Getgps(komma);
       if(num!=0) { jahrx=(short)atoi(line); jahr=(char)(jahrx-2000);}
    
    
    if (monat<3) {monat=monat+12;jahr--;}
    xx=(tag+((monat+1)*26)/10+jahr+jahr/4-35);// http://de.wikipedia.org/wiki/Zellers_Kongruenz
    num=xx/7;
    wochentag=xx-num*7;
    
    }
    
    void Datum()	//-------------------------------------------------------------------
    {
    char buffer[10];
    short temp;
    
    lcd_gotoxy(0,1);
    switch (wochentag)	// http://de.wikipedia.org/wiki/Zellers_Kongruenz
    	{ 	case 0: lcd_puts_p(PSTR("Samstag"));break;
    		case 1: lcd_puts_p(PSTR("Sonntag"));break;
    		case 2: lcd_puts_p(PSTR("Montag"));break;
    		case 3: lcd_puts_p(PSTR("Dienstag"));break;
    		case 4: lcd_puts_p(PSTR("Mittwoch"));break;
    		case 5: lcd_puts_p(PSTR("Donnerstag "));break;
    		case 6: lcd_puts_p(PSTR("Freitag"));break;
    	}
    
    strcpy(buffer,zeit);
    buffer[2]=0;
    stunden=atoi(buffer);
    temp=atoi(zeit)-stunden*100;
    minuten=(char)temp;
    stunden++;stunden++;// Sommerzeit 
    if (stunden>=24) stunden=stunden-24;
    		
    itoa(stunden,buffer,10);lcd_gotoxy(11,1);lcd_puts(buffer);lcd_gotoxy(13,1);lcd_putc('h');
    itoa(minuten,buffer,10);lcd_gotoxy(14,1);lcd_puts(buffer);
    
    }
    LCD Bibliothek ist von Fleury.

    Ich hatte schon mal so eine ähnliche Situation wo eine If Abfrage alles zum Absturz brachte und das konnte ich umgehen, aber die fehlende Drehzahlregelung in der Wartefunktion ist ein echter Nachteil.

    LG!
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  9. #19
    Ohne vollständigen Code kann man ja nur Raten, aber beim Überfliegen ist mir gleich folgendes aufgefallen:
    Code:
          
    do
      {
          c=USART_Receive();
          if(c==stern) return 0;
          if(c==komma) return i;
       
          if(c!=end) //Buchstaben sammeln
           {
            line[i]=(char)c;
            i++;
             line[i]=0; //End of String updaten
          }
    
      }while(c!=end);
    i wird nicht überwacht. Fehler auf der UART Seite -> Array kann Überlaufen. Sowas kann dir schon passieren wenn der Controller mal zu lange in einem Interrupt braucht und das entscheidente UART Zeichen verpasst wird!

  10. #20
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    Danke! Habs sofort eingebaut.

    LG!
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

Seite 2 von 4 ErsteErste 1234 LetzteLetzte

Berechtigungen

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

Labornetzteil AliExpress