PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Unerklärliche Programmfehler



damfino
19.08.2010, 14:53
Ich habe immer wieder mit dem Phänomen zu kämpfen dass bei einer kleinen Änderung in einer Funktion auf einmal das ganze Programm nicht mehr funktioniert. Und das oft obwohl bei normalen Ablauf diese eine Funktion erst spät aufgerufen wird.
Ein Beispiel: in einer Fahrfunktion wollte ich ein Timeout einbauen, dazu habe ich die globale Zeit auf eine Änderung überprüft. Der Robi hat dann nach ca 10s Fahrzeit mit Resets angefangen, irgendwelche anderen Funktionen aufgerufen, und zum Schluss auf gar nichts mehr reagiert. Diese eine Fahrfunktion wird erst nach ca 30 Minuten Fahrzeit aufgerufen, warum kann die also gleich nach dem Einschalten solche Störungen verursachen?
Inzwischen wurde das Timeout anders gelöst, das Programm erheblich erweitert, und funktioniert so immer noch.

Gestern gab es wieder so ein Problem, zur besseren Drehzahlregelung habe ich die schon vorhandene Funktion der Drehzahlüberwachung auch in die vorhande Wartefunktion eingebaut. (Der Robi wartet vor jeder Richtungsänderung 0.5s). Und wieder hat das Programm nicht mehr richtig gearbeitet, es wurde alle paar Sekunden immer wieder von vorne gestartet.

Die Überwachung in der Wartefunktion musste ich rausnehmen, dafür wurde in Drehzahlregelung ein PID Regler eingebaut der auch einiges an Variablen und Speicherplatz benötigt, und es funktioniert perfekt.

Woher kann so ein Verhalten kommen?
Ist der Atmega schon zu Tode geflasht??
Oder macht der Compiler manchmal einfach Mist??

Das Programm ist zu umfangreich um es komplett im Simulator laufen zu lassen (wie GPS, Kompass und Odometrie simulieren?), und wenn ich Teile entferne ist der Simulation nicht mehr vergleichbar und damit sinnlos.

Es geht um einen Atmega32, AVR Studio 4.17, WinAVR-20090313.
Program: 24970 bytes (76.2% Full)
Data: 1366 bytes (66.7% Full)
Build succeeded with 0 Warnings...

Es wäre gut diese Probleme lösen oder erklären zu können, um nicht immer wieder umständliche Lösungen für eigentlich einfache Aufgaben finden zu müssen.

LG!

markusj
19.08.2010, 15:11
Meine Glaskugel ist kaputt (und du hast keinen Code gepostet), daher bleiben nur generische Ansätze: Ist dein RAM vollgelaufen? Wenn der Stack mit den statischen Daten kollidiert, können interessante Dinge geschehen ...

Zur Fehlersuche wirst du wohl oder übel versuchen müssen, so lange Komponenten zu deaktivieren bis du den Fehler eingekreist hast ...

mfG
Markus

damfino
19.08.2010, 15:48
Ein riesen Code wird wenig nutzen da man lange braucht bis man den versteht und dann noch die eine kleine Variable finden muss, die den Ausschlag zwischen funktionierenden Code oder nicht gibt.

Den Fehler habe ich immer gefunden, einmal war es eine neue Variable, einmal eine zusätzliche IF Abfrage, oder letztens eine schon vorhandene Funktion an anderer Stelle zusätzlich eingebunden.
Und wie gesagt, das war oft an Programmstellen die beim Start nicht aufgerufen werden.
Nur wenn eine bestimmte If Abfrage das Programm komplett zum Absturz bringt, und ich andererseits jede Menge anderen Code dazupacken kann ohne das etwas passiert, das kann ich logisch nicht nachvollziehen.

Aber vielleicht ist das jemanden schon untergekommen?

Wie kann man überprüfen ob der RAM voll ist? Gibt es einen Befehl der mir das im laufenden Betrieb liefert?

LG!

markusj
19.08.2010, 16:14
Es gibt einen Trick: Dynamischen RAM-Verbrauch ermitteln (RN-Wissen) (http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Dynamischer_RAM-Verbrauch)

Insgesamt klingt das etwas chaotisch, von Zeit zu Zeit empfiehlt es sich, den Code etwas aufzuräumen und durchzustrukturieren ;)

mfG
Markus

Siro
19.08.2010, 17:22
Hallo,
ein ähnliches Phänomen hatte ich auch schon mit einem PIC Controller. Ich habe völlig blödsinnigen Code eingefügt, der nichtmal aufgerufen wurde und plötzlich lief mein Programm nicht mehr. Dann hab ich den Blödsinn wieder ausgeklammert und es lief. Es gab überhaupt keinen Zusammenhang zwischen dem unbenutzten Code. Die Ursache war, man sollte es nicht glauben eine "schlechte" Abblockung am Prozessor. Durch den zusätzlichen Programm-Code hat sich natürlcih der angesprungene Code im Flash Programmspeicher verschoben. Da der Flash in sogenannte Planes unterteilt ist, zieht der Prozessor beim aktivieren des Speichers mehr Strom, bei einer ungenügenden Abblockung springt er in die Wüste oder führt einen Reset aus. Vielleicht hast Du ein ähnliches Problem Versuche mal möglichst dicht an der Versorgungsspannung des Prozessors mit einem zusätzlichen Kondensator abzublocken Also zwischen Plus und Masse. Bei mir reichten 100nF.
So unglaublich es klingen mag, ich habe eine Woche im Programmcode gesucht und das eigentliche Problem war ein 100nF Kondi etwas zu weit entfernt vom den Prozssorpins.
mfg. Siro

Gock
19.08.2010, 17:51
Es kann sein, dass eine Optimierung des Compilers anders ausgeführt wird, wenn der Code fehlt. Das würde bedeuten, dass es mindestens einen weiteren Fehler gibt, der mit dem zusätzlichen Code nicht ins Gewicht fällt, also unsichtbar bleibt.
Interrupts können ähnliche Probleme gelegentlich auslösen, weil nicht immer klar ist, wann genau sie eintreten.
Wenn es am Compiler läge, würdest Du im Netz sehr wahrscheinlich etwas darüber erfahren.
Da es keine Warnungen gibt, kann man einige Dinge auschließen.
Aber eigentlich und logischerweise kann es natürlich nicht sein, dass ein Stück fehlerhafter Code ein Problem macht, wenn er nicht ausgeführt wird (sofern das restliche Programm und die Hardware fehlerfrei ist...). Und weil das so eindeutig ist, würde ich daran zweifeln, dass dieser Code wirklich nicht ausgeführt wird nach 10s.
Ich kenne ähnliche Probleme. Man hat eine Annahme, zB der Code würde nicht ausgeführt und sucht die Fehler überall, obwohl es höchst unlogisch ist. Am Ende stellt sich heraus, die Annahme war falsch und damit ist auch nichts mehr unlogisch.
Gruß

Hubert.G
19.08.2010, 18:04
Dein RAM ist auch schon zu 66,7% belegt. Wenn dann noch einige Variable dazu kommen dann kann der Stack schon mal überlaufen.
Vielleicht kannst du da etwas verlegen, LCD-Texte im Flash oder im EEPROM speichern z.B.

damfino
19.08.2010, 18:31
Den dynamischen Ram Verbrauch zu ermitteln hab ich grad versucht, geht nicht da das normale Fahrprogramm nicht mehr korrekt ausgeführt wird.

Der Flash war schon mal voller bevor ich mit der Option -s compilieren musste, und es ist ein Kondensator am Controller.

Das bei manchen Fehlern der betreffende Code sicher nicht ausgeführt werden sollte ist sicher. Denn eine Änderung bei zB Spiralfahrt kann sich nicht auf die normale Fahrt auswirken, denn er ruft diese nur in bestimmten Situationen auf, verlässt sie erst wenn er damit fertig ist, und das dauert ein paar Minuten.
Aber ich gehe davon aus dass er den Speicher für die Funktionen erst im Ram reserviert wenn die Funktion aufgerufen wird, deswegen erwarte ich ein Fehlverhalten genau dann, und nicht schon von Anfang an.

LG!

Gock
19.08.2010, 19:09
Ist es nicht so, dass in den RAM zu beginn auch unter anderem volatile Variablen geladen werden? Wenn Dein zusätzlicher Code auf Daten in einer Headerdatei oder sonstigen zugreifen "würde", kann es sein, dass dort ein Laden stattfindet, was ohne den Code nicht stattfinden würde. Bin aber nicht sicher.
Gruß

Hubert.G
19.08.2010, 23:05
Also globale und volatile Variablen werden gleich zu beginn geladen und bleiben zumindest als Platz reserviert.
Somit auch von Code der nicht abgerufen wird.

yaro
20.08.2010, 17:18
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

MichaF
20.08.2010, 18:31
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 ;)

damfino
20.08.2010, 21:04
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!

Bumbum
21.08.2010, 11:31
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

damfino
21.08.2010, 14:34
So, konnte den Fehler wieder hervorufen:
Das ist der normale Code der Wartefunktion

void Warten()
{
timecount=0;

while (1) { if (timecount>=50) break;}
}

und hier ist die Drehzahlüberprüfung eingebaut:

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!

yaro
21.08.2010, 14:55
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

MichaF
21.08.2010, 16:51
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.

damfino
21.08.2010, 17:56
Hier der Code für den Interrupt:


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:


//***********************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(buff er); // Anzeige GPS Daten nach Bedarf
lcd_gotoxy(13,0);lcd_puts(gpsstatus);
itoa(hd,buffer,10);lcd_gotoxy(15,0);lcd_puts(buffe r);
itoa(satcount,buffer,10);lcd_gotoxy(19,0);lcd_puts (buffer);

Datum();

}
}
}


Die restlichen Funktionen dazu:
Variablen die hier nicht deklariert sind, sind global.



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!

MichaF
22.08.2010, 10:17
Ohne vollständigen Code kann man ja nur Raten, aber beim Überfliegen ist mir gleich folgendes aufgefallen:


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!

damfino
22.08.2010, 11:16
Danke! Habs sofort eingebaut.

LG!

damfino
26.08.2010, 18:50
Anscheinend war es dieser Fehler beim UART, danach hat alles problemlos funktioniert.

Nachdem es funktioniert hat bin auf auf einen 644 umgestiegen, und habe jetzt Probleme mit Tastern und Sensoren: mal lösen sie von selbst aus, dann wieder nicht wenn sie es sollten. Alles mit Pull up.
Kann es sein dass der 644 empfindlicher auf Schwankungen in der Stromversorgung reagiert? Denn es liegt nicht an den Tastern und Sensoren, denn den 32 rein, und schon geht es wieder perfekt.

LG!

yaro
27.08.2010, 17:27
Auf welcher Frequenz lässt du ihn laufen?

Gruß, Yaro

damfino
27.08.2010, 17:59
Er hat einen 16Mhz Quarz, bei den Fuses ist die längste Start-up Zeit eingestellt.

Es sind alle am Port A angeschlossen:
#define Sensor_re ((PINA &(1 << PINA2)))
#define Sensor_li ((PINA &(1 << PINA3)))
#define Bumper (!(PINA &(1 << PINA4)))
#define Taster_Stop (!(PINA &(1 << PINA6)))
#define Taster_Schwarz (!(PINA &(1 << PINA7)))

am Pin 5 ist der ADC im free running Mode.

Davon funktionieren immer Sensor_re und Taster_Schwarz.
Sensor_li wird praktisch immer ignoriert, am Bumper kommen oft Fehlerauslösungen, am Taster_Stop kommen selten Fehlauslösungen.

Kann es sein dass es mit den ADC zusammenhängt? Sind schließlich die Pins um den verwendeten ADC betroffen.

/* ADC */
ADMUX |=(1<<REFS1) | (1<<REFS0); // interne 2.56V
ADMUX |=(1<<MUX2) | (1<<MUX0); // Kanal = PIN 5
ADCSRA |= (1<<ADEN) | (1<<ADSC) | ( 1 << ADATE ); // ADC ein + starten, free running mode
ADCSRA |=(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // prescaler 128


Die Sensoren haben Pullup am Sensor selbst, am Bumper habe ich zum internen noch einen externen Pullup angeschlossen, Taster haben nur den internen Pullup.

Stromversorgung kommt vom Akku mit 11,6-13,3V, über Diode, 1000µF C, 100nF C, L7805, 100nF C, und nochmal 100nF am Controller selbst.

LG!

yaro
27.08.2010, 20:30
JTAG aus?
AVCC an VCC?

Das SFIOR ist im m644 ADCSRB (name geändert) und etwas andere Funktionen, vielleicht hat es etwas damit zutun.

DIDR0 gibts im m644 aba nicht im m16

Guck da mal ein bisschen, vielleicht ist der Fehler ja schon dabei.

Pin-compatibel heißt nicht gleich Programm-Compatibel. Einige feinheiten gibts immer.

Gruß, Yaro

damfino
27.08.2010, 22:05
JTAG ist aus, am PortC ist die Motorsteuerung dran.
AVCC ist an VCC, braucht man ja auch am m32.

SFIOR habe ich nicht verwendet, ich setze die Pins so:
/* Eingänge mit Pullup*/
DDRA &= ~(1 << PA4); PORTA |= (1<<PA4); //Bumper
DDRA &= ~(1 << PA6); PORTA |= (1<<PA6); //Taster rot
DDRA &= ~(1 << PA7); PORTA |= (1<<PA7); //Taster schwarz

DIDR0 ist nicht gesetzt, laut Dok senkt es nur den Stromverbrauch, und der ist da mehr als vernachlässigbar. Aber ich werde es mal damit probieren.

Die anderen Unterschiede bei den Timern, PWM, USART habe ich alle geschafft, und nun schaffen mich simple IO Pins ](*,)

LG!

yaro
27.08.2010, 22:57
Gib mal die Eingänge auf nem LCD aus, ohne irgendwas anderes zu initialisieren. Dann kannst du sehen, obs an den Eingängen liegt, oder ob du iwas im Programm machst, was stört.

Gruß, Yaro

damfino
06.09.2010, 11:31
Nach vielen Versuchen und Anregungen von hier konnte die Probleme lösen:
Sensor: der m644 ist weniger empfindlich am Pin als die 2 m32 die ich hatte, eine LED am Sensor die die Funktion anzeigt entfernt und schon funktioniert es. Lt Datenblatt sind m32 und m644 gleich empfindlich, vielleicht hate ich einfach besonders gute bzw schlechte Exemplare.
Das Problem mit dem Bumper hat sich von selbst erledigt, einerseits nett, andererseits mag ich keine offenen Fragen.
Die letzten Programmfehler sind offenbar gelöst, leider auch ohne die echte Ursache zu kennen. Das Programm hatte zuvor max 9 Ebenen, ich hab es jetzt auf 7 Ebenen reduziert und das hat offenbar geholfen. Aber das bei 9 Ebenen beim m644 der Ram ausgeht halte ich für unwahrscheinlich, dann hätte es mit dem m32 gar nie funktionieren können. Ich konnte die Ursache für die Resets an genau eine Stelle nachvollziehen, ins Timeout bei der Navigation. Hier werden nach 2 Minuten zwei Variablen von 0 auf 1 gesetzt damit die Fahrt als erfolglos abgebrochen und die while Schleife dieser Funktion und damit die Funktion selbst verlassen wird. Die zweite Variable ist dabei eine globale damit auch der Rest der mit der Navigationsfahrt (zB Wegfindung zu weiteren Punkten) zu tun hat abgebrochen wird.
Warum soll das einen Reset auslösen?
Jetzt ist diese Funktion von max Ebene 7 auf max Ebene 5 gerückt, und es geht bisher ohne Reset.

Wenn ich noch herausfinde warum der Attiny Slave nicht will wäre ich so halbwegs zufrieden ;-)

LG!

MichaF
06.09.2010, 12:42
Warum soll das einen Reset auslösen?
Ich vermute immer noch das du mit dieser Art der Fehlersuche nicht glücklich werden wirst. Auch durch wahllose Änderungen unterdrückst du deine Probleme höchstwahrscheinlich nur. Es ändert sich beispielsweise die Reihenfolge von Variablen im Speicher, und ein irrlaufender Pointer hat gerade zufällig keine Auswirkungen mehr. Gehe deinen gesamten Code noch mal durch. Stück für Stück. Kontrolliere jede Variable auf ihren Wertebereich, und gib insbesondere acht auf Pointer/Arrays. Oder evtl. mal bei einem switch ein break; vergessen? Mir ist klar das so eine Aktion Stunden dauert. Es gibt unzählige Möglichkeiten, aber ich gehe fast jede Wette ein, das dein Problem den Namen Pointer trägt. Und über solche Probleme stolperst du früher oder später wieder wenn du sie nicht richtig beseitigst.

BurningWave
06.09.2010, 16:12
Dem stimme ich zu. Ich programmiere gerade ein größeres Programm mit C++ und hatte an den unmöglichsten Stellen Zugriffsverletzungen. Und woran lag es? Weil ich Speicher in der Datei-Lade-Funktion mit der alten C-Funktion malloc() reserviert habe anstatt mit new (was man in C++ benutzt) und malloc() bei komplexen Typen nicht funktioniert. Das wird bei dir sicher nicht das Problem sein, weil du in C programmierst, aber es ist ein gutes Beispiel dafür, dass Fehler auf unterster Ebene im späteren Programmverlauf zu sehr seltsamen Fehlern führen, die sehr schwer zu finden sind, gerade weil sie nicht immer auftreten.

damfino
07.09.2010, 11:16
Ich gehe den Code immer wieder auf Fehler durch, man ist aber oft schon blind die gleichen Stellen immer wieder durchzusehen. Der Compiler gibt leider nicht immer Warnungen raus, da gab es schon mal Tippfehler die er hätte melden müssen.
Mit Pointern stehe etwas auf Kriegsfuß und vermeide sie deswegen, denn ein Variablenüberlauf kann meines Erachtens weniger Schaden anrichten als ein fehlgeleiteter Pointer. Das der Code dadurch mehr Speicher braucht nehme ich in Kauf.
Aber man ist ja lernfähig, waren mir Anfangs zB die defines noch suspekt, so werden sie jetzt regelmäßig verwendet, und der Code wird mit jeder Änderung übersichtlicher und besser.

LG!

BurningWave
07.09.2010, 13:41
Pointer sind eigentlich was ganz tolles, deswegen würde ich sie verwenden. Man darf nur nicht fahrlässig mit ihnen umgehen und muss sich immer überlegen, auf was er zeigt und Adressen von den eigentlichen Daten unterscheiden.

Wenn der Code funktioniert und es zu keinen Problemen kommt, kannst du ja auch einfach mal weiterprogrammieren. Wenn du Glück hast, sind gar keine Fehler mehr vorhanden.

yaro
07.09.2010, 20:07
Arrays sind auch Pointer. (Falls du das nicht wusstest...)
Und ein Array-Überlauf führt (wie schon zig mal erwähnt) in der Regel zu mystischen Problemen...

Also nochmal alle Arrays prüfen, zur Not alle mal zu groß machen.

Gruß, Yaro