PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme bei Programmierung der Snake Vision für ASURO



nooby21
10.05.2011, 16:41
Ich versuche schon seit einiger Zeit meinen ASURO, den ich mit der Snake Vision erweitert habe, dazu zu bringen, dass er auf die wärmste Quelle, die er registriert zufährt, und wenn er an sie stößt ein stückweit rückwärts fahren.Danach sollte er nichts mehr tun. So leicht es sich auch anhört, bin ich mit meinen sehr beschränkten Programmierfähigkeiten nicht weit gekommen.

#include "asuro.h"

void ThermalData(unsigned int *data)
{

ADMUX = (1 << REFS0) | (1 << REFS1) | IR_LEFT;
ADCSRA |= (1 << ADSC);
while (!(ADCSRA & (1 << ADIF)));
ADCSRA |= (1 << ADIF);

data[0] = ADCL + (ADCH << 8);


ADMUX = (1 << REFS0) | (1 << REFS1) | IR_RIGHT;
ADCSRA |= (1 << ADSC);
while (!(ADCSRA & (1 << ADIF)));
ADCSRA |= (1 << ADIF);
data[1] = ADCL + (ADCH << 8);
}


int main(void)
{

unsigned int tdata[2];
signed int diff,sum;
Init();


while(1)
{

ThermalData(tdata);

sum=tdata[0]+tdata[1];
StatusLED(RED);

if(PollSwitch()==0){
MotorDir(FWD,FWD);


diff=((signed)tdata[0]-(signed)tdata[1])*32/sum;
if (diff>4) {

BackLED(ON,OFF);
MotorSpeed(0,140);
}
else if (diff<-4) {

BackLED(OFF,ON);
MotorSpeed(140, 0);
}
else {

BackLED(OFF,OFF);
MotorSpeed(140, 140);
}
}

else {

StatusLED(GREEN);
BackLED(OFF,OFF);
MotorDir(RWD,RWD);
MotorSpeed(140,140);
Sleep(2000);


}
}
return 0;
}


Mit diesem Programm fährt mein ASURO lediglich rechtsrum im Kreis und fährt nur solange rückwärts wie ein Taster gedrückt wird, obwohl er nach Tasterdrück eine gewisse zeitlang rückwärtsfahren soll.

Was muss ich verändern, damit das Programm funktioniert wie ich es will??? Oder ist schon der Ansatz an sich falsch???

Ich freu mich auf jede nur erdenkliche Rückmeldung, da ich selbst langsam nichts mehr verstehe.....

MfG nooby21

SprinterSB
10.05.2011, 18:48
data[...] = ADCL + (ADCH << 8);

Holla, das ist ja wie Russisch Roulette. Eine 50%-Wahrscheinlichkeit daß die Zugriffer wie von der Hardware vorgesehen passieren.

Warum nicht?

data[...] = ADC;

KR-500
10.05.2011, 20:18
Hi,

also als erstes würde ich mal empfehlen die Daten die gemessen werden über UART ausgeben zu lassen um einfach mal zu gucken was da los ist. Anstatt dem hier:

data[...] = ADCL + (ADCH << 8);könntest du auch:

data[...] = ADCW;schreiben. Ein weiterer Pukt an dem du ansetzen könntest wäre die Referenzspannung. Ich selber habe keine ASURO, habe mir aber mal das Snake Vision gekauft. Ich habe zum auswerten die interne Referenzspannung von 5 Volt benutzt. Ich habe dann übrigens schnell festgestellt das die Sensoren nur auf eine Entfernung von 30cm zu gebruachen sind. Wenn mein Ziel(Teelicht) weiter enfernt war dann haben die Sensoren nichts mehr feststellen können. Um auf die wärmste Quelle zu zufahren habe ich auch einen P-Regler verwndet das hat sehr gut geklappt und sah etwa so aus:


int ocr1a=0,ocr1b=0,dif=0,regler_kp=25,regler=0;
while((adc1<(pir+50))&&(adc2<(pir+50))){
adc1 = read_adc3();
adc2 = read_adc4();
dif = adc1 - adc2;

regler_kp = read_adc2()-128;

regler = (dif * regler_kp)/10;

speed = read_adc1();

ocr1a = speed - regler;
ocr1b = speed + regler;

if(ocr1a<0){ ocr1a = 0;}
if(ocr1b<0){ ocr1b = 0;}
if(ocr1a>255){ ocr1a = 255;}
if(ocr1b>255){ ocr1b = 255;}
OCR1A = ocr1a;
OCR1B = ocr1b;
}
An ADC1 und ADC2 habe ich noch Potentiometer um eine gewisse Grundgeschwindigkeit und die Regler_kp einzustellen. Und in der while-Schleife bleibt er solange bis er nah genug am Teelicht ist.

KR-500

nooby21
11.05.2011, 12:35
@SprinterSB

Leider hat sich weder mit ADC noch mit ADCW etwas verändert. Außerdem bin ich mir recht sicher, dass das Einlesen der Messwerte funktioniert, da ich diesen Teil des Programms aus dem Standartprogramm aus "Mehr Spaß mit ASURO 2" übernommen habe.

Hier mal das Standartprogramm:

#include "asuro.h"

// Schwellen für die intensitätsabhängige Geschwindigkeit

#define THRESH1 20
#define THRESH2 80
#define THRESH3 200


void ThermalData(unsigned int *data)
{
// ThermalData() funktioniert genauso, wie LineData(), ...
// ... nur dass dabei die interne Spannungsreferenz als ...
// ... AD-Wandlerreferenz verwendet wird.

// Prozessorinterne Referenz verwenden
// Multiplexer auf linken Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_LEFT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[0] = ADCL + (ADCH << 8);

// Prozessorinterne Referenz verwenden
// Multiplexer auf rechten Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_RIGHT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[1] = ADCL + (ADCH << 8);
}


int main(void)
{
// Speicher für die Messwerte bereitstellen
unsigned int tdata[2];
unsigned int speed;
signed int diff,sum;
Init();
// Motoren immer auf vorwärts
MotorDir(FWD,FWD);
while(1)
{
// Messwerte einlesen
ThermalData(tdata);
// Die Summe der Werte wird für die Berechnung der ...
// ... Geschwindigkeit genutzt
sum=tdata[0]+tdata[1];
// Signal stark genug?
if (sum>THRESH1) {
StatusLED(GREEN);
speed=140;
// Ziemlich stark?
if (sum>THRESH2) {
StatusLED(YELLOW);
speed=200;
}
// Sehr stark?
if (sum>THRESH3) {
StatusLED(RED);
speed=255;
}
// Richtung bestimmen
diff=((signed)tdata[0]-(signed)tdata[1])*32/sum;
if (diff>4) {
// Links deutlich wärmer? Nach links fahren!
BackLED(ON,OFF);
MotorSpeed(0,speed);
}
else if (diff<-4) {
// Rechts deutlich wärmer? Nach rechts fahren!
BackLED(OFF,ON);
MotorSpeed(speed, 0);
}
else {
// Sonst geradeaus!
BackLED(OFF,OFF);
MotorSpeed(speed, speed);
}
}
else {
// Keine Wärmequelle in Sicht? Stehen bleiben!
StatusLED(OFF);
BackLED(OFF,OFF);
MotorSpeed(0,0);

}
}
return 0;
}

ich glaube nun ist auch zu erkennen, dass ich dieses Programm einfach modifizieren wollte...
Mein Grundgedanke ist, dass ich if(sum>THRESH1) einfach durch if(PollSwitch()==0) ersetze, so dass ASURO anhält sobald ein Taster gedrückt wird.
Doch nicht mal so was funktioniert -.-

nooby21
11.05.2011, 12:43
@KR-500

Dein Programm hört sich sehr gut an. Allerdings glaub ich, dass so etwas für mein Verständnis um einiges zu hoch ist. Außerdem bekomm ich viele Promblemmeldungen bei deinem Programm ,da Befehle wie adc1 oder pir nicht definiert sind.

Ich vermute, dass mein Problem in der while-Schleife sitzt.

nooby21
11.05.2011, 13:22
Ich hab nun einfach das Standartprogramm übernommen und eine weitere If-Schleife eingefügt, die den ASURO zum anhalten bringen soll, wenn ein Taster gedrückt wird. Der ASURO fährt jetzt auf meine Wärmequelle (eine Teelicht) zu, zwar etwas ruckartig, aber es funktioniert. Das Anhalten bei Tasterdruck geht aber weiterhin nicht...


#include "asuro.h"

// Schwellen für die intensitätsabhängige Geschwindigkeit

#define THRESH1 20


void ThermalData(unsigned int *data)
{
// ThermalData() funktioniert genauso, wie LineData(), ...
// ... nur dass dabei die interne Spannungsreferenz als ...
// ... AD-Wandlerreferenz verwendet wird.

// Prozessorinterne Referenz verwenden
// Multiplexer auf linken Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_LEFT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[0] = ADCL + (ADCH << 8);

// Prozessorinterne Referenz verwenden
// Multiplexer auf rechten Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_RIGHT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[1] = ADCL + (ADCH << 8);
}


int main(void)
{
// Speicher für die Messwerte bereitstellen
unsigned int tdata[2];
unsigned int speed;
signed int diff,sum;
Init();
// Motoren immer auf vorwärts
MotorDir(FWD,FWD);

while(1)
{
// Messwerte einlesen
ThermalData(tdata);
// Die Summe der Werte wird für die Berechnung der ...
// ... Geschwindigkeit genutzt
sum=tdata[0]+tdata[1];
StatusLED(RED);

// Signal stark genug?
if (sum>THRESH1) {

speed=140;


// Richtung bestimmen
diff=((signed)tdata[0]-(signed)tdata[1])*32/sum;
if (diff>4) {
// Links deutlich wärmer? Nach links fahren!
BackLED(ON,OFF);
MotorSpeed(0,speed);
}
else if (diff<-4) {
// Rechts deutlich wärmer? Nach rechts fahren!
BackLED(OFF,ON);
MotorSpeed(speed, 0);
}
else {
// Sonst geradeaus!
BackLED(OFF,OFF);
MotorSpeed(speed, speed);
}
if(PollSwitch()){
MotorSpeed(0,0);
StatusLED(GREEN);}

}

else {
// Keine Wärmequelle in Sicht? Stehen bleiben!
StatusLED(OFF);
BackLED(OFF,OFF);



}
}
return 0;
}

nooby21
13.05.2011, 14:19
hat wirklcih keiner ne ahnung was ich tun muss? wär echt net wenn mal jemand über mein problem drüber schaun würd...

nooby21
13.05.2011, 15:49
Ich konnte mein Problem weitgehenst beheben. Allerdings kenne ich keinen Befehl, der den ASURO dazu bringt, nachdem er rückwärts gefahren ist, das gesamte Programm zu unterbrechen und einfach nichts zu tun...


#include "asuro.h"

// Schwellen für die intensitätsabhängige Geschwindigkeit

#define THRESH1 20
#define THRESH2 80
#define THRESH3 200


void ThermalData(unsigned int *data)
{
// ThermalData() funktioniert genauso, wie LineData(), ...
// ... nur dass dabei die interne Spannungsreferenz als ...
// ... AD-Wandlerreferenz verwendet wird.

// Prozessorinterne Referenz verwenden
// Multiplexer auf linken Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_LEFT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[0] = ADCL + (ADCH << 8);

// Prozessorinterne Referenz verwenden
// Multiplexer auf rechten Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_RIGHT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[1] = ADCL + (ADCH << 8);
}


int main(void)
{
// Speicher für die Messwerte bereitstellen
unsigned int tdata[2];
unsigned int speed;
signed int diff,sum;
Init();
// Motoren immer auf vorwärts
MotorDir(FWD,FWD);
while(1)
{
// Messwerte einlesen
ThermalData(tdata);
// Die Summe der Werte wird für die Berechnung der ...
// ... Geschwindigkeit genutzt
sum=tdata[0]+tdata[1];
// Signal stark genug?
if (sum>THRESH1) {

speed=140;
// Ziemlich stark?
if (sum>THRESH2) {

speed=140;
}
// Sehr stark?
if (sum>THRESH3) {
StatusLED(OFF);
speed=140;
}
// Richtung bestimmen
diff=((signed)tdata[0]-(signed)tdata[1])*32/sum;
if (diff>4) {
// Links deutlich wärmer? Nach links fahren!
BackLED(ON,OFF);
MotorSpeed(0,speed);
}
else if (diff<-4) {
// Rechts deutlich wärmer? Nach rechts fahren!
BackLED(OFF,ON);
MotorSpeed(speed, 0);
}
else {
// Sonst geradeaus!
BackLED(OFF,OFF);
MotorSpeed(speed, speed);

if(PollSwitch()){
MotorSpeed(0,0);
Msleep(900);
MotorDir(RWD,RWD);
MotorSpeed(140,140);
Msleep(900);
StatusLED(GREEN);}
}
}
//else if(PollSwitch()){
//MotorSpeed(0,0);
//StatusLED(GREEN);}

else {
// Keine Wärmequelle in Sicht? Stehen bleiben!
StatusLED(OFF);
BackLED(OFF,OFF);
MotorSpeed(0,0);



}
}
return 0;
}

Ceos
14.05.2011, 10:42
bau dir noch eine Variable für den Status ein, je nach Wert lässt du ihn in deiner main-schleife dann die entsprechende Aktion ausführen


switch(Status){
case(0): {/*hier deine Snakevision in der du bei einem Hindernis den Status auf 1 erhöhst*/ break;}
case(1): {/*hier dein Rückwärts-fahren bis du fertig bist und dann Status auf 2 erhöhst*/ break;}
case(2): {/hier das gelangweilte Rumstehen bis du irgendwas machst dass den Status auf 0 zurücksetzt ODER auf 3 erhöht falls du noch was vor hast*/ break;}
default: {/*default kannst du weglassen, aber solltest du deinem Status nicht vertrauen, kann es nicht schaden eine Fehlerausgabe oder sowas mit einzubauen ^^*/(kein break bei dem letzten Case/default)}
}

nooby21
15.05.2011, 14:22
@Ceos,

vielen Dank für den Tipp. Ich hab versucht deinen Hinweis umzusetzen und bin leider gescheitert... Mein ASURO fährt nach dem Einschalten sturr gerade aus und schaltet die LED auf Grün. Bei einem Tastendruck ändert sich daran auch nichts.
Hier mein Programm:

#include "asuro.h"

// Schwellen für die intensitätsabhängige Geschwindigkeit

#define THRESH1 20
#define THRESH2 80
#define THRESH3 200
#define STATUS 0

void ThermalData(unsigned int *data)
{
// ThermalData() funktioniert genauso, wie LineData(), ...
// ... nur dass dabei die interne Spannungsreferenz als ...
// ... AD-Wandlerreferenz verwendet wird.

// Prozessorinterne Referenz verwenden
// Multiplexer auf linken Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_LEFT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[0] = ADCL + (ADCH << 8);

// Prozessorinterne Referenz verwenden
// Multiplexer auf rechten Sensor schalten
ADMUX = (1 << REFS0) | (1 << REFS1) | IR_RIGHT;
// Wandlung starten
ADCSRA |= (1 << ADSC);
// Warten, bis Wandlung beendet
while (!(ADCSRA & (1 << ADIF)));
// ADCIF zurücksetzen
ADCSRA |= (1 << ADIF);
// ADC-Wert auslesen
data[1] = ADCL + (ADCH << 8);
}


int main(void)
{
// Speicher für die Messwerte bereitstellen
unsigned int tdata[2];
unsigned int speed;
signed int diff,sum;
StatusLED(OFF);



Init();
switch(STATUS){
case(0): {// Messwerte einlesen
ThermalData(tdata);
// Die Summe der Werte wird für die Berechnung der ...
// ... Geschwindigkeit genutzt
sum=tdata[0]+tdata[1];
// Signal stark genug?
if (sum>THRESH1) {
MotorDir(FWD,FWD);
speed=140;
// Ziemlich stark?
if (sum>THRESH2) {
speed=140;
}
// Sehr stark?
if (sum>THRESH3) {
speed=140;
}
// Richtung bestimmen
diff=((signed)tdata[0]-(signed)tdata[1])*32/sum;
if (diff>4) {
// Links deutlich wärmer? Nach links fahren!
BackLED(ON,OFF);
MotorSpeed(0,speed);
}
else if (diff<-4) {
// Rechts deutlich wärmer? Nach rechts fahren!
BackLED(OFF,ON);
MotorSpeed(speed, 0);
}
else {
// Sonst geradeaus!
BackLED(OFF,OFF);
MotorSpeed(speed, speed);

if(PollSwitch()){
STATUS==1;}
break;

}
case(1): { StatusLED(GREEN);
MotorSpeed(0,0);
Msleep(900);
MotorDir(RWD,RWD);
MotorSpeed(140,140);
Msleep(900);
STATUS==2;
break;}
case(2): { StatusLED(YELLOW);
MotorSpeed(0,0);
if(PollSwitch()){
STATUS==0;}
break;
}

}
}

}
}


ich befürchte, dass meine STATUS-deklarierung nicht passt oder die brea-Befehle falsch gesetzt sind. Ich würe mich über weitere Tipps freuen, da ich der Meinung bin, dass ich dieses Projekt so realisieren kann.

Gruß nooby21