PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hinderniserkennung über die Spannung



cucu
27.05.2009, 22:25
Hi,

ich habe mir letztens überlegt eine Hinderniserkennung für Asuro zu schreiben die blockierte Räder erkennt also Asuro unterschtützt wenn die Taster vorne überfordert sind mit der Situation.
Ich habe mal eine Funktion geschrieben:


int kollision()
{

unsigned int ergebnisse[9];
int ableitung[8];

for (int b = 0; b < 9; b++)
{
ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 <<MUX0) | (1 << MUX2); // interne Referenz und ADC5( als analoger Kanal )

ADCSRA |= (1 << ADSC); // conversation START

while( !(ADCSRA & ( 1 << ADIF) ) ) // ADIF ist 0
{
; // Mache garnichts
}
// Messung ist zuende, da ADIF = 1

ADCSRA &= ~( 1 << ADIF ); // Setze ADIF auf 0

ergebnisse[b] = ADCL | ( ADCH << 8);
}

for (int c = 0; c<8;c++)
{

ableitung[c] = ergebnisse[c] - ergebnisse[c+1]; // Steigung zwischen den Messungen


}


for (int d = 0; d<8;d++)
{

if(ableitung[d] < (-25) )
{
if(d<7)
{
if((ergebnisse[d] - ergebnisse[d+2]) < (-10)) // Ableitung zum nächsten Punkt also Spitzen ausschließen
{
return TRUE;// Kollision
}
}
else // die letzte Ableitung also kein Vergleich nach vorne möglich
{
// Dann einen Messpunkt holen und vergleichen
int data;

// Messpunkt wird geholt

ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 <<MUX0) | (1 << MUX2); // interne Referenz und ADC5( als analoger Kannal )

ADCSRA |= (1 << ADSC); // conversation START

while( (ADCSRA & ( 1 << ADIF) ) ) // ADIF ist noch 0
{
; // Mache nichts
}
// Messung ist zuende, da ADIF = 1

ADCSRA &= ~( 1 << ADIF ); // Setze ADIF auf 0

data = ADCL | ( ADCH << 8);

// Jetzt kann man bestimmen, ob es eine Fehlmessung war oder nicht
if((ergebnisse[d] - data) < (-10)) // Ableitung zum nächsten Punkt also Spitzen ausschließen
{
return TRUE;// Kollision
}

}//else

}//if


}//for

return FALSE;//keine Kollision
}

Also bei mir funktioniert sie, wenn man beide Räder festhält.

Damit Asuro umdreht habe ich eine Funktion zum umdrehen geschrieben.
Ich habe mich dort für die Odometrie entschieden, da die Messungen nicht wirklich genau sind und man somit eine art Zufall beim umdrehen erhält.


void umdrehen()
{
unsigned int odom[2];
unsigned int odomSumme = 0;

for ( int i= 0; odomSumme < 20000;i++)
{
MotorDir(RWD,RWD);
OCR1A = 230; // Setze Motor Speed auf 230 von 255
OCR1B = 150; // Setze Motor Speed auf 150 von 255
OdometrieData(odom);
odomSumme += odom[1]/100;

}
//wieder geradeaus
MotorDir(FWD,FWD);
OCR1A = 230; // Setze Motor Speed auf 230 von 255
OCR1B = 230; // Setze Motor Speed auf 250 von 255
PORTD &= ~(1 << PD2); // Status LED rot aus
for (int i= 0; i<500;i++)
{
if(kollision()==FALSE && i > 250) // Warten bis Motoren wieder in die richtige Richtung fahren
{
break;
}
}
}

Beim umdrehen achte ich darauf, dass die Motoren angelaufen sind und somit sichergestellt ist, dass nicht schon wieder eine Blockade der Räder festgestellt wird.

Mein Großes Problem dabei ist, dass Asuro nach höchstens 5 mal umdrehen Abstürzt.
Es fangen alle Lichter an zu Leuchten. Oder es dreht sich nur ein Rad. Oder Asuro fährt dauerhaft geradeaus und reagiert gar nicht mehr.

Irgendwo muss ich einen oder mehrer große(n) Fehler machen.


THX cucu

radbruch
27.05.2009, 22:49
Hallo

Nette Idee. Dir ist aber schon klar dass du mit OdometrieData() keine Ticks zählst sondern die Helligkeitswerte der Odosensoren:

for ( int i= 0; odomSumme < 20000;i++)
{
MotorDir(RWD,RWD);
OCR1A = 230; // Setze Motor Speed auf 230 von 255
OCR1B = 150; // Setze Motor Speed auf 150 von 255
OdometrieData(odom);
odomSumme += odom[1]/100;
}


Was soll der Mix aus Libraryfunktionen und direktem Zugriff auf die Hardware? Es erschwert die Lesbarkeit enorm. Um die Ursachen der Abstürze einzugrenzen würde ich erstmal nur die erprobten Funktionen verwenden. Zu häufiges Laden der OCR1X-Register kann auch zu Problemen führen und sollte vermieden werden:


MotorDir(RWD,RWD);
OCR1A = 230; // Setze Motor Speed auf 230 von 255
OCR1B = 150; // Setze Motor Speed auf 150 von 255
for ( int i= 0; odomSumme < 20000;i++)
{
OdometrieData(odom);
odomSumme += odom[1]/100;
}


Gruß

mic

cucu
27.05.2009, 23:20
Sorry für die schlechte Lesbarkeit. Es ist der Versuch direkt Hardwarenah zu programmieren und alle Hintergründe zu verstehen, was dann aber den Code dann echt komplex aussehen lässt.
Deshalb habe ich ein paar Funktionen eingebaut. Werde das ändern.

Mit den Odometrie Daten habe ich nur so rumgespielt(brauchte nur etwas was zählt), damit ich irgendwie das zurückfahren Timen kann aber dennoch ein Zufall eingebaut ist.
Habe bis jetzt noch keine Nachteile festgestellt. Ausser als ich in der if ( größer als 80000 ) abgefragt habe, dann fuhr Asuro unendlich lang rückwärts. Woran lag das ?

Aber ich muss die OCR1x Register ja beschreiben damit Asuro sich umdrehen kann.
Das macht doch auch die Funktion in der Asuro libary.

Aber vielen Dank für die Antwort ich werde versuchen die Zugriffe auf die OCR1x zu minimieren.

radbruch
27.05.2009, 23:29
Bis 80000 kann man mit 16 Bit nicht zählen, deshalb wird odomSumme auch immer kleiner sein!

Es reicht wenn man die OCRX-Register einmal vor der while-Schleife mit dem aktuellen MotorSpeedwert läd.

cucu
27.05.2009, 23:54
Stimmt ist ja total logisch hatte auch an sowas gedacht aber dachte der Fehler liegt an meiner programmierweise.
Ist echt alles ne harte Nummer wenn man "einsteigen" will.