PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SFR05 an RP6Base



BeWe
26.01.2011, 18:30
Hallo,

ich habe seit Weihnachten einen RP6 und mir vor kurzem den Ultraschall-Sensor SFR05 gekauft. Link: http://www.nodna.com/product_info.php?products_id=616&XTCsid=1c153977611f3fb336cefd413990031d
Ich habe die Kabel so angebracht, das er in Mode2 arbeitet, was bedeutet, das Auslöse-Impuls und Echo über einen Port ausgelöst bzw. empfangen werden können. Nun hab ich aber als Anfänger nicht wirklich viel Ahnung, wie ich das Teil programmieren soll. Ich kann zwar den Impuls auslösen, weiß aber nicht, wie ich nun die Länge des zurückgesendeten Signals messen kann :(

Hier erstmal der Quelltext:


//Ultraschallsensor ansteuern und auswerten

#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();

powerON();

setStopwatch1(0);

while(true)
{

DDRC|=(SCL); //SCL als Ausgang definieren
PORTC&=~SCL; //SCL auf low setzten
setLEDs(0b100100);
startStopwatch1();
while(getStopwatch1()<11) PORTC|=SCL; //für 10ms SCL auf high setzten
PORTC&=~SCL; //SCL auf low setzten
setStopwatch1(0);
DDRC &=~(SCL); //SCL als Eingang definieren???

if(PORTC|=SCL) //Wenn SCL einen Impuls sendet und Stopwatch1 = 0, dann starte Stopwatch1
{
setLEDs(0b010010);
if(getStopwatch1()==0) startStopwatch1();

}

if(PORTC&=~SCL) //Wenn das Signal zuende ist??,dann stoppe Stopwatch1
{
stopStopwatch1();
}

if(getStopwatch1()>0) //Wenn Stopwatch1 > 0 dann setzte alle LEDs auf on
{
setLEDs(0b111111);
setStopwatch1(0);
}
mSleep(1000);
}

return 0;
}


Irgendwie ist aber Stopwatch1 nie größer als Null, was ja bedeuten würde, dass kein Signal empfangen wurde.
Es wäre schön, wenn mir jemand helfen könnte, da ich es irgendwie nicht gebacken bekomme :cry:

Mfg
BeWe

Dirk
26.01.2011, 19:22
Ein paar Sachen, die mir auffallen:

1. Der Impuls sollte ~10 µs und nicht ~10 ms sein.

2. Die if Abfragen gehen nicht mit PORTC, sondern mit PINC.

3. Warum kann die Stopwatch1 nur gestartet werden, wenn sie 0 ist?

4. Mit der 1ms Stopwatch wird man nicht sehr genau messen können. Vielleicht solltest du als Zähler den 100µs timer nehmen.

Gruß Dirk

BeWe
26.01.2011, 20:05
So,
erstmal danke für die schnelle Antwort!!!

Mhmm... mit dem Impuls muss ich mich irgendwie verlesen haben ](*,)
Die Stoppuhr hab ich jetzt auch so eingestellt, dass sie nicht nur startet wenn sie null ist und bei den if-Abfragen hab ich PORTC durch PINC ersetzt. Aber trotzdem wird die Stoppuhr nie größer als null, obwohl im Datenblatt steht, dass der Impuls bis zu 25ms lang sein kann, was die Stoppuhr ja erfassen müsste. Und wie kann ich eigentlich den 100µs-Timer aufrufen?

Gruß
BeWe

Dirk
27.01.2011, 20:21
Aber trotzdem wird die Stoppuhr nie größer als null, obwohl im Datenblatt steht, dass der Impuls bis zu 25ms lang sein kann,...
Du must dir auch noch mal deine Programmlogik genau ansehen:

1. An der Stelle, wo du mit "if (PINC & SCL)" auf die steigende Flanke des Impulses testest, müßtest du eigentlich auf diese Flanke WARTEN. Schreib das mal so um.

2. Wenn die steigende Flanke dann gekommen ist, müßtest du die Stopwatch starten.

3. Dann must du wieder WARTEN, bis die fallende Flanke des Impulses (SCL wird low: "(!(PINC & SCL))" ) kommt.

4. Danach kannst du dann den Stopwatch Wert auswerten.

5. Erst danach geht es dann nach einer PAUSE an den Anfang deiner while(true) Schleife mit einem neuen Impuls von 10µs.

Viel Erfolg!

Gruß Dirk

BeWe
29.01.2011, 21:13
ES FUNKTIONIERT!!!

Nach einigem probieren und befolgen von Dirks Tipps hab ich das Teil nun endlich zum laufen gebracht. Nochmal vielen, vielen Dank \:D/

EDIT: Wen es interessiert, ich hab mal ein kleines Video mit dem Ultraschallsensor erstellt:



http://www.youtube.com/watch?v=SXuaoKMKFYw

Gruß BeWe

BeWe
16.03.2011, 17:25
Hi!

Um den Ultraschallsensor nach links, rechts, oben und unten bewegen zu können, habe ich eine Servohalterung montiert. Nun wollte ich das Nick-Servo auch verwenden. Zum schonen der RP6-Akkus habe ich einen Empfängerakku aus dem RC-Bereich durch ein Y-Kabel mit den beiden Servos verbunden. Nun ist es aber so, dass sich nur dass Nick-Servo bewegt und das Gier-Servo gar nichts macht. Wenn ich nur dass Gier-Servo mit dem Roboterakkus verbinde und das Nick-Servo mit dem Empfängerakku, dann funktioniert das Gier-Servo und das Nick-Servo geht auf Anschlag und macht nicht was es soll. Andersrum macht nur das Nick-Servo etwas und das Gier-Servo macht gar nichts.

Weiß jemand, was ich da machen kann?

Dirk
16.03.2011, 17:53
@BeWe:

... habe ich einen Empfängerakku aus dem RC-Bereich durch ein Y-Kabel mit den beiden Servos verbunden.
Du hast aber schon Masse (GND, Minuspol) des RC-Empfängerakkus auch mit GND des RP6 verbunden?

Wenn ja: Wie steuerst du die Servos denn an?

BeWe
16.03.2011, 19:28
Mit GND habe ich den Empfängerakku nicht verbunden. Wenn ich das mache, leuchtet SL2 und die Servos machen nix. Außerdem hätten die Servos dann ja keinen Massenanschluss.
Angesteuert werden diese momentan über einen IO-Ports und extInt mit einem Programm, was ich hier im Forum gefunden habe.

EDIT: Klappt nun doch, ich hatte nicht beachtet, dass die Servos ja auch an GND angeschlossen sein müssen. Ich dachte, der Minus-Pol des Akkus würde auch gehen ](*,)
So, dann kann ich meinen Robby das Kopfnicken beibringen:cheesy:

BeWe
17.03.2011, 13:41
Hmmm...
So ganz einfach scheint es dann doch nicht zu gehen:(
Ich hab jetzt GND von Servos und seperaten Akku mit GND des Robbys verbunden. Wenn ich das Programm ausführe, bricht es dann irgendwann ab und der Roboter fährt so weiter, wie er es gerade getan hat.

Kann es sein, dass der Roboter durch den zusätzlichen Akku irgendwie überlastet wird??

RolfD
17.03.2011, 15:40
Und was will der Künstler uns damit sagen?
Dann wird da wohl ein Fehler im Programm sein.... *rolleyes
LG Rolf

Dirk
17.03.2011, 16:34
Kann es sein, dass der Roboter durch den zusätzlichen Akku irgendwie überlastet wird??
Nein, eigentlich nicht.
Nachdem wir das mit GND geklärt hatten:
Wie sieht es denn mit dem Pluspol des RC-Akkus aus?

Der sollte NUR mit den Servos (meist rotes Kabel) verbunden sein, aber nicht mit dem RP6.

Wenn das so ist: Zeig mal dein Programm!

BeWe
17.03.2011, 16:56
Das roten Kabel des RC-Akkus sind nur mit den roten Kabeln der Servos verbunden.

Hier wäre das (bestimmt unübersichtliche) Programm:


///Hindernisausweichen mit Ultraschallsensor

#include "RP6RobotBaseLib.h"

#define pos1 320
#define pos2 410
#define pos3 600

void usleep(unsigned char usec);

extern uint8_t acs_state;
uint16_t servo_pos, servo_pos2, servo_timer, servo_dummy, Zeit;
int16_t Dist, Dist_left, Dist_right, Dist_front;
int8_t x, z, a, Dist_3;

int main(void)
{
initRobotBase();

powerON();
startStopwatch3();
startStopwatch2();

servo_pos2=pos2;

a=0;
x=1;
z=0;
Dist_3=1;

servo_pos=1000;

setACSPwrLow();

while(true)
{

if ((getStopwatch2() > 20) && (acs_state < 2))
{

servo_timer = servo_pos;
extIntON();
while(servo_timer--) servo_dummy ^= servo_timer;
extIntOFF();
servo_timer = servo_pos2;
setLEDs(0b010000);
while(servo_timer--) servo_dummy ^= servo_timer;
setLEDs(0b000000);
z=z+1;
setStopwatch2(0);
}

if(z>3)
{
Dist=0;
DDRC|=(SDA);
PORTC&=~SDA;
PORTC|=SDA;
usleep(10);
PORTC&=~SDA;
DDRC&=~(SCL);

while(!(PINC& SCL))
{
setLEDs(0b000000);
}
while(PINC& SCL)
{
Dist=Dist+1;
usleep(1);
}
if(PINC&=~SCL)
{
if(Dist<23)
{

if(Dist<12)
{
servo_pos2=pos1;
startStopwatch4();
if(servo_pos<920)
{
a=0;
changeDirection(LEFT);
moveAtSpeed(50,50);
}
else
{
if(servo_pos>1150)
{
a=0;
changeDirection(RIGHT);
moveAtSpeed(50,50);
}
else
{
a=1;
stopStopwatch3();
setStopwatch3(1030);
if(adcLSL>adcLSR) {changeDirection(LEFT); moveAtSpeed(100,100);} else {changeDirection(RIGHT); moveAtSpeed(100,100);}
}
}
}
else
{
servo_pos2=pos2;
a=0;
stopStopwatch4();
setStopwatch4(0);
changeDirection(FWD);
if(servo_pos<1050)
{
moveAtSpeed(15,100);
}
else
{
moveAtSpeed(100,15);
}
}
}
else
{
servo_pos2=pos3;
a=0;
stopStopwatch4();
setStopwatch4(0);
changeDirection(FWD);
if(Dist_left-Dist_right>10)
{
moveAtSpeed(110,45);
}
else
{
if(Dist_right-Dist_left>10)
{
moveAtSpeed(45,110);
}
else
{
moveAtSpeed(100,100);
}
}
}
}
setStopwatch1(0);
z=0;
}

if(getBumperLeft()) {move(100, BWD, DIST_MM(150), true); rotate(100, RIGHT, 70, true);}
if(getBumperRight()) {move(100, BWD, DIST_MM(150), true); rotate(100, LEFT, 70, true);}

if(getStopwatch4()>2000)
{
if(adcLSL>adcLSR) {rotate(100, LEFT, 175, true);} else {rotate(100, RIGHT, 175, true);}
stopStopwatch4();
setStopwatch4(0);
}

if(servo_pos<700 && servo_pos>600) Dist_right=Dist;
if(servo_pos<1000 && servo_pos>1060) Dist_front=Dist;
if(servo_pos<1550 && servo_pos>1450) Dist_left=Dist;

if(a==0) startStopwatch3();

Zeit=getStopwatch3();

if(getStopwatch3()>1700)
{
if(x==0)
{
x=1;
setStopwatch3(0);
}
else
{
x=0;
setStopwatch3(0);
}
}

if(a==0)
{
if(x==0)
{
servo_pos=600+Zeit/2;
}

if(x==1)
{
servo_pos=1550-Zeit/2;
}
}
else
{
servo_pos=1030;
}

//task_RP6System();
task_ADC();
task_ACS();
task_Bumpers();
task_motionControl();
}

return 0;
}
void usleep(unsigned char usec)
{
for (int s=0; s<usec; s++) {
for (long int i=0; i<140; i++) {
asm volatile("nop");
asm volatile("nop");
}
}
}

RolfD
19.03.2011, 01:18
Hier wäre das (bestimmt unübersichtliche) Programm:


Manchmal versteh ich die Leute in meinem Umfeld nicht... Du benennst ein Problem sogar selbst und löst es nicht... statt dessen erwartest Du, das wir dein Problem zu unserem machen und es für dich lösen? Und das obwohl wir alle sicher eigene Aufgaben haben und kein SRF5 zum testen vorliegt. SO... wird das nix...

Vielleicht räumst Du erst mal dein ganz sicher unübersichtliches Programm auf, unterteilst es in Funktionen und logische Blöcke, (die man dann auch einzeln debuggen kann), kommentierst den Code anständig (ca. 50% des Textes sollte Docu sein) und versuchst damit schon selbst Lösungen zu erarbeiten? Meist findet man schon dabei die Probleme - wir helfen Dir gern wenn es dann noch klemmt - aber hier wird bestimmt keiner aus heiterem Himmel diesen endlos-Spagetticode debuggen!
Es gibt ein paar gute Faustregeln zum Thema Programmieren - die z.B. auch in den RP6Libs weitgehend umgesetzt sind - und diese Regeln wurden nicht erdacht, damit Hinz und Kunz Mainloops über sagenhafte 190 Zeilen schreiben und sich dann wundern wenn es irgendwo klemmt !
Du verstößt gegen allereinfachste Grundsätze wie aussagekräftige Variablennamen, Funktionen nicht länger als 1. Bildschirmseite, Constanten statt Zahlen usw... 190 zusammenhängende Zeilen nur und ausschließlich über Einrückungen lesbar zu machen ist heftig.
Beschäftige dich doch vielleicht mal mit "Brainfuck" - eine Bytecode Programmiersprache, die Deinen Arbeitsstil perfektioniert hat. Dort kannst Du schon mit 8 einfachen Befehlen vergleichbare Verwirrung stiften und Du sparst sogar das Einrücken der Befehle. :)
http://de.wikipedia.org/wiki/Brainfuck


>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]
<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
<++++>-]<+.[-]++++++++++.Für mehr visuell denkende Menschen und Mausschubser ist vielleicht besser "Piet" und ein Malprogramm geeignet...
http://de.wikipedia.org/wiki/Piet

Sehr schön, aber eher konventionell ist auch:
http://de.wikipedia.org/wiki/INTERCAL

... würde dein Zeichensalat da oben wenigstens fehlerfrei laufen - so wie diese wirklich abgedrehten 3 Beispiele - würde ich sagen.. "ok.. Genie und Wahnsinn liegen oft dicht beisammen" ... aber so ist das ein alphanumerischer Schrotthaufen und kein Programm! Tut mir leid wenn ich das so hart formuliere, ich hoffe Du lernst draus, machst es besser und nimmst es mir nicht übel.
LG Rolf