PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 Software (Library und Demos)



Dirk
04.07.2007, 20:35
Hier kann es um die mitgelieferte Software des RP6 gehen.
Welche Funktionen enthält die RP6Lib? Was könnte man verbessern? Probleme mit den Demos? usw. usw.

Schaun wir 'mal, was da in C auf uns zu kommt! O:)

Gruß Dirk

radbruch
12.07.2007, 14:12
Es wäre schöner, wenn die LEDs wie die zugeordeten Bits von 0 bis 5 gezählt würden.

Aktuell:

setLEDs(0b000001); // Und dieser schaltet StautsLED1 an und alle anderen aus.

Schöner wäre doch so:


setLEDs(0b000001); // Und dieser schaltet StautsLED0 an und alle anderen aus.
(Der Tippfehler im Komentar ist übrigens aus der Doku, im Kapitel "4.6.4. Status LEDs und Bumper")

Im LED-Struct der BaseLib.h:


struct {
unsigned LED1:1;
unsigned LED2:1;
unsigned LED3:1;
unsigned LED4:1;
unsigned LED5:1;
unsigned LED6:1;
unsigned reserved1:1;
unsigned reserved2:1;
};

Und die Reserve vielleicht 6+7?

Man könnte dann viel einfacher Bitmanipulationen im Bitfeld machen wenn die LED-Namen mit 0 starten. Es fehlt auch eine getLEDS()-Funktion.

Gruß

mic

SlyD
12.07.2007, 15:22
Hallo mic,

es gibt beim RP6 6 Status LEDs.
Die heissen SL1 bis SL6 was eine Abkürzung für StatusLED1 bis StatusLED6 ist.
Das ist mit SL1 bis 6 auf dem Mainboard beschriftet, würde ich daher eigentlich ungern ändern.



Man könnte dann viel einfacher Bitmanipulationen im Bitfeld machen wenn die LED-Namen mit 0 starten.


Hier verstehe ich nicht ganz was Du mir eigentlich sagen willst?
Was hat der Name einer LED mit Bitmanipulationen zu tun?

Die LEDs heissen einfach so! Habe auch noch nirgendwo eine LED0 gesehen ;)




Es fehlt auch eine getLEDS()-Funktion.


Könnte man noch hinzufügen - ja. Braucht man aber nicht unbedingt - wenn dann würde ein Makro reichen.

Über diese Union (aus RP6RobotBaseLib.h):



union {
uint8_t byte;
struct {
unsigned LEDsR:3;
unsigned LEDsL:3;
unsigned reserved:2;
};
struct {
unsigned LED1:1;
unsigned LED2:1;
unsigned LED3:1;
unsigned LED4:1;
unsigned LED5:1;
unsigned LED6:1;
unsigned reserved1:1;
unsigned reserved2:1;
};
} statusLEDs;


kannst Du einfach auf das Status LEDs byte und die einzelnen LED Bits zugreifen.
Wird in der Anleitung auch beschrieben wie das geht.
(Schreiben zumindest - lesen ist aber nicht viel anders)

Du kannst direkt die Variable "statusLEDs.byte" verwenden.
Oder statusLEDs.LED1 bis 6

Hier ein Auszug aus einem Beispielprogramm:


if(obstacle_left && obstacle_right) // Obstacle in the middle?
statusLEDs.byte = 0b100100;
else
statusLEDs.byte = 0b000000;
statusLEDs.LED5 = obstacle_left;
statusLEDs.LED4 = (!obstacle_left); // Inverted LED5!
statusLEDs.LED2 = obstacle_right;
statusLEDs.LED1 = (!obstacle_right); // Inverted LED2!

// Update the LED values:
updateStatusLEDs();




-------

Die beiden reservierten Bits sind da eigentlich nur um den Rest vom Byte auch noch bitweise zugänglich zu machen. Brauchst Du abernicht. Mache ich einfach immer so um zu kennzeichnen das da noch Bits frei sind in dem Byte...

MfG,
SlyD

radbruch
12.07.2007, 16:29
Hallo

Ich bitte um Nachsicht, ich bin doch noch c-Neuling. Den lesenden Zugriff mit .byte habe ich inzwischen auch entdeckt. Und das mit LED1 das Bit 0 gemeint ist , werde ich mir schon merken können.

Kann ich mit der Libary auch die PWRON-LED steuern? Ich finde das nirgends.


Mache ich einfach immer so um zu kennzeichnen das da noch Bits frei sind in dem Byte... Für blinken links/rechts zum Beispiel

Gruß

mic

SlyD
12.07.2007, 16:41
Hallo mic,



Ich bitte um Nachsicht, ich bin doch noch c-Neuling.


Hatte ich schon fast wieder vergessen ;) Sorry ;)


Ja die PWRON Led kannst Du mit den Funktionen

powerON()

und

powerOFF()

steuern.
Es sind eigentlich keine richtigen Funktionen - sind nur Makros, die einen I/O Pin umschalten (s. RP6RobotBase.h):



// Enable/Disable Encoders, IR Receiver and Current Sensors to
// save power when not moving.
#define powerON() PORTB |= PWRON
#define powerOFF() PORTB &= ~PWRON


Die LED zeigt an, ob beide Encoder, Stromsensoren und ACS angeschaltet sind. Wenn man das alles inkl. POWERON LED ausschaltet, spart man insgesamt etwa 10mA an Strombedarf.


Da hat mich adrisch schon drauf hingewiesen - das fehlt noch im Handbuch. Da wird bisher nur drauf hingewiesen, dass ohne powerON auszuführen die Encoder, Motorstromsensoren und das ACS nicht funktionieren.
Das füge ich natürlich noch ein.

MfG,
Dominik

radbruch
12.07.2007, 17:17
Hallo

Alles klar, dass hatte ich auch gelesen und powerON() und powerOFF() auch schon in meine Kurzreferenz eingefügt. Da dann aber auch die LEDs der Sensoren ausgehen, dachte ich, es gibt vielleicht eine Möglichkeit die PWRLED einzeln anzusteuern. Das geht aber nicht laut Schaltplan, da hätte ich auch gleich reinschauen können.

Danke für die Infos.

Gruß

mic

Xtreme
13.07.2007, 19:58
Da ja in einem anderen Thread mehr Infos von den Testern des RP6 gefordert wurden, will ich euch mal ein bisschen was über die Demoprogramme erzählen:
Es werden 20 Beispielprogramme für die "Base-Platine" und 11 für die Erweiterungsplatine mitgeliefert. Zusätzlich ist ein Selftestprogramm dabei.
Alle Demos sind jeweils in zwei Ausführungen dabei, einmal in kommentierter Form (sehr ausführlich!!, ideal für Einsteiger) und einmal unkommentiert.
Die Base- Demos reichen vom Klassiker "LEDs" ansteuern, über ACS, Statemachine und Lightfollowing bis hin zu I2C Master/Slave.
Die "Qualität" der Demos ist durchweg einwandfrei, also sehr lehrreich.

radbruch
13.07.2007, 21:37
Hallo

Ich muss nun auch mal dem "Druck der Öffentlichkeit" nachgeben und euch ein paar (wie bei meinen Beiträgen üblich eher unspektakuläre) Videos meiner Tests zeigen:

Eines der Demos (Move4) prüft beim Fahren die Bumper und weicht bei Kontakt aus:

http://radbruch.roboterbastler.de/rp6/pics/demo-move4/demo-move4-org.mpg
(ca. 7MB, 320X240)

Wie man deutlich sieht, ist die KI dieses Demos noch nicht wirklich ausgereift. Aber das sind ja auch nur (super kommentierte, allerdings in Englisch) Beispiele die wohl zum Nachdenken (das hatten wir doch schon) und verbessern anregen sollen. Eine kleine Änderung und der RP6 kann's schon deutlich besser:

http://radbruch.roboterbastler.de/rp6/pics/demo-move4/demo-move4-neu1.mpg
http://radbruch.roboterbastler.de/rp6/pics/demo-move4/demo-move4-neu2.mpg
(je ca. 2MB)

Der RP6 rasseln zwar etwas beim Fahren, aber daran stört sich mein Hund (Sally, ein 11jähriges Dobermannmädchen) nicht besonders. O:)

Unglaublich, draußen ist super Sommer und ich hocke in der Bude und spiele mit dem RP6. Ich bin eindeutig suchtgefährdet... ;)

Gruß

mic

Sommer
14.07.2007, 09:29
Hi Leute!

Ja es schein wieder Sommer zu werden ;-)
Ist passend hab Urlaub :-)

Dickes Lob! Jetzt wird das ganze schon Informativer.

@Radbruch: Ich weis nicht ob du auch den RP5 hast oder in Betrieb kennst, aber ist das neue Getrieb viel leiser als das vom RP5?

Schönes Wochenende Ulli

Xtreme
14.07.2007, 10:14
Ich hab den RP5 hier, und mach auch zu dem Thema gerade ein Video... einen Moment noch...

radbruch
14.07.2007, 10:38
Hallo Sommer,

vermutlich kannst du die Wortspiele mit deinem Namen schon lange nicht mehr hören. :-#

Zu deiner Frage:
Nein, ich habe keinen RP5. Mein asuro ist der erste und einzige Roboter den ich vor dem RP6 hatte.
Der ist aber nach meinem Kettenumbau (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=31572) nun auch deutlich lauter als der RP6:

http://radbruch.roboterbastler.de/rp6/pics/demo-move4/kettenasuro.mpg
(ca. 1,7MB, 320X240, rc5-gesteuert)

Gruß aus dem Pool

mic

Sommer
14.07.2007, 14:35
Ja das ist aber mal ne ausgefallene Idee, den Asuro auf Kette umzubauen!
Sieht echt gut aus!!!

Wie man sieht lohnt sich der Name! Ich habe Urlaub und das Wetter wird schön... noch fragen ;-)

Grüße von der anderen Seite des Pool´s :-)

radbruch
14.07.2007, 16:09
Hallo

Ich kenne vom RP5 nur dieses PC-Welt-Video aus deren Robotertest, aber das ist sehr kurz und der Sound ist mies:

http://radbruch.roboterbastler.de/rp6/pics/demo-move4/robby_rp5_auf_der_rampe.mpg

Mir gefällt der kettenasuro auch sehr gut, allerdings wird er wohl demnächst in der Vitrine verschwinden, ich habe ja nun ein neues "Auto".

Gruß

mic

Xtreme
15.07.2007, 12:02
Bei dem Video Upload heute Nacht ist wohl was schief gelaufen... ich probiers gleich nochmal.

Xtreme
17.07.2007, 21:15
Das Video zum Thema Lautstärke ist ja bereits online.

Heute habe ich mal begonnen die Fähigkeiten der Antriebsfunktionen zu testen.
Wie schon erwähnt gibt es sehr brauchbare Routinen, wie "Drehen um einen best Winkel" oder "Fahren einer best Strecke".
Es ist z.B. ganz einfach ihn 30cm nach vorne fahren zu lassen. Die Motioncontrol übernimmt ganz automatisch die Regelung der Motoren und die Abfrage der Radencoder. Der Code dazu sieht so aus:


#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
powerON();

move(60, FWD, DIST_MM(300), true);

while(true);
return 0;
}


Wie genau er die 30cm fährt sieht man hier:
http://video.google.de/videoplay?docid=4436610195576011984&hl=de

Da 30cm noch nicht sehr aussagekräftig sind werde ich demnächst mal größere Strecken probieren.
Auch die Rotate Funktionen der Lib werden noch getestet.

radbruch
19.07.2007, 01:03
Hallo

Die Fahrregelung der RP6-Lib ist noch nicht optimal, man sieht und hört es deutlich beim Fahren. Hier ein kleines Testprogramm, dass die wichtigsten Daten beim Beschleunigen, bei Konstantfahrt und beim Verzögern an den PC sendet. Als Grundlage für unsere Diagrammkünstler, denn das kann ich leider nicht so gut.

Mit diesem Programm beschleunigt der RP6 auf eine definierte Sollgeschwindigkeit, fährt eine definierte Zeit konstant und verzögert dann. Während der Fahrt werden in definierten Abständen die wichtigsten Fahrdaten zum PC gesendet. (definiert=mit #define am Anfang des Programms festgelegt)


// Beschleunigen, Konstantfahrt und Verzögerung mic 19.7.07
// mit der Funktion moveAtSpeed() aus der RP6-Library

// Die Funktion regelt selbständig über das Task-System die Geschwindigkeit,
// während laufend (einstellbar) die folgenden Daten zum PC gesendet werden:

// Datensatznummer
// Sollwert der Geschwindigkeit / 90% davon (Maxwert Speed ist 200, wird begrenzt)
// Istwert der Geschwindigkeit Links / Rechts
// Aktueller PWM-Werte der Geschwindigkeit (Maxwert PWM ist 210!!!)
// Aktueller Motorstrom Links /Rechts
// Anzeige für Geschwindikeit +-%5 vom Soll Links/Rechts

// LEDs:
// Alle an bedeutet, dass die Fahrt in 0,5 Sekunden beginnt!
// 3+6 blinkend beim Beschleunigen
// 2+5 blinkend beim Verzögern
// 1+4 innerhalb +-5% bei Konstantfahrt
// 1+4 blinkend am Programmende

// PWLED leuchet während der Fahrt ;)

// ++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++
// ++++ ++++
// ++++ ACHTUNG! DER RP6 FÄHRT BEI DIESEM PROGRAMM!!! ++++
// ++++ ++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++

#include "RP6RobotBaseLib.h"
#define speed 75 // Dies ist die Sollgeschwindigkeit
#define konstantfahrt 2000 // Dauer der konstanten Fahrt in ms
#define samplerate 10 // 10ms bedeutet 100 Werte/Sekunde zum PC senden
#define debug false // Textausgaben zwischen den Werten einschalten? (true=an)

uint8_t loop; // Vor und wieder zurück, wir wollen ihm ja nicht nachlaufen ;)
uint16_t data_count=0; // Zählt die gesendeten Datensätze

void daten_senden(void) // diese Funktion sendet die Daten
{
setStopwatch2(1); // gleicht Zeitfehler aus?
writeInteger(data_count++, DEC); // Anzahl übertragene Datensätze
writeString_P("\t"); // Cursor weiter zur nächsten Tabstelle

writeInteger(speed, DEC); // Sollgeschw. und 90%-Limit
writeString_P("/");
writeInteger(speed*9/10, DEC);
writeString_P("\t");

writeInteger(getLeftSpeed(), DEC); // Speed Istwerte
writeString_P("/");
writeInteger(getRightSpeed(), DEC);
writeString_P("\t");

writeInteger(mleft_power, DEC); // PWM Istwerte
writeString_P("/");
writeInteger(mright_power, DEC);
writeString_P("\t");

writeInteger(adcMotorCurrentLeft, DEC); // Motorströme
writeString_P("/");
writeInteger(adcMotorCurrentRight, DEC);
writeString_P("\t");

// Bei ca. +-5% der Sollgeschwindigkeit setzen wir noch ein Sternchen
if ((getLeftSpeed() > speed*19/20) && (getLeftSpeed() < speed*21/20))
writeString_P("*"); else writeString_P(" ");
writeString_P("/");
if ((getLeftSpeed() > speed*19/20) && (getLeftSpeed() < speed*21/20))
writeString_P("*"); else writeString_P(" ");

writeString_P("\n\r"); // Zeilenvorschub
}

int main(void)
{
initRobotBase();
setLEDs(0b111111); // alle LEDs anschalten
startStopwatch1(); // Start des allgemeinen Zeitgebers bis 65,3 sek ;)
writeString_P("Regelungtest:\n\rMotor beschleunigt, fährt konstant und ");
writeString_P("verzögert. mic 18.7.07\n\n\r");
writeString_P("Nr.\tSoll/90%\tIst l/r\tPWM l/r\tIM l/r\t+-5% l/r\n\n\r");
mSleep(500); // Warnzeit, gleich geht's ab
setLEDs(0);
powerON(); // Muss immer eingeschaltet sein, siehe Doku
startStopwatch2(); // Zeitgeber für die Samplerate
daten_senden(); // Daten Stillstand senden
for (loop=0; loop<2; loop++)
{
if (loop == 1) // Vorbereitung für Rückwärtsfahrt
{
changeDirection(BWD); // 2. Durchgang rückwärts
if (debug) writeString_P("\n\rVorwärts fertig, nun das selbe zurück:\n\n\r");
}
mSleep(500); // besser noch etwas warten, letzte Chance zu hochheben!!!

// Wir beginnen mit der Beschleunigung

moveAtSpeed(speed,speed); // der RP6 soll auf Sollgeschw. beschleunigen
do
{
if (getStopwatch2() >= samplerate) daten_senden(); // Nun daten senden
statusLEDs.LED3=statusLEDs.LED6=((getStopwatch1() & (1<<7)) && 1);
updateStatusLEDs(); // LED blinken ;)
task_RP6System();
} while ((getLeftSpeed() < speed*9/10) && (getRightSpeed() < speed*9/10));

// und gehen bei ca.90% der Sollgeschwindigkeit zur Konstantfahrt über

if (debug) writeString_P("\n\rStart Konstantfahrt\n\n\r");
setLEDs(0);
startStopwatch3(); // Zeitgeber für 1 Sekunde Konstantfahrt starten
if (loop ==1) setStopwatch3(0); // für Rückwärts eine neue Sekunde ;)
while (getStopwatch3() <= konstantfahrt)
{
if (getStopwatch2() >= samplerate) daten_senden(); // wieder Daten senden
if ((getLeftSpeed() > speed*19/20) && (getLeftSpeed() < speed*21/20))
statusLEDs.LED4=1; else statusLEDs.LED4=0;
if ((getRightSpeed() > speed*19/20) && (getRightSpeed() < speed*21/20))
statusLEDs.LED1=1; else statusLEDs.LED1=0;
updateStatusLEDs(); // Anzeige +-5%
task_RP6System();
}

// um dann am Ende bis zum Stillstand zu verzögern

if (debug) writeString_P("\n\rEnde Konstantfahrt\n\n\r");
setLEDs(0);
moveAtSpeed(0,0);
do
{
if (getStopwatch2() >= samplerate) daten_senden(); // Daten senden *gähn*
statusLEDs.LED2=statusLEDs.LED5=((getStopwatch1() & (1<<7)) && 1);
updateStatusLEDs(); // LEDs blinken wieder ;)
task_RP6System();
} while ((getLeftSpeed() > 0) || (getRightSpeed() > 0)); // beide bei 0?
setLEDs(0b111111);
}
setLEDs(0);
powerOFF();
writeString_P("\n\n\rFertig (Testdauer: ");
writeInteger(getStopwatch1(), DEC);
writeString_P("ms)");
while(true) // Endlosschleife mit blinkenden LEDs ;)
{
statusLEDs.LED1=((getStopwatch1() & (1<<7)) && 1);
statusLEDs.LED4=!statusLEDs.LED1;
updateStatusLEDs();
}
return 0;
}

Die Ausgabe im Terminal (blöderweise funktionieren hier die Tabs nicht so wie bei mir):


Terminal cleared!
Regelungtest:

Motor beschleunigt, fãhrt konstant und verzõgert. mic 18.7.07


Nr. Soll/90%Ist l/r PWM l/r IM l/r +-5% l/r


0 75/67 0/0 0/0 0/0 /

1 75/67 0/0 0/0 0/0 /

2 75/67 0/0 37/37 0/0 /

3 75/67 0/0 37/37 0/0 /

4 75/67 0/0 37/37 0/0 /

5 75/67 0/0 37/37 0/1 /

6 75/67 0/0 37/37 0/1 /

7 75/67 0/0 37/37 1/2 /

8 75/67 0/0 37/37 3/2 /

9 75/67 0/0 75/75 5/3 /

10 75/67 0/0 75/75 6/4 /

11 75/67 0/0 75/75 7/5 /

12 75/67 0/0 75/75 9/6 /

13 75/67 0/0 75/75 11/8 /

14 75/67 0/0 75/75 13/10 /

15 75/67 0/0 75/75 14/11 /

16 75/67 0/0 75/75 15/13 /

17 75/67 0/0 75/75 17/14 /

18 75/67 0/0 75/75 19/15 /

19 75/67 0/0 75/75 20/16 /

20 75/67 0/0 75/75 22/18 /

21 75/67 0/0 75/75 23/19 /

22 75/67 0/0 75/75 25/21 /

23 75/67 0/0 75/75 26/23 /

24 75/67 0/0 75/75 27/25 /

25 75/67 0/0 75/75 29/27 /

26 75/67 0/0 75/75 31/29 /

27 75/67 0/0 75/75 32/31 /

28 75/67 0/0 75/75 34/32 /

29 75/67 0/0 75/75 36/34 /

30 75/67 0/0 75/75 38/36 /

31 75/67 40/28 92/98 41/38 /

32 75/67 40/28 92/98 43/38 /

33 75/67 40/28 92/98 46/40 /

34 75/67 40/28 92/98 49/41 /

35 75/67 40/28 92/98 52/43 /

36 75/67 40/28 92/98 54/44 /

37 75/67 40/28 92/98 57/45 /

38 75/67 40/28 92/98 60/47 /

39 75/67 40/28 92/98 63/48 /

40 75/67 40/28 92/98 65/49 /

41 75/67 40/28 92/98 68/51 /

42 75/67 40/28 92/98 71/52 /

43 75/67 40/28 92/98 74/54 /

44 75/67 40/28 92/98 76/56 /

45 75/67 40/28 92/98 78/58 /

46 75/67 40/28 92/98 79/60 /

47 75/67 40/28 92/98 80/61 /

48 75/67 40/28 92/98 81/62 /

49 75/67 40/28 92/98 81/62 /

50 75/67 40/28 92/98 81/63 /

51 75/67 40/28 92/98 81/63 /

52 75/67 40/28 92/98 82/63 /

53 75/67 40/107 92/98 81/63 /

54 75/67 112/107 74/82 81/63 /

55 75/67 112/107 74/82 81/62 /

56 75/67 112/107 74/82 81/61 /

57 75/67 112/107 74/82 79/60 /

58 75/67 112/107 74/82 78/58 /

59 75/67 112/107 74/82 76/57 /

60 75/67 112/107 74/82 74/55 /

61 75/67 112/107 74/82 73/53 /

62 75/67 112/107 74/82 71/51 /

63 75/67 112/107 74/82 69/49 /

64 75/67 112/107 74/82 67/49 /

65 75/67 112/107 74/82 66/48 /

66 75/67 112/107 74/82 65/48 /

67 75/67 112/107 74/82 65/48 /

68 75/67 112/107 74/82 65/48 /

69 75/67 112/107 74/82 66/48 /

70 75/67 112/107 74/82 66/48 /

71 75/67 112/107 74/82 66/48 /

72 75/67 112/107 74/82 65/48 /

73 75/67 112/107 74/82 65/49 /

74 75/67 112/107 74/82 65/50 /

75 75/67 112/107 74/82 65/50 /

76 75/67 109/112 57/64 64/51 /

77 75/67 109/112 57/64 64/51 /

78 75/67 109/112 57/64 63/51 /

79 75/67 109/112 57/64 62/51 /

80 75/67 109/112 57/64 60/50 /

81 75/67 109/112 57/64 59/49 /

82 75/67 109/112 57/64 57/48 /

83 75/67 109/112 57/64 55/46 /

84 75/67 109/112 57/64 53/45 /

85 75/67 109/112 57/64 52/44 /

86 75/67 109/112 57/64 50/42 /

87 75/67 109/112 57/64 49/42 /

88 75/67 109/112 57/64 48/41 /

89 75/67 109/112 57/64 48/41 /

90 75/67 109/112 57/64 47/41 /

91 75/67 109/112 57/64 47/41 /

92 75/67 109/112 57/64 47/41 /

93 75/67 109/112 57/64 47/42 /

94 75/67 109/112 57/64 46/42 /

95 75/67 109/112 57/64 46/42 /

96 75/67 109/112 57/64 46/42 /

97 75/67 109/112 57/64 45/42 /

98 75/67 83/83 57/64 45/42 /

99 75/67 83/83 53/60 45/42 /

100 75/67 83/83 53/60 45/42 /

101 75/67 83/83 53/60 44/42 /

102 75/67 83/83 53/60 43/42 /

103 75/67 83/83 53/60 43/41 /

104 75/67 83/83 53/60 42/41 /

105 75/67 83/83 53/60 41/40 /

106 75/67 83/83 53/60 41/40 /

107 75/67 83/83 53/60 41/40 /

108 75/67 83/83 53/60 40/40 /

109 75/67 83/83 53/60 40/41 /

110 75/67 83/83 53/60 40/41 /

111 75/67 83/83 53/60 40/41 /

112 75/67 83/83 53/60 40/41 /

113 75/67 83/83 53/60 40/41 /

114 75/67 83/83 53/60 40/41 /

115 75/67 83/83 53/60 39/40 /

116 75/67 83/83 53/60 39/40 /

117 75/67 83/83 53/60 39/40 /

118 75/67 83/83 53/60 39/40 /

119 75/67 83/83 53/60 39/40 /

120 75/67 83/83 53/60 39/40 /

121 75/67 71/70 55/62 39/39 /

122 75/67 71/70 55/62 39/39 /

123 75/67 71/70 55/62 39/40 /

124 75/67 71/70 55/62 40/40 /

125 75/67 71/70 55/62 40/40 /

126 75/67 71/70 55/62 40/41 /

127 75/67 71/70 55/62 40/41 /

128 75/67 71/70 55/62 40/41 /

129 75/67 71/70 55/62 40/41 /

130 75/67 71/70 55/62 40/41 /

131 75/67 71/70 55/62 40/41 /

132 75/67 71/70 55/62 40/41 /

133 75/67 71/70 55/62 40/41 /

134 75/67 71/70 55/62 40/40 /

135 75/67 71/70 55/62 40/40 /

136 75/67 71/70 55/62 40/40 /

137 75/67 71/70 55/62 40/40 /

138 75/67 71/70 55/62 40/40 /

139 75/67 71/70 55/62 40/40 /

140 75/67 71/70 55/62 40/40 /

141 75/67 71/70 55/62 40/40 /

142 75/67 71/70 55/62 40/40 /

143 75/67 72/72 55/62 40/40 */*

144 75/67 72/72 56/64 40/40 */*

145 75/67 72/72 56/64 40/39 */*

146 75/67 72/72 56/64 40/40 */*

147 75/67 72/72 56/64 40/40 */*

148 75/67 72/72 56/64 40/41 */*

149 75/67 72/72 56/64 40/41 */*

150 75/67 72/72 56/64 40/41 */*

151 75/67 72/72 56/64 40/41 */*

152 75/67 72/72 56/64 40/41 */*

153 75/67 72/72 56/64 40/41 */*

154 75/67 72/72 56/64 39/41 */*

155 75/67 72/72 56/64 39/41 */*

156 75/67 72/72 56/64 39/41 */*

157 75/67 72/72 56/64 39/41 */*

158 75/67 72/72 56/64 39/41 */*

159 75/67 72/72 56/64 39/41 */*

160 75/67 72/72 56/64 39/41 */*

161 75/67 72/72 56/64 39/41 */*

162 75/67 72/72 56/64 39/41 */*

163 75/67 72/72 56/64 39/40 */*

164 75/67 72/72 56/64 38/40 */*

165 75/67 72/72 56/64 38/40 */*

166 75/67 77/76 55/63 38/40 */*

167 75/67 77/76 55/63 38/40 */*

168 75/67 77/76 55/63 38/40 */*

169 75/67 77/76 55/63 37/39 */*

170 75/67 77/76 55/63 37/39 */*

171 75/67 77/76 55/63 37/39 */*

172 75/67 77/76 55/63 37/39 */*

173 75/67 77/76 55/63 37/39 */*

174 75/67 77/76 55/63 36/38 */*

175 75/67 77/76 55/63 36/38 */*

176 75/67 77/76 55/63 36/38 */*

177 75/67 77/76 55/63 36/38 */*

178 75/67 77/76 55/63 36/38 */*

179 75/67 77/76 55/63 36/38 */*

180 75/67 77/76 55/63 36/38 */*

181 75/67 77/76 55/63 36/38 */*

182 75/67 77/76 55/63 36/38 */*

183 75/67 77/76 55/63 36/37 */*

184 75/67 77/76 55/63 36/37 */*

185 75/67 77/76 55/63 36/37 */*

186 75/67 77/76 55/63 36/37 */*

187 75/67 77/76 55/63 36/37 */*

188 75/67 77/78 54/62 35/37 */*

189 75/67 77/78 54/62 35/37 */*

190 75/67 77/78 54/62 35/36 */*

191 75/67 77/78 54/62 35/36 */*

192 75/67 77/78 54/62 35/36 */*

193 75/67 77/78 54/62 35/36 */*

194 75/67 77/78 54/62 34/36 */*

195 75/67 77/78 54/62 34/36 */*

196 75/67 77/78 54/62 34/36 */*

197 75/67 77/78 54/62 34/36 */*

198 75/67 77/78 54/62 34/36 */*

199 75/67 77/78 54/62 34/36 */*

200 75/67 77/78 54/62 34/36 */*



Hier muste ich kürzen, weil nur 20000 Zeichen pro Beitrag erlaub sind ;)


512 75/67 76/75 58/62 52/39 */*

513 75/67 76/75 58/62 52/39 */*

514 75/67 76/75 58/62 52/39 */*

515 75/67 76/75 58/62 51/39 */*

516 75/67 76/75 58/62 51/39 */*

517 75/67 76/75 58/62 51/39 */*

518 75/67 76/75 58/62 51/39 */*

519 75/67 76/76 58/62 51/39 */*

520 75/67 76/76 58/62 50/39 */*

521 75/67 76/76 58/62 50/39 */*

522 75/67 76/76 58/62 50/39 */*

523 75/67 76/76 58/62 50/39 */*

524 75/67 76/76 58/62 50/38 */*

525 75/67 76/76 58/62 49/38 */*

526 75/67 76/76 58/62 49/38 */*

527 75/67 76/76 58/62 49/38 */*

528 75/67 76/76 58/62 49/38 */*

529 75/67 76/76 58/62 50/38 */*

530 75/67 76/76 58/62 50/38 */*

531 75/67 76/76 58/62 50/38 */*

532 75/67 76/76 58/62 50/38 */*

533 75/67 76/76 58/62 50/38 */*

534 75/67 76/76 58/62 50/38 */*

535 75/67 76/76 58/62 50/38 */*

536 75/67 76/76 58/62 51/38 */*

537 75/67 76/76 58/62 51/37 */*

538 75/67 76/76 58/62 51/37 */*

539 75/67 76/76 58/62 51/37 */*

540 75/67 76/76 58/62 50/37 */*

541 75/67 76/76 58/62 50/37 */*

542 75/67 77/77 57/61 50/37 */*

543 75/67 77/77 57/61 50/36 */*

544 75/67 77/77 57/61 49/36 */*

545 75/67 77/77 57/61 49/36 */*

546 75/67 77/77 57/61 49/36 */*

547 75/67 77/77 57/61 49/36 */*

548 75/67 77/77 57/61 48/36 */*

549 75/67 77/77 57/61 48/35 */*

550 75/67 77/77 57/61 48/35 */*

551 75/67 77/77 57/61 48/35 */*

552 75/67 77/77 57/61 47/35 */*

553 75/67 77/77 57/61 48/35 */*

554 75/67 77/77 57/61 48/35 */*

555 75/67 77/77 57/61 48/35 */*

556 75/67 77/77 57/61 48/35 */*

557 75/67 77/77 57/61 47/35 */*

558 75/67 77/77 57/61 47/35 */*

559 75/67 77/77 57/61 47/35 */*

560 75/67 77/77 57/61 47/35 */*

561 75/67 77/77 57/61 46/35 */*

562 75/67 77/77 57/61 46/35 */*

563 75/67 77/77 57/61 46/35 */*

564 75/67 77/78 56/59 46/34 */*

565 75/67 77/78 56/59 46/34 */*

566 75/67 77/78 56/59 46/34 */*

567 75/67 77/78 56/59 45/34 */*

568 75/67 77/78 56/59 45/33 */*

569 75/67 77/78 56/59 45/33 */*

570 75/67 77/78 56/59 45/33 */*

571 75/67 77/78 56/59 44/33 */*

572 75/67 77/78 56/59 44/33 */*

573 75/67 77/78 56/59 44/33 */*

574 75/67 77/78 56/59 44/32 */*

575 75/67 77/78 56/59 44/32 */*

576 75/67 77/78 56/59 44/32 */*

577 75/67 77/78 56/59 44/32 */*

578 75/67 77/78 56/59 44/32 */*

579 75/67 77/78 56/59 44/32 */*

580 75/67 77/78 56/59 44/32 */*

581 75/67 77/78 56/59 44/32 */*

582 75/67 77/78 56/59 44/32 */*

583 75/67 77/78 56/59 45/32 */*

584 75/67 77/78 56/59 45/32 */*

585 75/67 77/78 56/59 44/32 */*

586 75/67 77/78 56/59 45/32 */*

587 75/67 76/75 55/59 45/31 */*

588 75/67 76/75 55/59 45/31 */*

589 75/67 76/75 55/59 44/31 */*

590 75/67 76/75 55/59 44/31 */*

591 75/67 76/75 55/59 44/31 */*

592 75/67 76/75 55/59 44/31 */*

593 75/67 76/75 55/59 44/31 */*

594 75/67 76/75 55/59 44/31 */*

595 75/67 76/75 55/59 44/32 */*

596 75/67 76/75 55/59 44/32 */*

597 75/67 76/75 55/59 44/32 */*

598 75/67 76/75 55/59 44/32 */*

599 75/67 76/75 55/59 44/32 */*

600 75/67 76/75 55/59 44/32 */*

601 75/67 76/75 55/59 44/32 */*

602 75/67 76/75 55/59 44/32 */*

603 75/67 76/75 55/59 44/32 */*

604 75/67 76/75 55/59 44/32 */*

605 75/67 76/75 55/59 44/32 */*

606 75/67 76/75 55/59 44/32 */*

607 75/67 76/75 55/59 44/32 */*

608 75/67 76/75 55/59 44/32 */*

609 75/67 75/75 18/22 44/32 */*

610 75/67 75/75 18/22 45/32 */*

611 75/67 75/75 18/22 44/32 */*

612 75/67 75/75 18/22 44/31 */*

613 75/67 75/75 18/22 43/31 */*

614 75/67 75/75 18/22 42/30 */*

615 75/67 75/75 18/22 40/28 */*

616 75/67 75/75 18/22 39/28 */*

617 75/67 75/75 18/22 38/26 */*

618 75/67 75/75 18/22 36/25 */*

619 75/67 75/75 18/22 35/24 */*

620 75/67 75/75 18/22 33/23 */*

621 75/67 75/75 18/22 32/22 */*

622 75/67 75/75 18/22 31/21 */*

623 75/67 75/75 18/22 29/20 */*

624 75/67 75/75 18/22 28/19 */*

625 75/67 75/75 18/22 27/18 */*

626 75/67 75/75 18/22 25/17 */*

627 75/67 75/75 18/22 24/17 */*

628 75/67 75/75 18/22 23/16 */*

629 75/67 75/75 18/22 23/16 */*

630 75/67 75/75 18/22 22/16 */*

631 75/67 42/42 18/22 21/15 /

632 75/67 42/42 0/1 21/15 /

633 75/67 42/42 0/1 20/15 /

634 75/67 42/42 0/1 20/15 /

635 75/67 42/42 0/1 19/15 /

636 75/67 42/42 0/1 18/14 /

637 75/67 42/42 0/1 18/14 /

638 75/67 42/42 0/1 17/13 /

639 75/67 42/42 0/1 15/12 /

640 75/67 42/42 0/1 14/11 /

641 75/67 42/42 0/1 13/11 /

642 75/67 42/42 0/1 12/10 /

643 75/67 42/42 0/1 11/9 /

644 75/67 42/42 0/1 10/8 /

645 75/67 42/42 0/1 9/8 /

646 75/67 42/42 0/1 8/7 /

647 75/67 42/42 0/1 7/7 /

648 75/67 42/42 0/1 6/6 /

649 75/67 42/42 0/1 5/6 /

650 75/67 42/42 0/1 5/6 /

651 75/67 42/42 0/1 5/5 /

652 75/67 42/42 0/1 4/5 /

653 75/67 42/42 0/1 3/5 /

654 75/67 2/2 0/0 3/4 /

655 75/67 2/2 0/0 3/4 /

656 75/67 2/2 0/0 2/4 /

657 75/67 2/2 0/0 2/3 /

658 75/67 2/2 0/0 1/3 /

659 75/67 2/2 0/0 1/3 /

660 75/67 2/2 0/0 1/3 /

661 75/67 2/2 0/0 2/2 /

662 75/67 2/2 0/0 1/2 /

663 75/67 2/2 0/0 0/2 /

664 75/67 2/2 0/0 0/2 /

665 75/67 2/2 0/0 2/2 /

666 75/67 2/2 0/0 0/1 /

667 75/67 2/2 0/0 0/1 /

668 75/67 2/2 0/0 2/1 /

669 75/67 2/2 0/0 1/1 /

670 75/67 2/2 0/0 0/1 /

671 75/67 2/2 0/0 0/1 /

672 75/67 2/2 0/0 0/1 /

673 75/67 2/2 0/0 0/1 /

674 75/67 2/2 0/0 0/1 /

675 75/67 2/2 0/0 0/1 /

676 75/67 0/0 0/0 0/1 /




Fertig (Testdauer: 7484ms)

Und noch ein kleines, wirklich unspektakuläres Video dazu:

http://radbruch.roboterbastler.de/rp6/move-test/move-test.mpg
(1,4MB 3,6sek 320X240 unscharfes MPEG)

Dies ist mein erstes, halbwegs vernünftige Programm für den RP6 und zeigt u.a. den Gebrauch der moveAtSpeed()-Funktion und den flexiblen Gebrauch der Stopwatches. O:)

Gruß

mic

stochri
19.07.2007, 06:53
Hallo xTreme,

das Haus vom Nikolaus (http://roboter.net-con.net/asuro/odometrie.html) ist meiner Meinung nach sehr gut als Odometrietest geeignet. Ich habe meinen Rp6 noch nicht, sonst würde ich es einmal ausprobieren ).

Gruss,
stochri

Xtreme
19.07.2007, 07:26
Hi stochri, willkommen im Club ;-)

Danke, das werde ich mal ausprobieren!

Hartgas
19.07.2007, 22:06
Hallo Leute!
Es wäre sehr nett wenn ihr mir ein bischen helfen könntet...
Also ich beschäftige mich seit heute mit der C Programmierung und wollte gerade mal das Programm von Xtreme zum Fahren einer bestimmten Strecke auf meinen Robby übertragen da ich noch einige Schwierigkeiten mit den Radencodern habe.
Also hab ich flux das Programmer´s Notepad geöffnet und wollte ein neues Projekt erstellen. So weit so gut.
Also das Programm fix ausm Forum kopiert (Sorry für das klauen Xtreme, bitte nich steinigen :cheesy: ) und eingefügt und dann die Make All Funktion gewählt...
Hmm tja und siehe da, WinAVR schmeisst mir ne Fehlermeldung raus.
Diese lautet wie folgt: (ausm Output Fenster abgetippt)


> "make.exe" all
make.exe: *** no rule to make target `all´. Stop.

> Process Exit Code: 2
> Time Taken bla bla bla

Das wars!
HILFEEEEEEEE

Viele Grüße

Hartgas

PS Bitte nicht lachen! 8-[

SlyD
19.07.2007, 22:23
Hallo Hartgas,

Du brauchst noch ein Makefile damit das funktioniert! Der Code allein reicht nicht.

Im Beispielverzeichnis zum RP6 liegen schon einige Makefiles die nahezu unverändert einfach mit ins Projektverzeichnis kopiert werden können. Im Makefile muss oben allerdings der richtige Name des Programms eingetragen werden. Sonst findet der Compiler die Programmdatei nicht.

Also - kopiere das "makefile" (heisst genau so) aus dem Beispielverzeichnis "Example_01_LEDs" in Dein neues Projektverzeichnis das Du angelegt hast.
Öffne das Makefile in einem Texteditor (kann man auch ins PN Projekt mit aufnehmen, muss man aber nicht unbedingt. Hauptsache ist, dass es im richtigen Verzeichnis liegt! Für jedes neue Projekt, sollte man ein neues Verzeichnis anlegen.)

Dann oben in Zeile 33 im makefile


TARGET = RP6Base_LEDs

das "RP6Base_LEDs" durch den Namen der Datei ersetzen, in die Du den Code von Xtreme reinkopiert hast! (Achtung: OHNE das ".c" hintendran!)

Beide Dateien abspeichern - das vergisst man leicht!

Dann sollte "make all" eigentlich klappen!

MfG,
SlyD

Hartgas
19.07.2007, 22:44
Ich verneige mich erfürchtig! :cheesy:
Danke nochmals

Grüße

Hartgas

Xtreme
20.07.2007, 06:27
Bei den paar Zeilen kann man wohl nicht mal von "klauen" sprechen ;-)

Hartgas
21.07.2007, 12:22
Hi Fans!
Könnte jemand von euch mir mal sagen wo ich die ganzen Befehle finde die man für den Robby benutzen kann?
Ich würde mir die dann mal raussuchen und dazu schreiben was man genau damit anstellen kann. Falls dann nochmal jemand Infos dazu braucht und genauso Noob ist wie ich würde es demjenigen ne ganze Ecke leichter fallen denk ich mal.

Viele Grüße

Hartgas

Dirk
21.07.2007, 12:35
Hallo Hartgas,

die wesentlichen Funktionen findest du in:
RP6RobotBaseLib.c
RP6I2CMasterTWI.c
RP6I2CSlaveTWI.c
RP6uart.c
RP6ControlLib.c

Die sind da auch gut kommentiert.

Die Definitionen sind in den xyz.h Dateien zu finden.

Gruß Dirk

Hartgas
21.07.2007, 13:20
Besten Dank Dirk.
Ich werd mich mal daran machen.

Gruß

Hartgas

radbruch
21.07.2007, 13:50
Hallo,

ich hab schon eine Textliste der Funktionen in der Doku erstellt:


4.6.1. Mikrocontroller initialisieren
void initRobotBase(void)
void powerON(void)
void powerOFF(void)

4.6.2. UART Funktionen (serielle Schnittstelle)

4.6.2.1. Senden von Daten über die serielle Schnittstelle
void writeChar(char ch)
void writeString(char *string)
void writeString_P(STRING)
void writeStringLength(char *data, uint8_t length, uint8_t offset)
void writeInteger(int16_t number, uint8_t base)

4.6.2.2. Empfangen von Daten über die serielle Schnittstelle
void receiveBytes(uint8_t numberOfBytes)
void waitUntilReceptionComplete(void)
void copyReceivedBytesToBuffer(char *buffer)

4.6.3. Delay Funktionen (Verzögerungen und Zeitsteuerung)
void sleep(uint8_t time)
void mSleep(uint16_t time)

Stopwatch()-Makros
startStopwatchX()
stopStopwatchX()

uint8_t isStopwatchXRunning()
setStopwatchX(uint16_t preset)
getStopwatchX()

4.6.4. Status LEDs und Bumper
void setLEDs(uint8_t leds)

statusLEDs.LEDX
updateStatusLEDs()

uint8_t getBumperLeft(void)
uint8_t getBumperRight(void)

void task_Bumpers(void)
bumper_left
bumper_right
void BUMPERS_setStateChangedHandler(void (*bumperHandler)(void))

4.6.5. ADC auslesen (Batterie-, Motorstrom- und Lichtsensoren)
uint16_t readADC(uint8_t channel)
ADC_BAT --> Batteriespannungs Sensor
ADC_MCURRENT_R --> Motorstromsensor des rechten Motors
ADC_MCURRENT_L --> Motorstromsensor des linken Motors
ADC_LS_L --> Linker Lichtsensor
ADC_LS_R --> Rechter Lichtsensor
ADC_ADC1 --> Freier ADC Kanal für eigene Sensoren
ADC_ADC0 --> Freier ADC Kanal für eigene Sensoren

void task_ADC(void)
ADC_BAT: adcBat
ADC_MCURRENT_L: adcMotorCurrentLeft
ADC_MCURRENT_R: adcMotorCurrentRight
ADC_LS_L: adcLSL
ADC_LS_R: adcLSR
ADC_ADC1: adc0
ADC_ADC0: adc1

4.6.6. ACS – Anti Collision System
void setACSPwrOff(void) --> ACS IR LEDs aus
void setACSPwrLow(void) --> Geringe Reichweite
void setACSPwrMed(void) --> Mittlere Reichweite
void setACSPwrHigh(void) --> Maximale Reichweite

void task_ACS(void)
obstacle_left
obstacle_right
void ACS_setStateChangedHandler(void (*acsHandler)(void))

4.6.7. IRCOMM und RC5 Funktionen
void IRCOMM_sendRC5(uint8_t adr, uint8_t data)
void IRCOMM_setRC5DataReadyHandler(void (*rc5Handler)(RC5data_t))
rc5data.device
rc5data.toggle_bit
rc5data.key_code

4.6.8. Antriebs Funktionen
void task_motionControl(void)

void moveAtSpeed(uint8_t desired_speed_left, uint8_t desired_speed_right)
getDesSpeedLeft()
getDesSpeedRight()
getLeftSpeed()
getRightSpeed()

void changeDirection(uint8_t dir)
FWD - für Vorwärts (FWD ist eine Abkürzung für „Forwards“)
BWD – für Rückwärts (BWD ist eine Abkürzung für „Backwards“)
LEFT – nach links drehen
RIGHT – nach rechts drehen
getDirection()

void move(uint8_t desired_speed, uint8_t dir, uint16_t distance,
uint8_t blocking)
DIST_MM(DISTANCE)
uint8_t isMovementComplete(void)

void stop(void)

void rotate(uint8_t desired_speed, uint8_t dir, uint16_t angle,
uint8_t blocking)

4.6.9. task_RP6System()
void task_RP6System(void)
task_ADC();
task_ACS();
task_bumpers();
task_motionControl();

4.6.10. I²C Bus Funktionen

4.6.10.1. I²C Slave
void I2CTWI_initSlave(uint8_t address)
I2CTWI_readRegisters
I2CTWI_writeRegisters
I2CTWI_genCallCMD
I2CTWI_readBusy
I2CTWI_writeBusy

4.6.10.2. I²C Master
void I2CTWI_transmitByte(uint8_t adr, uint8_t data)
void I2CTWI_transmit2Bytes(uint8_t adr, uint8_t data1, uint8_t data2) ???????????????
void I2CTWI_transmit3Bytes(uint8_t adr, uint8_t data1, uint8_t data2) ???????????????

void I2CTWI_transmitBytes(uint8_t targetAdr, uint8_t *msg, uint8_t numberOfBytes)
I2CTWI_BUFFER_SIZE
I2CTWI_isBusy()

uint8_t I2CTWI_readByte(uint8_t targetAdr)
void I2CTWI_readBytes(uint8_t targetAdr, uint8_t * messageBuffer, uint8_t numberOfBytes);

void task_I2CTWI(void)
void I2CTWI_requestDataFromDevice(uint8_t requestAdr, uint8_t requestID, uint8_t numberOfBytes)
void I2CTWI_getReceivedData(uint8_t *msg, uint8_t msgSize)
void I2CTWI_setRequestedDataReadyHandler(void (*requestedDataReadyHandler)(uint8_t))
void I2CTWI_setTransmissionErrorHandler(void(*transmiss ionErrorHandler)(uint8_t))



mic

ehenkes
21.07.2007, 14:30
Da ein writeFloat(...), z.B. zur Ausgabe der Akkuspannung oder von Messwerten fehlt, hier eine Ergänzung:


void float2string(float value, int decimal, char* valuestring)
{
int neg = 0;
char tempstr[20];
int i = 0;
int j = 0;
int c;
long int val1, val2;
char* tempstring;
tempstring = valuestring;
if (value < 0){ neg = 1; value = -value; }
for (j=0; j < decimal; j++) {value = value * 10;}
val1 = (value * 2);
val2 = (val1 / 2) + (val1 % 2);
while (val2 !=0){
if ((decimal > 0) && (i == decimal)){
tempstr[i] = (char)(0x2E);
i++;
}
else{
c = (val2 % 10);
tempstr[i] = (char) (c + 0x30);
val2 = val2 / 10;
i++;
}
}
if (neg){
*tempstring = '-';
tempstring++;
}
i--;
for (;i > -1;i--){
*tempstring = tempstr[i];
tempstring++;
}
*tempstring = '\0';
}

float Ubatt = 10.21; // Beispiel
char text[6];
float2string(Ubatt,2,text); // 2 Dezimalstellen
writeString(text); // o.ä. z.B. auf das Display

Dirk
21.07.2007, 20:02
@radbruch:
Hallo mic,

zwei Fragen zu deiner Doku:
1. Warum fängt die Doku bei 4.6.1 an oder was kommt davor?
2. Warum hast du bei diesen Funktionen ...
void I2CTWI_transmit2Bytes(uint8_t adr, uint8_t data1, uint8_t data2) ???????????????
... und ...
void I2CTWI_transmit3Bytes(uint8_t adr, uint8_t data1, uint8_t data2) ???????????????
... die vielen ??? drangehängt?

Gruß Dirk

radbruch
21.07.2007, 20:36
Hallo Dirk

zu 1.: Das Kapitel 4.6 in der Dokumentation beschreibt die Funktionen der Library. Die Nummern sind der Bezug zur Doku, die wollte ich für meine geplante HTML-Kurzreferenz nutzen. Im Moment zeigen sie nur an, wo man die jeweilige Funktion in der Doku findet.

zu 2.: Weil bei I2CTWI_transmit3Bytes() ein Parameter fehlte. Meine Liste habe ich auf Basis der vorläufigen Test-Doku erstellt, dieser Fehler dürfte in der aktuellen Version (http://www.arexx.com/rp6/downloads/RP6_manual_DE_20070717.zip) (vom 17.7.07) beseitigt sein.

Meine Liste ist ja noch keine echte Doku, es soll mal eine werden. Ich habe sie erstellt um mir selbst einen Überblick über die Funktionien zu verschaffen. Dies sind auch nur die in der Doku beschriebenen Funktionen. Es gibt noch unzählige andere, die super (aber eben in englisch) erklärt, in den einzelnen Dateien der Library enthalten sind. Diese sollte man als RP6-Anfänger aber besser nicht verwenden, weil sie auf die Basics, gebildet durch das Task-System, der Funktionen zugreifen. Da sollte man dann schon genau wissen, was man tut.

Bei dieser Gelegenheit ziehe ich mal den Hut vor Dominik (aka SlyD) der das alles entwickelt und geschrieben hat. https://www.roboternetz.de/phpBB2/images/smiles/eusa_clap.gif

Gruß

mic

Dirk
21.07.2007, 21:06
Hallo mic,


Weil bei I2CTWI_transmit3Bytes() ein Parameter fehlte.

... der fehlt in meiner Lib nicht. Die Lib ist ok!

Gruß Dirk

Skaki
22.07.2007, 10:20
Hallo Leute, ich bin neu hier (sowohl hier im Netz, als auch in Bezug auf Roboter).
Seit einer Woche bin ich nun stolzer Besitzer eines RP6. Die Beispielprogramme habe ich (teilweise) getestet bzw. von manchen nur den Quellcode angesehen und ich muss wirklich sagen, Respekt! Sehr gut kommentiert!!

Für meine ersten Gehversuche suche ich eine Möglichkeit, Daten mit dem PC auszutauschen. Dazu schau ich mir grade die UART-Schnittstelle an. Im Zusammenhang mit dem RP6Loader funktioniert alles einwandfrei.

Nun möchte ich Daten per UART über ein anderes Programm austauschen. (Und dabei das USB-Interface mit der virtuellen COM-Schnittstelle verwenden). (Arbeite unter WinXP)

Für einen ersten Test hab ich mal das Hyperterminal hergenommen und eine Verbindung zur (bei mir) COM8 konfiguriert (Parameter 9600,8,n,1,keine)
Wenn ich nun eine Verbindung per Hyperterminal zum Robby herstell, dann sieht es so aus, als wenn die Gesammte Spannung zusammen bricht . Die Leds gehen aus bzw. glimmen nur noch leicht. Es werden keine Daten zum Terminal übertragen. (Im Robby läuft das SerialInterface_01)

Für den Test hab ich das RP6Loader beendet, damit nicht beide Applikationen gleichzeitig auf der Seriellen "rum machen".

Trenne ich die Verbindung im Hyperterminal, dann scheint dies beim Robby ein Reset auszulösen bzw. der Controller arbeitet dann normal,
die LEDs leuchten wieder.

Nun die Frage: Bug oder Feature ?
Verwendet der RP6Loader die UART in besonderer Weise oder muss ich andere Parameter verwenden ?
Wäre schön wenn mir da jemand helfen könnte.

Viele Grüße
Skaki

SlyD
22.07.2007, 11:17
Hallo Skaki,

ich mache normalerweise nicht viel mit Hyperterminal (gefällt mir nicht so ;) )
aber ich habe das gerade selbst mal ausprobiert - anscheinend setzt Hyper Terminal die Leitung RTS auf low --> das hält den MEGA32 im Reset Modus!
Keine Ahnung wie man das in Hyperterminal umstellen kann.

RTS ist nämlich mit dem Reset Pin des Mikrocontrollers verbunden. So kann der Bootloader mit der PC Software besser gesteuert werden.


Probier doch mal HTerm:
http://www.der-hammer.info/terminal/index.htm
aus.
Das kann auch direkt die Leitung RTS kontrollieren (gibt unten einen Button) und man kann damit den MEGA32 resetten.

Wie Du HTerm einstellen musst, siehst Du auf dem Screenshot den ich angefügt habe.
9600 Baud werden so nicht klappen, der RP6 verwendet normalerweise 38400 Baud.

Das Programm auf dem Bot kann man in HTerm starten, indem man nachdem der Bootloader "[READY]" ausgegeben hat einfach ein 's' sendet.

Das lässt sich so natürlich auch mit einer eigenen Software steuern...

MfG,
SlyD

ehenkes
22.07.2007, 11:26
Wenn man ein völlig eigenes Terminal auf dem PC entwickeln will/muss, dann ist z.B. dies ein guter Ausgangspunkt:
http://www.codeproject.com/system/serial.asp
Damit ist man völlig frei in der Entwicklung seiner Schnittstelle zum Bot.
Der Standard nach dem Compilieren/Linken sieht so aus:
http://www.henkessoft.de/Roboter/Bilder/SerialMFC.jpg
Ein Dialog zum Einstellen der Verbindung ist auch bereits dabei:
http://www.henkessoft.de/Roboter/Bilder/SerialMFC_Einstellungen.jpg

22.07.2007, 11:46
Hallo SlyD,

herzlichen Dank für die schnelle Hilfe!!
Das Hammer-Terminal ist ja wirklich der Hammer. Damit funktionierts auch einwandfrei!
Das Hyperterm hatte ich nur für einen ersten "Kontaktversuch" verwendet. (Leider kann man den RTS-Pin da nicht konfigurieren)
Danke deiner Hilfe weiss ich nun, worauf ich beim Schnittstellenprogrammieren achten muss. Ich hab gott sei dank noch eine Schnittstellen-Library, welches die RS232-Programmierung unter XP etwas einfacher macht. Da kann ich auch das RTS direkt steuern.

Damit steht einer ersten Applikation nichts mehr im Wege. Nochmals vielen Dank und noch ein schönes Wochenende!

Viele Grüße
Skaki

Skaki
22.07.2007, 11:57
Jetzt bin ich als Newbee doch glatt in die Login-Falle getappt (Gast), sorry!

Hallo ehenkes,

danke für die Info. Vielleicht ist die OpenSource-Lib sogar noch besser geeignet, als die was ich auf der Platte rum liegen hab. Ich schaus mir auf jeden Fall mal an.

Viele Grüße
Skaki

BacaBej
03.08.2007, 16:44
Aaaaalsooo.... Ich hab heute den Robby RP6 bekommen und auch schon ein paar Beispielprogramm geuploadet. Nun funktioniert die MAKE ALL funktion nicht. Auch die Beispielprogramme ( nicht die .hex dateien ) kann ich nicht compilieren. Ich habe auch Target = (dateiname) gemacht.
Vielleicht habe ich auch das mit dem Projektverzeichnis falsch verstanden. Wenn ich PN2 öffne ist ja links mein Projekt. Da ist dann z.b. das Beispielprogramm und darunter das MAKEFILE. Aber nix geht. Da kommt immer der Fehlercode: 1 und ne Meldung das der Befehl MAKE falsch geschrieben ist oder so und es den nicht gibt. Hab nicht mehr die genauen Worte im Kopf^^... Hab ich irgendwas falsch gemacht ?? ? Gibt es eine andere möglichkeit das in ne .hex datei zu compilieren ?

Ansonsten hoffe ich auf eine schnelle Antwort... Und ich will noch was loswerden: Geiles Forum... hier kann man sich Totlesen^^...

P.S. Ich hab net so viel ahnung von ,C'... ( ok.-> KEINE ) aber ich arbeite mich da jetzt mal durch und die ganzen Fachbegriffe, wie z.b die namen von den anschlüssen und wat weiß ich sagen mir im moment gar nichts...
Bitte auf Kindergartenniveau antworten 8-[ 8-[

Mfg

BacaBej O:) O:)

SlyD
03.08.2007, 23:05
Hallo BacaBej,

erstmal willkommen im Forum :)


Was genau willst Du denn machen?
Ein eigenes Projekt anlegen oder die vorhandenen Beispielprogramme abändern?

Im letzteren Fall:


Ich habe auch Target = (dateiname) gemacht.


Da brauchst Du an den Makefiles der fertigen Beispielprogramme nichts zu ändern, das sollte alles so bleiben wie es ist.
Bei einem eigenen Projekt musst Du beachten das "Dateiname" nicht die Dateiendung - also das ".c" hintendran - enthält.
Also wenn Dein Programm "MeinProgramm.c" heisst, muss die Zeile also "Target = MeinProgramm" lauten!


Hast Du die Datei "RP6BaseExamples.ppg" in PN2 geöffnet? Dann solltest Du ja wie in der Anleitung abgebildet alle Beispielprogramme in der Liste links sehen. Du musst dann eine der C Dateien (z.b. RP6Base_LEDs.c) doppelt anklicken - es öffnet sich das Sourcecode Fenster.

Wenn der Editor mit dieser Datei geöffnet und ausgewählt ist, kannst Du Make All über das Menü aufrufen.
Dann sollte das eigentlich klappen.
Bei der Instalation von WinAVR hat es aber sonst keine Probleme gegeben, richtig?

Mach mal bitte folgendes:
Klick auf "Start-->Ausführen"
und dann "cmd" eingeben und Enter drücken!

Es öffnet sich ein DOS Fenster.

Gib hier mal
"avr-gcc --version"
ein.

Es sollte


avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


erscheinen!
Klappt das?


MfG,
SlyD

PS:
Bei Fehlermeldungen:
Bitte immer die ganzen Ausgaben unten im PN2 markieren, kopieren (STRG+C) und hier im Forum einfügen (STRG+V)

z.B. so


> "make.exe" all

> Failed to create process: Der Verzeichnisname ist ungültig.

> Process Exit Code: 0
> Time Taken: 00:00



Dann kann man meistens besser sehen um welche Fehlermeldung es genau geht!

BacaBej
04.08.2007, 09:49
Erstmal Danke für die Antwort...

1. Das mit dem avr-gcc --version klappt.

2. Ich hab jetzt nochmal ein Beispielprogramm compiliert und jetzt geht das. Gestern funktionierte das komischerweise nicht... Aber hauptsache das geht jetzt

Mach ich nun ein neues Projekt, mach da das makefile von exampleLED1... (das erste beispiel jedenfalls) und ein neues ,,C-dokument''... wie das auch immer heißen soll. Das nenn ich dann 123 und in dem Makefile mach ich dann auch TARGET = 123 (ohne.c) . Mach in nun MAKE ALL kommt die Fehlermeldung das die angegebene Datei nicht gefunden wurde... Das ist mir aber jetzt auch egal.... Ich finde das eh was komplizierter immer neues projekt öffnen, makefile rein, neues c,,dokument''....

Ich veränder jetzt einfach immer ein Beispielprogramm. Geht so am schnellsten...

Und ich wollte noch ma fragen wie lange ich gebraucht hattet, bis ihr C einigermaßen verstanden habt ? Mir kommt das sehr schwer vor.... Habs auch erst 1 Tag xD


Das war's dann schon

Mfg

BacaBej

ehenkes
04.08.2007, 11:07
Und ich wollte noch ma fragen wie lange ich gebraucht hattet, bis ihr C einigermaßen verstanden habt ? Mir kommt das sehr schwer vor.... Habs auch erst 1 TagDas braucht einige Monate je nach Übung.
Hier noch ein Link zu C, der Dir vielleicht hilft:
http://www.pronix.de/pronix-607.html

BacaBej (Gast)
04.08.2007, 14:09
Moin Moin,

Folgendes Problem: Aus der Anleitung will ich das compilieren:


uint16_t tolleVariable = 16447;
if(tolleVariable < 16000) // Wenn tolleVariable < 16000
{ // Dann:
writeString("tolleVariable ist kleiner als 16000!\n");
}
else // Sonst:
{
writeString("tolleVariable ist größer oder gleich 16000!\n");
}

Nun kommt diese Fehlermeldung:


Compiling: RP6Base_SerialInterface_01.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Base_SerialInterface_01.lst -I../../RP6lib -I../../RP6lib/RP6base -I../../RP6lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Base_SerialInterface_01.o.d RP6Base_SerialInterface_01.c -o RP6Base_SerialInterface_01.o
RP6Base_SerialInterface_01.c:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'tolleVariable'
RP6Base_SerialInterface_01.c:2: error: expected identifier or '(' before 'if'
RP6Base_SerialInterface_01.c:6: error: expected identifier or '(' before 'else'
RP6Base_SerialInterface_01.c:9:2: warning: no newline at end of file
make: *** [RP6Base_SerialInterface_01.o] Error 1

> Process Exit Code: 2
> Time Taken: 00:00


Das müsste ja eigentlich klappen...

Ich denke mal der weiß net was uint8_t und so ist. Unter Tools-> keywords steht das aber drin


Mfg

BacaBej

BacaBej
04.08.2007, 14:33
Moin,

LOL

Bin wohl in nen Anfängerfehler getappt....

Hab den Fehler selber gefunden


#include "RP6RobotBaseLib.h"
int main(void)

fehlte..... *peinlich**peinlich*

MfG

BacaBej

BacaBej
16.08.2007, 20:37
Folgendes Problem: Ich hab nen Code geschrieben( seeeeeehr einfachen), wo der Roboter einfach nur woanders hinfährt, wenn ein bumper gedrückt wird... Hab den RP6 noch nicht so lange....
Wird der Bumper gedrückt, dreht sich der Roboter im Kreis und fährt nicht weiter...

Nun zum Code: ( wie gesagt,.... anfängercode, und dann noch ein Fehler...)


#include "RP6RobotBaseLib.h"


void bumpersStateChanged(void)
{
if(bumper_left)

{setLEDs(0b111111);
move(50, BWD, DIST_MM(100), true);
setLEDs(0b001111);
rotate(90, RIGHT, 70, true);
setLEDs(0b001001);

}




else if(bumper_right)

{setLEDs(0b111111);
move(50, BWD, DIST_MM(100), true);
setLEDs(0b111001);
rotate(90, LEFT, 70, true);
setLEDs(0b001001);

}

}


int main(void)
{

initRobotBase();

BUMPERS_setStateChangedHandler(bumpersStateChanged );

powerON();

setLEDs(0b001001);



while(true)
{

moveAtSpeed(100,100);





task_RP6System();
}

return 0;}


Gibts ne andere Möglichkeit, oder muss moveAtSpeed in der schleife stehn ? und kann man die If schleifen auch erst nach dem PowerOn schreiben?


MfG

BacaBej

radbruch
16.08.2007, 20:51
Hallo

Keine Sorge wegen deines Codes, jeder hier hat mal klein angefangen. 8-[

Zu deinem Problem:
Möglicherweise verhindert die blockierende Ausführung von Move und Rotate, dass die Bumber neu eingelesen werden können. Wenn man das Task-System verwendet, sollte man blockierende Funktionen vermeiden.

Anstelle des "true" verwendet man dann besser diese Funktion:

uint8_t isMovementComplete(void)

und der Code würde dann etwa so aussehen:


...
if(bumper_left)

{setLEDs(0b111111);
move(50, BWD, DIST_MM(100), false);
while (!isMovementComplete()) task_RP6System();
setLEDs(0b001111);
rotate(90, RIGHT, 70, false);
while (!isMovementComplete()) task_RP6System();
setLEDs(0b001001);

}
...


So ist gewährleistet, dass alle Task-Funktionen weiterhin ausgeführt werden.

Gruß

mic

Carlos31
16.08.2007, 21:58
Hallo :
Nicht verzweifeln :-), ich hab mein rp6 schon 2 wochen und hab noch kein progr. zum standen gebracht , bin aber am kämpfen , und am rumprobieren :-) ,
Ich brauche noch ein experimentier steckboard , und ein paar elektronische komponente , weisst jemand wo ich so was kriege in österreich zum bestellen ?, bei reichelt muss ich mindestens 150 euro bestellen als export kunde , und conrad hat nicht was ich will , danke in voraus

gruss Carlos

BacaBej
17.08.2007, 15:36
Tach,

Erstma danke für die Antworten...

In der Anleitung steht doch ein Programm wo auch das mit dem move und rotate drin steht oder ?? ? Kann mich auch irren... Und in der Anleitung steht auch nichts davon, das dat blockieren könnte.... Hätte man ja schreiben können... Oder ich hab das überlesen..

Jedenfalls versteh ich nicht ganz warum das blockiert...(ich will alles ganz genau wissen um das besser zu verstehn^^) Es müsste doch erst die Move Funktion ausgeführt werden UND erst dann das rotate... Und während dem Move und Rotate müssen die Bumber ja auch net ausgelesen werden...oder ? hehe Fragen über Fragen.....


Mfg

BacaBej

radbruch
17.08.2007, 17:08
Hallo

Zitat aus Kapitel 4.6.9 (Seite 101) der Anleitung:

Der letzte Parameter der Funktion, „blocking“ ist eine kleine Besonderheit, die wir etwas
genauer erklären müssen.
Die Funktion setzt normalerweise nur ein paar Variablen und es würde dann sofort mit
dem normalen Programmablauf weitergemacht. Die Fahrt würde „im Hintergrund“ automatisch
von der motionControl Funktion gesteuert. Das ist sinnvoll, wenn der Roboter
nebenbei noch andere Dinge tun muss, wie z.B. auf Hindernisse reagieren.

Das Task-System des RP6 verwaltet im Hintergrund mit einer Mischung aus Polling (regelmässiges Aufrufen aus dem Hauptprogramm) und Interupts (unterbrechen des Hauptprogramms) die Funktionen des Roboters. Mit den Funktionen der Bibliothek steuert man quasi nicht selbst den Roboter, man übergibt dem Task-System den Befehl und dieses organisiert dann das Zusammenspiel der einzelnen Funktionen. Dabei unterscheiden sich zwei Möglichkeiten:

- Es muss schnell auf ein Ereigniss reagieren (z.B. auf einen Feldwechsel der Odometry-Sensoren) oder periodisch immer wiederkehrend auf ein Ereigniss reagieren (z.B. Stopwatches oder Rampen bei setMotorPower). Dann verwendet das Task-System einen Interrupt und unterbricht für seine Aufgaben das Hauptprogramm (um z.B. den Impulszähler des Antriebs oder die Werte der Stopuhren zu akualisieren). Diese Unterbrechungen sind sehr kurz, weil sie nur aus ein paar Befehlen bestehen und nur das nötigste erledigen. Das Hauptprogramm wird dadurch fast nicht gebremst. (Tiefer mag ich an dieser Stelle nicht auf die Interupts eingehen)

- Es muss regelmässig umfangreiche Berechnungen anstellen (Fahrwege überwachen, Geschwindigkeiten regeln, IR und ACS-Signale auswerten..), die analogen Eingänge einlesen (Bumper, LDRs, Motorströme...) und andere, weniger zeitkritische Dinge erledigen. Es reicht vollkommen, wenn man dazu das Hauptprogramm an einer Stelle unterbricht und diese Tätigkeiten durch den Aufruf der jeweiligen Task-Funktion ausführen läßt. Im Gegensatz zum Interrupt, der ja für das Hauptprogramm zu einem willkührlichen Zeitpunkt auftreten kann, spricht man hier vom Polling. Allerdings werden nicht alle Aktionen bei nur einem Aufruf erledigt, es dauert einige Aufrufe, bis alle arbeiten erledigt sind und die Abarbeitung erneut startet. In der Anleitung steht dazu:


Ständig aus dem Hauptprogramm
aufrufen heisst hier nichts anderes, als dass man diese Funktion in der
Hauptschleife des Programms bei jedem Schleifendurchlauf einmal aufrufen muss. Es
reicht, wenn die Funktion alle 10 bis 50 Millisekunden einmal aufgerufen wird. Besser
ist es allerdings, die Funktion noch sehr viel öfter aufzurufen. Es schadet nicht, wenn
man die Funktion noch schneller aufruft, denn das Timing wird von einem der Hardwaretimer
gesteuert. Daher ist es auch egal ob man die Funktion in gleichbleibenden
Intervallen aufruft, oder ob man mal 1ms und mal 10ms zwischen den einzelnen Aufrufen
benötigt. Es kostet auch nur unwesentlich mehr Rechenzeit, die Funktion oft
aufzurufen. Sie wird nur komplett ausgeführt, wenn auch etwas zu tun ist.

"Blockierend" bedeutet nun, das Hauptprogramm pollt nicht (oder zu langsam). Ursachen sind z.B. zu lange Schleifen ohne Task-Aufruf, mSleep()s oder das Senden von vielen Zeichen. Und beim blockierenden Move() werden alle Tasks außer dem motionControll blockiert.

Nach soviel Text und Erklärungen bleibt mir leider nur noch zu sagen, dass dies alles nichts mit der Fehlfunktion deines Programms zu tun hat. Das ist mir zwar peinlich, aber es fehlt wohl nur der setMotorDir(FWD,FWD); vor dem moveAtSpeed(100,100); deshalb drehen die Motoren mit den Richtungen weiter, die sie beim Rotate() hatten.

Gruß

mic

BacaBej
17.08.2007, 20:56
Abend,

Danke Danke.... Jetzt hab ich das auch kapiert warum das net funzt.... In der schleife steht zwat moveAtSpeed(100,100) aber net in welche richtung... und da die letzte Richtung das Rotieren ist, dreht der halt weiter... *Peinlicher Fehler*. Aber naja.. Ich werde mich schon noch verbessern. Auf jedenfall nochmal Danke für die schnelle Antwort.

MfG

BacaBej

SlyD
17.08.2007, 21:18
Hallo,

genau genommen gehört das moveAtSpeed() nicht mit in die Hauptschleife rein. Das braucht man nur dann aufzurufen, wenn sich die Geschwindigkeit ändern soll.
Genauso ist es mit changeDirection()!

setMotorDir sollte man nur dann verwenden, wenn man das task System NICHT benutzt ;)
Also bitte nicht mit der Funktion beim ASURO verwechseln - das funktioniert beim RP6 ein wenig anders.
Hier sollte man eigentlich immer changeDirection verwenden.

MfG,
SlyD

andieh
09.01.2009, 18:02
Hallo!

Ich bin auch gerade dabei, den Robo über die serielle zu steuern, bekomme es aber nicht wirklich hin.


aber ich habe das gerade selbst mal ausprobiert - anscheinend setzt Hyper Terminal die Leitung RTS auf low --> das hält den MEGA32 im Reset Modus!

ich habe die RX und TX Leitungen mit meinem PC verbunden und eben noch GND. Leider bekomme ich keine Ausgabe mit Hyperterminal hin (Keine Angst, beides läuft mit 5V). Ist es grundsätzlich nicht möglich, mit Hyperterminal eine verbindung hinzubekommen? Ich kann leider kein anderes Programm benutzen, da die Software in OpenWRT auf einem fonera router läuft.

Ziel soll es ja sein, die Verbindung über ein eigenes Programm zu steuern. Hat jemand von euch schon mal so was gemacht? Also in C direkt auf die serielle Konsole zugegriffen? Man muss das Rad ja nicht mehrmals erfinden.

Vielen Dank für eure Antworten!

MfG
andieh

kevin123
19.04.2009, 15:08
Ich habe mier einen RP6 gekauft und des program wo dabei war kapier ich net wie man des insterliert köntet ihr mier einen link schiken wo man das Program umsonst Downlouden kan ?
danke im foraus

SlyD
19.04.2009, 15:34
Hast Du schon die ANLEITUNG gelesen?
Da ist das alles ausführlich beschrieben.

Das steht übrigens ganz vorne folgender Link drin:
http://www.arexx.com/rp6

;)

MfG,
SlyD

kevin123
19.04.2009, 16:01
Danke SlyD danke

kevin123
19.04.2009, 16:32
Und was mus ich mier von der softwer runderladen ?

SlyD
19.04.2009, 16:36
Erstmal die DOKU LESEN!

http://www.arexx.com/rp6/html/de/docs.htm

RP6Loader, Beispielprogramme und WinAVR