PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Bitfeld Array



damfino
24.07.2014, 09:44
Ich hab mit ein Bitfield Array erstellt, mit dem ich die Karte vom Grundstück abbilde:
1. Feld 3 Bit: Zähler für Felder in denen der Roboter schon war
2. Feld 4 Bit: Zähler für temporäre Hindernisse: Wenn der Roboter selbst ein Hinderniss erkennt, soll hier der Wert hochgezählt werden
3. Feld 1 Bit: Bit setzen wenn das Feld blockiert ist, zB Haus, ist fix in Karte_init vorgegeben.

Der Roboter ist schon seit letztem Jahr mit der Karte unterwegs, bisher wurden nur Felder 1 und 3 verwendet.
Jetzt wollte ich auch Feld 2 verwenden, um damit eine teilweise selbstlernende Karte umzusetzen.

Wenn aber Werte in Feld 2 geschrieben werden (Funktion Karte_Temp_schreiben), wird auch zumindest Feld 3 verändert. Ob auch Feld 1 zufällig verändert wird kann ich nicht bestätigen da immer sehr viele Felder betroffen sind. Zumindest ist mir nicht aufgefallen dass diese auf einmal niedrigere Werte hätten, also sollte es passen.
Es werden oft gleich ganze Spalten (y) von Feld 3 verändert. Hatte zuerst das EEPROM in Verdacht, aber seitdem ich die Funktion Karte_Temp_schreiben deaktiviert habe, passt die Karte wieder. (Übertrage die Daten vom EEPROM ins Excel für eine übersichtliche Ansicht der Karte)


Damit es ja keine Fehler gibt wie über die Array Grenzen hinaus schreiben oder lesen, wird das Array nur über die unten gezeigten Funktionen beschrieben/gelesen.

Unten der Code, wo liegt der Fehler?
Mit falschen Werten in Feld 3 funktioniert die Navigation nicht mehr.

LG!


allgemeine defines der Karte:

#define grund_x 46 // Anzahl Felder W-O
#define grund_y 84 //Anzahl Felder S-O
#define kartenfeld 50 // Größe eines Kartenfeldes in 1cm Einheit
#define zielbereich 80 // auf 80*x cm genau soll Ziel erreicht werden
#define besetzt 1

#define pos_x_max (grund_x*kartenfeld-1)
#define pos_y_max (grund_y*kartenfeld-1)

// für A*
#define max_x_karte (grund_x/2-2)
#define max_y_karte (grund_y/2-2)
#define max_x (max_x_karte-1)
#define max_y (max_y_karte-1)
#define kartenfeld_navi (kartenfeld*2)

karte.h:

extern unsigned char Karte_lesen(unsigned char x, unsigned char y); /* liest 1x gemaehtes Felder */
extern unsigned char Karte_lesen_navi(unsigned char x, unsigned char y); /* liest 4x fixbesetze Felder */
extern unsigned char Karte_lesen_naviII(unsigned char x, unsigned char y);/* liest 1x fixbesetze Felder */
extern void Karte_schreiben(unsigned char x, unsigned char y, unsigned char wert); /* schreibt 1x gemaehtes Felder */
extern unsigned char Karte_Temp_lesen(unsigned char x, unsigned char y); /* liest 1x temp Felder */
extern void Karte_Temp_schreiben(unsigned char x, unsigned char y, unsigned char wert); /* schreibt 1x temp Felder */
extern void Karte_init(void); // besetzte Felder der Karte festlegen
extern void Karte_schreiben_init(unsigned char x, unsigned char y); /* schreibt 1x besetzt Felder */
extern void Karte_loeschen(void); // komplett löschen

Karte.c:

#include <stdlib.h>
#include "karte.h"
#include <allgemeine_defines.h>

static struct
{
unsigned char gemaeht:3;
unsigned char temp_besetzt:4;
unsigned char fixbesetzt:1;

} Karte[grund_x+1][grund_y+1];

/*+++++++++++++++ Karte bearbeiten ++++++++++++++++++++++*/
inline unsigned char Karte_lesen(unsigned char x, unsigned char y)
{
unsigned char wert;

if ((x<grund_x)&&(y<grund_y))
{
if (Karte[x][y].fixbesetzt!=0) wert=100; // beim überprüfen auf fertig gemäht müssen die besetzten Felder mitgezählt werden.
else wert=Karte[x][y].gemaeht;

}
else wert=255;

return(wert);
}



// 4 Felder auf 1x lesen, Navi verwendet Karte mit nur 1/4 Auflösung!!!!
inline unsigned char Karte_lesen_navi(unsigned char x, unsigned char y)
{
unsigned char wert;
wert=0;
if (((x*2+1)<grund_x)&&((y*2+1)<grund_y))
{
wert=Karte[x*2][y*2].fixbesetzt;
wert=wert+Karte[x*2][y*2+1].fixbesetzt;
wert=wert+Karte[x*2+1][y*2].fixbesetzt;
wert=wert+Karte[x*2+1][y*2+1].fixbesetzt;


}
else wert=255;

return(wert);
}

inline unsigned char Karte_lesen_naviII(unsigned char x, unsigned char y)
{
unsigned char wert;
wert=0;
if ((x<grund_x)&&(y<grund_y))
{
wert=Karte[x][y].fixbesetzt;

}
else wert=1;

return(wert);
}


inline void Karte_schreiben(unsigned char x, unsigned char y, unsigned char wert)
{
if ((x<grund_x)&&(y<grund_y))
{
if(Karte[x][y].fixbesetzt==0)
{
if (wert==0)
{
if (Karte[x][y].gemaeht<7) Karte[x][y].gemaeht++;
}
else
{if (wert>7) wert=7;
Karte[x][y].gemaeht=wert;
}
}
}
}

inline unsigned char Karte_Temp_lesen(unsigned char x, unsigned char y)
{
unsigned char wert;

if ((x<grund_x)&&(y<grund_y))
{
wert=Karte[x][y].temp_besetzt;
}
else wert=0;

return(wert);
}
inline void Karte_Temp_schreiben(unsigned char x, unsigned char y, unsigned char wert)
{
if ((x<grund_x)&&(y<grund_y))
{
if (wert==0)
{
if (Karte[x][y].temp_besetzt<=1) Karte[x][y].temp_besetzt=9;
if (Karte[x][y].temp_besetzt<13) Karte[x][y].temp_besetzt++;
}
else
{
if (wert>14) wert=14;
Karte[x][y].temp_besetzt=wert;
}

}
}

void Karte_schreiben_init(unsigned char x, unsigned char y)
{
if ((x<grund_x)&&(y<grund_y))
{
Karte[x][y].fixbesetzt=1;

}

}

/*++++++++++++++++++ Karte init +++++++++++++++++++++++++++*/
void Karte_init(void) // besetzte Felder der Karte festlegen
{unsigned char x,y;

// Tor
Karte_schreiben_init(14,0);Karte_schreiben_init(16 ,0);Karte_schreiben_init(18,0);
Karte_schreiben_init(15,0);Karte_schreiben_init(17 ,0);Karte_schreiben_init(19,0);
// Kompost
// Karte_schreiben_init(4,82,besetzt);Karte_schreiben _init(5,82,besetzt);Karte_schreiben_init(4,81,bese tzt);
for (x=2;x<=3;x++)
{for (y=77;y<=79;y++)
Karte_schreiben_init(x,y);
}
// Ecke Terasse Garagenmauer schwer erreichbar
// Karte_schreiben_init(17,29,besetzt);
// Zaun hinten

for (x=26;x<grund_x;x++) // Zaun hinten schief
Karte_schreiben_init(x,83);
for (x=28;x<grund_x;x++) // Büsche
Karte_schreiben_init(x,82);
for (x=28;x<grund_x;x++) // Büsche
Karte_schreiben_init(x,81);
for (y=72;y<grund_y;y++) // Büsche
Karte_schreiben_init(44,y);


// Zaun links
for (y=22;y<grund_y;y++)
Karte_schreiben_init(0,y);
for (y=64;y<grund_y;y++)
Karte_schreiben_init(1,y);
// Zaun rechts
for (y=46;y<grund_y;y++)
Karte_schreiben_init(45,y);
for (x=28;x<grund_x;x++)
Karte_schreiben_init(x,0);
//Haus
for (x=14;x<=38;x++)
{for (y=38;y<=60;y++)
Karte_schreiben_init(x,y);
}
// Garage
for (x=8;x<=16;x++)
{for (y=32;y<=47;y++)
Karte_schreiben_init(x,y);
}
for (x=10;x<=16;x++) // //schwer erreichbar ==> nicht als leeres Feld suchen und anfahren lassen, aber auch nicht für Zufallsfahrt blockieren
{for (y=18;y<=31;y++)
Karte_schreiben(x,y,3);
}


for (y=18;y<=32;y++) // Garagenmauern, notwendig für A*
{ Karte_schreiben_init(9,y);
Karte_schreiben_init(16,y);
}


// Terasse
for (x=16;x<=28;x++)
{for (y=30;y<=37;y++)
Karte_schreiben_init(x,y);
}



//Spielhaus
for (x=39;x<=42;x++)
{for (y=8;y<=12;y++)
Karte_schreiben_init(x,y);
}

//Sandkiste
for (x=40;x<=42;x++)
{for (y=15;y<=18;y++)
Karte_schreiben_init(x,y);
}

}


void Karte_loeschen(void)
{
unsigned char x,y;

for (x=0;x<grund_x;x++) // Karte komplett löschen
{
for (y=0;y<grund_y;y++)
{
Karte[x][y].fixbesetzt=0;
Karte[x][y].temp_besetzt=1;
Karte[x][y].gemaeht=1;
}
}
}

damfino
16.08.2014, 19:52
Keiner eine Ahnung warum Karte_Temp_schreiben nicht funktioniert?

Wsk8
16.08.2014, 20:05
Werde mir das demnächst mal ansehen. Sehe ich das soweit richtig, dass ein Fehler immer nur auftritt, wenn du Karte_temp_schreiben anwendest?

mfg

shedepe
16.08.2014, 20:09
Ich rate jetzt einfach mal so ins blaue rein und gebe mal paar möglichkeiten an die so ein Verhalten hervorrufen könnten. 1. Du versuchst mehr als 4 bit reinzuschreiben. 2. Der Speicher deines Microcontrollers reicht nicht aus. 3,. Du greifst sonst irgendwie drauf zu und zerschiest dabei was.

damfino
16.08.2014, 21:20
@Wsk8: genau, die Funk​tion Karte_temp_schreiben beeinflusst Feld 3, die Karte funktioniert nur wenn diese Funktion nicht verwendet wird.

@shedepe: der Kontroller hat noch 9kB SRam frei. Es wird nur über diese hier aufgeführten Funktionen auf das Array zugegriffen, gerade um ein zerschiesen des Programmes auszuschließen!

LG!

Sisor
16.08.2014, 21:21
static struct {
unsigned char gemaeht:3;
unsigned char temp_besetzt:4;
unsigned char fixbesetzt:1;
} Karte[grund_x+1][grund_y+1];

Warum grund_x+1 bzw. grund_y+1 statt grund_x bzw. grund_y?

damfino
17.08.2014, 07:37
Angstbytes damit das Array sicher groß genug ist.
LG!

Wsk8
17.08.2014, 11:50
Also Karte_temp_schreiben sollte korrekt funktionieren. Gab bei mir keine Probleme. Und wenn du die 4 Bits voll ausnutzen möchtest, dann dürfen da Werte <= 15 drin stehen.

mfg

markusj
17.08.2014, 13:05
Wenn du sagst, dass ganze Spalten (mehrere X=const, Y=variabel Koordinaten) betroffen sind, spricht das eigentlich für einen Fehler außerhalb. Läuft dein Code auch ohne angeschlossene Hardware (oder alternativ: Hast du Zugang zu einem Hardware-Debugger? Dann würde ich dir nämlich raten, einfach Mal dem AVR beim Rechnen zuzusehen und zu beobachten wann die betreffenden Speicherbereiche beschädigt werden.

Alternativ könntest du versuchen, Routinen zur Speicher-Validierung umzusetzen (dir z.Bsp. einige Zellen mit bekanntem Inhalt auswählen, deren Inhalt vor/nach jeder Manipulation prüfen und sobald eine Abweichung vom Soll auftritt, Alarm schlagen und möglichst detailliert den aktuellen Systemzustand ausgeben).

mfG
Markus

damfino
18.08.2014, 11:27
Hm, werde die Funktion wieder aktivieren, rechne aber dass es wieder die Karte zerstören wird. Ohne Karte_temp_schreiben waren die Werte stabil, dh die blockierten Felder waren immer sichtbar.
Überlege was ich zur Speicher Validierung umsetzen kann, vielleicht ein paar fixe Positionen mit Karte_temp_schreiben beschreiben, um zu sehen wie lange oder bei welchen Positionen die Karte fehlerhaft wird.

LG!

markusj
18.08.2014, 12:37
um zu sehen wie lange oder bei welchen Positionen die Karte fehlerhaft wird.

Und vor allem: Ausgelöst durch welche Funktionsaufrufe? Mit welchen Parametern? Welche Werte standen vorher an den entsprechenden Positionen? Du brauchst mehr Informationen damit du weg vom reinen Rätselraten kommst.

mfG
Markus