Das war leider nicht das Problem. Ich habe jetzt an mehreren Stellen Sleep Funktionen zum beschleunigen eingebaut, damit er Zeit zum Beschleunigen hat und erst dann anfängt zu messen.
Das klappt auch ganz gut. Manchmal korrigiert er was, fährt ein stück relativ gerade aus, doch dann - wie die meiste Zeit - fährt er wieder ne Kurve.
Daher habe ich den Eindruck dass irgendwas mit meiner Logik nicht funktioniert - vielleicht ist es aber auch nur das Finetuning der Werte, ihr habt da mehr Erfahrung. Zur Logik habe ich mal kurz eine Skizze gemacht.
Das folgende Programm wurde an einigen Stellen überarbeitet, also besser dieses anschauen : ). Ich wäre euch sehr dankbar wenn ihr mir helfen könntet diese Hürde endlich mal zu bewältigen ; )!
Danke und Gruß!
Code:
#include "asuro.h" // Konfigurationsdateien laden
#define MITTER 155 // Die ca. Hälfte der Amplitude
#define MITTEL 140 // für die ersten Anpassungen
/* Funktionen definieren */
/* Globale Variablen */
unsigned char i; // Zähler
unsigned char alr=0; // schon (already) gelaufen?
unsigned char alr2=0; // schon (already) gelaufen?
unsigned int cntsL=0; // Zähler (counts)
unsigned int cntsR=0; // Zähler
unsigned int cnts=0; // Zähler
unsigned int odoData[2]; // Array für Odo Werte
unsigned int lrHi[2]={MITTEL, MITTER}; // left right highest
unsigned int lrLo[2]={MITTEL, MITTER}; // left right lowest
unsigned int spd0=190; // Geschwindigkeit (speed)
unsigned int spd1=190; // Geschwindigkeit
unsigned int odoMemL[3]; // Ododaten zwischenspeichern (ododmetrie memory)
unsigned int odoMemR[3]; // Ododaten zwischenspeichern
unsigned int testErg[2]; // Ergebnisse des Durchlaufes (test ergebnis)
// 0=low, 1=hi
void schlafen(unsigned int wert){
for(i=0; i<=wert; i++){
Sleep(72);}
}
/* Geradeausfahren */
char InitFwd(void){
schlafen(250);
StatusLED(RED);
schlafen(250);
StatusLED(YELLOW);
MotorDir(FWD,FWD); // zunächst gasgeben damit er fährt und Werte sammelt, Vortest
MotorSpeed(190,190);
schlafen(250);
while(cnts<500){ // 200 mal zählen
OdometrieData(odoData);
for(i=0; i<3; i++){ // 3 durchläufe für OdoWerte
OdometrieData(odoData);
odoData[0]=odoMemL[i];
odoData[1]=odoMemR[i];
if(odoData[0]>lrHi[0]){ // die Höchstwerte ermitteln LINKS
lrHi[0]=odoData[0];}
else if(odoData[0]<lrLo[0]){ // die Tiefstwerte ermitteln
lrLo[0]=odoData[0];}
if(odoData[1]>lrHi[1]){ // die Höchstwerte ermitteln RECHTS
lrHi[1]=odoData[1];}
else if(odoData[1]<lrLo[1]){ // die Tiefstwerte ermitteln
lrLo[1]=odoData[1];}
}
testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
/* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
/* links */
if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
cntsL++;}
else if((odoMemL[0]<odoMemL[1] && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
cntsL++;}
/* rechts */
if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
cntsR++;}
else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
cntsR++;}
if(cntsL>420 && cntsR>420){
alr=1;
StatusLED(RED);
schlafen(250);
StatusLED(GREEN);}
cnts++;
}//while cnts
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
StatusLED(YELLOW);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
StatusLED(YELLOW);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
StatusLED(YELLOW);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
return alr;
}
void Forward(void){
if(alr2 == 0){ // Beschleunigen damit er in Fahrt Werte sammelt
MotorDir(FWD,FWD);
MotorSpeed(spd0,spd1);
schlafen(250);
alr2 = 1;}
if(alr == 1){ // Falls Vorprüfung stattgefunden hat, ausführen
for(i=0; i<3; i++){ // 3 durchläufe für OdoWerte
OdometrieData(odoData);
odoData[0]=odoMemL[i];
odoData[1]=odoMemR[i];
if(odoData[0]>lrHi[0]){ // die Höchstwerte ermitteln LINKS
lrHi[0]=odoData[0];}
else if(odoData[0]<lrLo[0]){ // die Tiefstwerte ermitteln
lrLo[0]=odoData[0];}
if(odoData[1]>lrHi[1]){ // die Höchstwerte ermitteln RECHTS
lrHi[1]=odoData[1];}
else if(odoData[1]<lrLo[1]){ // die Tiefstwerte ermitteln
lrLo[1]=odoData[1];}
}
testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
/* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
/* links */
if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
cntsL++;}
else if((odoMemL[0]<odoMemL[1] && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
cntsL++;}
/* rechts */
if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
cntsR++;}
else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
cntsR++;}
if(spd1==255 || spd0==255){ // Falls Maximalspd erreicht Spielraum schaffen
spd1=spd1-10;
spd0=spd0-10;}
if(cntsL>cntsR){ // Korrektur!
spd1++;
StatusLED(RED);}
if(cntsL<cntsR){
spd0++;
StatusLED(GREEN);}
if((cntsR > 10000 || cntsL > 10000) && (cntsR>7000 && cntsL>7000)){ // aufpassen dass Variable nicht überläuft
cntsL=cntsL-7000;
cntsR=cntsR-7000;}
MotorDir(FWD,FWD); // und go!!
MotorSpeed(spd0,spd1);
}// if alr
}
/* Beginn des Hauptprogramms */
int main (void){
Init(); //Prozessor initialisieren
InitFwd(); // Odo Initialisieren
while(1) // Endlosschleife
{
Forward();
}
/* Schluss ! */
return 0;
}
// EDIT:
Mittlerweile bin ich mir relativ sicher dass das Problem beim Messen liegt. Durch die Schleife
Code:
for(i=0; i<3; i++){ // 3 durchläufe für OdoWerte
OdometrieData(odoData);
odoData[0]=odoMemL[i];
odoData[1]=odoMemR[i];
wird der Fall wie in der Skizze dargestellt nur sehr selten auftreten. Ein neuer Algorithmus muss her 
// EDIT die 2.:
So, jetzt habe ich einen neuen Algorithmus entwickelt. ASURO arbeitet jetzt mit durchlaufenden Werten und es sollten daher alle Übergänge verzeichnet werden.
Code:
/* Neuer Algorithmus: "Durchlaufende Werte" */
OdometrieData(odoData);
odoMemL[0]=odoMemL[1];
odoMemL[1]=odoMemL[2];
odoMemL[2]=odoData[0];
odoMemR[0]=odoMemR[1];
odoMemR[1]=odoMemR[2];
odoMemR[2]=odoData[1];
Klappen tut es allerdings noch nicht....
Ein bisschen Sorgen macht es mir, dass er bei folgender Kontrollfunktion auch niemals etwas ans Terminal sendet!!
Code:
if(cntsL>cntsR){ // Korrektur!
spd1++;
StatusLED(RED);
SerWrite("L groesser R",12);}
else if(cntsL<cntsR){
spd0++;
StatusLED(GREEN);
SerWrite("R groesser L",12);}
else if(cntsL==cntsR){
spd0++;
StatusLED(GREEN);
SerWrite("R gleich L",10);}
Irgendeine Idee warum es immer noch nicht klappt? Hier nochmal das komplette Program:
Code:
#include "asuro.h" // Konfigurationsdateien laden
#define MITTER 155 // Die ca. Hälfte der Amplitude
#define MITTEL 140 // für die ersten Anpassungen
/* Funktionen definieren */
/* Globale Variablen */
unsigned char i; // Zähler
unsigned char alr=0; // schon (already) gelaufen?
unsigned char alr2=0; // schon (already) gelaufen?
unsigned int cntsL=0; // Zähler (counts)
unsigned int cntsR=0; // Zähler
unsigned int cnts=0; // Zähler
unsigned int odoData[2]; // Array für Odo Werte
unsigned int lrHi[2]={MITTEL, MITTER}; // left right highest
unsigned int lrLo[2]={MITTEL, MITTER}; // left right lowest
unsigned int spd0=190; // Geschwindigkeit (speed)
unsigned int spd1=190; // Geschwindigkeit
unsigned int odoMemL[3]; // Ododaten zwischenspeichern (ododmetrie memory)
unsigned int odoMemR[3]; // Ododaten zwischenspeichern
unsigned int testErg[2]; // Ergebnisse des Durchlaufes (test ergebnis)
// 0=low, 1=hi
void schlafen(unsigned int wert){
for(i=0; i<=wert; i++){
Sleep(72);}
}
/* Geradeausfahren */
char InitFwd(void){
schlafen(250);
StatusLED(RED);
schlafen(250);
StatusLED(YELLOW);
MotorDir(FWD,FWD); // zunächst gasgeben damit er fährt und Werte sammelt, Vortest
MotorSpeed(190,190);
schlafen(250);
while(cnts<500){ // XXX mal zählen
/* Neuer Algorithmus: "Durchlaufende Werte" */
OdometrieData(odoData);
odoMemL[0]=odoMemL[1];
odoMemL[1]=odoMemL[2];
odoMemL[2]=odoData[0];
odoMemR[0]=odoMemR[1];
odoMemR[1]=odoMemR[2];
odoMemR[2]=odoData[1];
if(odoData[0]>lrHi[0]){ // die Höchstwerte ermitteln LINKS
lrHi[0]=odoData[0];}
else if(odoData[0]<lrLo[0]){ // die Tiefstwerte ermitteln
lrLo[0]=odoData[0];}
if(odoData[1]>lrHi[1]){ // die Höchstwerte ermitteln RECHTS
lrHi[1]=odoData[1];}
else if(odoData[1]<lrLo[1]){ // die Tiefstwerte ermitteln
lrLo[1]=odoData[1];}
testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
/* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
/* links */
if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
cntsL++;}
else if(((odoMemL[0]<odoMemL[1]) && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
cntsL++;}
/* rechts */
if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
cntsR++;}
else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
cntsR++;}
if(cntsL>420 && cntsR>420){
alr=1;
StatusLED(RED);
schlafen(250);
StatusLED(GREEN);}
cnts++;
}//while cnts
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
StatusLED(YELLOW);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
StatusLED(YELLOW);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
StatusLED(YELLOW);
schlafen(250);
StatusLED(GREEN);
schlafen(250);
return alr;
}
void Forward(void){
if(alr2 == 0){ // Beschleunigen damit er in Fahrt Werte sammelt
MotorDir(FWD,FWD);
MotorSpeed(spd0,spd1);
schlafen(250);
alr2 = 1;}
if(alr == 1){ // Falls Vorprüfung stattgefunden hat, ausführen
/* Neuer Algorithmus: "Durchlaufende Werte" */
OdometrieData(odoData);
odoMemL[0]=odoMemL[1];
odoMemL[1]=odoMemL[2];
odoMemL[2]=odoData[0];
odoMemR[0]=odoMemR[1];
odoMemR[1]=odoMemR[2];
odoMemR[2]=odoData[1];
if(odoData[0]>lrHi[0]){ // die Höchstwerte ermitteln LINKS
lrHi[0]=odoData[0];}
else if(odoData[0]<lrLo[0]){ // die Tiefstwerte ermitteln
lrLo[0]=odoData[0];}
if(odoData[1]>lrHi[1]){ // die Höchstwerte ermitteln RECHTS
lrHi[1]=odoData[1];}
else if(odoData[1]<lrLo[1]){ // die Tiefstwerte ermitteln
lrLo[1]=odoData[1];}
testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
/* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
/* links */
if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
cntsL++;}
else if((odoMemL[0]<odoMemL[1] && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
cntsL++;}
/* rechts */
if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
cntsR++;}
else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
cntsR++;}
if(spd1==255 || spd0==255){ // Falls Maximalspd erreicht Spielraum schaffen
spd1=spd1-10;
spd0=spd0-10;}
if(cntsL>cntsR){ // Korrektur!
spd1++;
StatusLED(RED);
SerWrite("L groesser R",12);}
else if(cntsL<cntsR){
spd0++;
StatusLED(GREEN);
SerWrite("R groesser L",12);}
else if(cntsL==cntsR){
spd0++;
StatusLED(GREEN);
SerWrite("R gleich L",10);}
if((cntsR > 10000 || cntsL > 10000) && (cntsR>7000 && cntsL>7000)){ // aufpassen dass Variable nicht überläuft
cntsL=cntsL-7000;
cntsR=cntsR-7000;}
MotorDir(FWD,FWD); // und go!!
MotorSpeed(spd0,spd1);
}// if alr
}
/* Beginn des Hauptprogramms */
int main (void){
Init(); //Prozessor initialisieren
InitFwd(); // Odo Initialisieren
while(1) // Endlosschleife
{
Forward();
}
/* Schluss ! */
return 0;
}
Lesezeichen