Hallo zusammen,
Ich kämpfe wieder mit unerklärlichen Resets, und je mehr ich versuche Fehler zu vermeiden, desto weniger funktioniert. Mal fährt er 5 Minuten richtig, mal 2h, zuletzt hatte ich alle Arrays global definiert, und dann stürzt er nach 1 Minute ab.
Sieht nach Stacküberlauf oder falschen Array Index aus, ich seh aber einfach den Fehler nicht.
Verwendet wird ein Atmega1284P mit 16Mhz, sollte also mit 16kB mehr als genug RAM vorhanden sein da zuvor ein 644 mit 4kB verwendet wurde. Speicherbedarf der Arrays + globale Variablen derzeit bei knapp 4kb, dazu die einzelnen Funktionen mit in Summe ca 100Byte.
Die Änderungen gegenüber dem Code für den 644er sind: Entfall von UART, Entfall vom LCD, und dafür mehr am TWI (Fleury lib), mehr Sensoren/Bumper ausgewertet. Also im Prinzip den alten Code genommen, UART und LCD gegen TWI Routinen getauscht, und Auswertung von 4 statt 1 Bumper. Arrays sind schon extra größer als notwendig definiert. Und ich bekomme das ehemals stabile Programm nicht mehr zum laufen.
Ich poste hier mal den Code der am ehesten für die Fehler verantwortlich ist:
die Arrays (für A* testweise global, ansonsten in der Funktion definiert)
Code:
#define grund_x 23 // 23 Anzahl Felder W-O
#define grund_y 42 //42 Anzahl Felder S-O
unsigned char Karte[grund_x+1][grund_y+1];
#define kartenfeld 100 // Größe eines Kartenfeldes in 1cm Einheit= 1m X 1m
#define pos_x_max (grund_x*kartenfeld-1)
#define pos_y_max (grund_y*kartenfeld-1)
// A*: Rand wird nicht berücksichtigt, daher um 2 kleiner
#define max_x_karte grund_x-2
#define max_y_karte grund_y-2
#define max_x max_x_karte-1
#define max_y max_y_karte-1
unsigned char x_vor_l_punkt[max_x_karte+1][max_y_karte+1]; // l_punkt <100, 100, 200, x_vor 0-99
unsigned char y_vor[max_x_karte+1][max_y_karte+1];
unsigned char g_wert[max_x_karte+1][max_y_karte+1];
für die Karte gibts eigene Routinen um Fehler auszuschließem:
Code:
unsigned char Karte_lesen(unsigned char x, unsigned char y)
{
unsigned char wert;
wert=150;
if ((x<grund_x)&&(y<grund_y))
{
wert=Karte[x][y];
}
return(wert);
}
void Karte_schreiben(unsigned char x, unsigned char y, unsigned char wert)
{
if ((x<grund_x)&&(y<grund_y)&&(x>=0)&&(y>=0))
{
if (wert==0)
{
if (Karte[x][y]<100) Karte[x][y]++;
}
else
{
if (Karte[x][y]<besetzt) Karte[x][y]=wert;
if (wert==besetzt) Karte[x][y]=besetzt; // für initialsierung der Karte notwendig
}
}
}
im A* sieht es so aus:
Code:
for (xt=0;xt<=max_x;xt++)// niedrigsten f-Wert ermitteln
{
for (yt=0;yt<=max_y;yt++)
{
if ((x_vor_l_punkt[xt][yt]>=100)&&(x_vor_l_punkt[xt][yt]<200)) // Punkte auf open List vergleichen
{
ff=2*((abs(xt-x_ziel))+(abs(yt-y_ziel)));
fwert=g_wert[xt][yt]+ff;// f=g+ h-Wert
for (ii=0;ii<8;ii++)
{
if (ii==0) {xx=xt;yy=yt+1;}
if (ii==1) {xx=xt;yy=yt-1;}
if (ii==2) {xx=xt+1;yy=yt;}
if (ii==3) {xx=xt-1;yy=yt;}
if (ii==4) {xx=xt+1;yy=yt+1;}
if (ii==5) {xx=xt+1;yy=yt-1;}
if (ii==6) {xx=xt-1;yy=yt+1;}
if (ii==7) {xx=xt-1;yy=yt-1;}
if (xt<=0) {xx=0;}
if (yt<=0) {yy=0;}
if (xx>max_x) {xx=max_x;}
if (yy>max_y) {yy=max_y;}
if (Karte_lesen(xt,yt)>=blockiert) fwert=fwert+2;
}
if (fwert>512) fwert=512;
if (fwert<temp)
{temp=fwert;xf=xt;yf=yt;}
}
}
}
In Verdacht habe ich auch die ISR, da diese doch länger ist:
Code:
/*+++++++Timer2++++++++++++++++*/
TCCR2A = (1<<WGM21);// CTC Mode
TCCR2B = (1<<CS22); // Prescaler 64
TIMSK2 = (1<<OCIE2A); //Interupt compare match enable
OCR2A=23; // alle 0,1ms 1 Interrupt
/*+++ Interrupt Messer +++++++++*/
EICRA |= (1<<ISC20) | (1<<ISC21); // steigende Flanke
EIMSK |= (1<<INT2); // Int enable
/*+++ Interrupt Vorderrad +++++++++*/
PCICR |= (1<<PCIE3); // Int 31-24 enable
PCMSK3 |= (1<<PCINT24); // Pin D0
/*+++ Interrupt Odo Links +++++++++*/
EICRA |= (1<<ISC10) ; // jede Flanke
EIMSK |= (1<<INT1); // Int enable
/*+++ Interrupt Odo Rechts +++++++++*/
EICRA |= (1<<ISC00); // jede Flanke
EIMSK |= (1<<INT0); // Int enable
/********** Interrupts ***********************************/
volatile unsigned char timecount,odo_li,odo_re,timer_zwei, mowerspeed;
volatile short i_summe,v_alt;
volatile unsigned short drehzahl_ist;
volatile unsigned short radcount, messer_zeit;
ISR(ISR_Timer2)
{
timer_zwei++;
messer_zeit++ ; if (messer_zeit>14000) messer_zeit=14000;
if (timer_zwei>100)
{timer_zwei=0;
timecount++;
radcount++;
}
}
ISR(INT0_vect) //Odo_re
{
odo_re++;
}
ISR(INT1_vect) // Odo_li
{
odo_li++;
}
ISR(INT2_vect) // Messerdrehzahl
{
short mowersp,v;
drehzahl_ist= (unsigned short)(300000L/messer_zeit);
v = (short)(drehzahl_soll-drehzahl_ist); //Vergleich
i_summe = i_summe + v/10; //(i_summe*9)/10 + v; //Integration I-Anteil
if (i_summe < -1000) i_summe = -1000; //Begrenzung I-Anteil
if (i_summe > 1000) i_summe = 1000;
mowersp=(3*v+15*((i_summe))+8*((v -v_alt)))/80;
v_alt=v;
if (mowersp < 77) mowersp = 77; //Begrenzung Stellgröße
if (mowersp > 255) mowersp = 255;
mowerspeed=(unsigned char)(mowersp);
Mower=mowerspeed;
messer_zeit=0;
}
ISR(PCINT3_vect) // Vorderrad
{
radcount=0;
}
die Messerdrehzahl, bzw PWM Wert für den Motor wird 2x pro Umdrehung berechnet, dh bei 2 Impulse pro Umdrehung und 2500U/min ca alle 12ms.
Pointer gibt es im Programm ausser den Arrays keine, was sonst kann den Code noch ruinieren?
Kämpfe mich mit Zeit und Schlafmangel schon wochenlang durch den Code, bin für jeden Hinweis dankbar!
LG!
Lesezeichen