PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 Linienfolger



darksky
23.02.2008, 18:30
Hallo zusammmen
Ich möchte dass mein RP6 Linien nachfahren kann. Ich habe auch schon verschiedene Themen darüber gelesen. Aber ich weiss nicht so recht wlche Sensoren ich verwenden soll und wo ich diese am besten montieren soll.
=D>
Anschliessen kann ich die Sensoren ja wahrscheinlich an der Erweiterungsplatine, oder?
Danke im vorraus
darksky
O:)

Dirk
23.02.2008, 18:44
Es gäbe für das "Linienfolgen" beim RP6 diese Lösungen:

1. Anschluß der Sensoren (z.B. CNY70) an die Control M32 (6 Sensoren an die ADC-Eingänge oder Digital-Eingänge)
2. Anschluß der Sensoren über an einen I2C-Portexpander den I2C-Bus des RP6

Gruß Dirk

radbruch
23.02.2008, 18:46
Hallo

Ich hatte es mal mit einer Kamera versucht:

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=308110#308110

Aber einfacher wäre es wohl mit normalen Sensoren an den Pins ADC0 und ADC1 der RP6-Basis. Möglicherweise kann man auch die vorhandenen LDRs nutzen. Licht-Boden-Spiegel-LDR. (Das muss ich gleich mal testen, habe noch reichlich Spiegelfliese über...)

Gruß

mic

-andi_007-
23.02.2008, 18:49
Da hätte ich auch mal ne frage dazu:

Kann mann mit diesen teil eine Linie am boden verfolgen?

Das schlisse ich beim ADC eingang an oder?, und dass müsste auch ohne erweiterungsmodul beim rp6 klappen oder!!!

Da die artikelnummer beim conrad: 190789-LN

Link: www.conrad.at

radbruch
23.02.2008, 19:16
Das gesuchte Produkt ist nicht in unserer Online-Datenbank gelistet.
Artikelbeschreibung? Artikelname?

Im Prinzip funktionieren alle lichtempfindlichen Bauteile. Gute Quellen sind alte Videorekorder, Floppylaufwerke oder CD-Roms. Teilweise sind dort auch Gabellichtschranken verbaut (Sendediode und Empfänger, teilweise mit Vorwiderständen, in U-förmigen Gehäuse) die man ausschlachten kann.

Gruß

mic

radbruch
23.02.2008, 21:28
Nochmal hallo

Ich muss leider gestehen, ich habe den eigentlichen RP6 bisher sträflich vernachlässigt. Dass er ein kompletter Roboter ist habe ich wegen meiner ganzen Spielereien völlig ingnoriert, ich habe in nur als Kontroller und Stromquelle für meine Experimente missbraucht. Dabei hat er selbst schon erstaunlich viel Potential.

Die Idee mit den LDRs habe ich nun angetestet und bin begeistert:

http://radbruch.bplaced.net/rp6/liniensuche3/linie_erkennen_mit_ldr1_klein.jpg (http://radbruch.bplaced.net/rp6/liniensuche3/linie_erkennen_mit_ldr1.jpg) http://radbruch.bplaced.net/rp6/liniensuche3/linie_erkennen_mit_ldr2_klein.jpg (http://radbruch.bplaced.net/rp6/liniensuche3/linie_erkennen_mit_ldr2.jpg) http://radbruch.bplaced.net/rp6/liniensuche3/linie_erkennen_mit_ldr3_klein.jpg (http://radbruch.bplaced.net/rp6/liniensuche3/linie_erkennen_mit_ldr3.jpg)

Eine Lampe (drei helle LEDs) und ein Stück Spiegel (funktioniert auch mit einem Blatt Papier!) genügen um einen schwarzen Strich zu erkennen. Auch ohne seitliche Abdeckungen registrieren die Lichtsensoren des RP6 über den Spiegel die Helligkeitsunterschiede unter ihnen die durch unterschiedliche Reflexion des Untergrunds verursacht werden:

http://i.ytimg.com/vi/694Q7X_PB4Q/1.jpg (http://www.youtube.com/watch?v=694Q7X_PB4Q)
http://www.youtube.com/watch?v=694Q7X_PB4Q

Durch Verschieben der Lichtquelle (gegen Ende des Filmchens) kann man das Ganze kalibrieren. Der "Strich" ist übrigens das schon bekannte USB-Kabel ;)

Vielleicht inspiriert es euch zu eigenen Ideen. Ich bin im Moment voll mit anderen Projekten beschäftigt und mag mich eher ungern wieder mit einem Linienfolger befassen.

Gruß

mic


// Einfaches Linienfolgen mit RP6-Sensoren (Test der Funktion) 23.2.2008 mic

#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
while(1)
{
writeInteger(readADC(ADC_LS_L), 10);
writeString_P(" - ");
writeInteger(readADC(ADC_LS_R), 10);
writeString_P("\n\r");
if (readADC(ADC_LS_L) > readADC(ADC_LS_R))
setLEDs(4); else setLEDs(32);
mSleep(500);
}
return(0);
}

thietho
24.02.2008, 18:48
Cool,
das muss ich mal Testen.

gruß thietho

robob
01.03.2008, 15:37
echt geil! bei mir funktionirts auch!

radbruch
06.03.2008, 00:17
Hallo

Fortuna meint es grad ziemlich gut mit mir und hat mir einen defekten Scanner zugespielt. Die kleine Leuchstoffröhre lief im Scanner mit knapp 10V, leuchtet aber mit der Akkuspannung des RP6 auch recht hell und vor allem extrem geichmässig:

http://i.ytimg.com/vi/vStz89FPpvg/2.jpg (http://www.youtube.com/watch?v=vStz89FPpvg) http://i.ytimg.com/vi/IRGwc-c9afM/1.jpg (http://www.youtube.com/watch?v=IRGwc-c9afM)
http://www.youtube.com/watch?v=vStz89FPpvg
http://www.youtube.com/watch?v=IRGwc-c9afM

Die hier verwendeten Spiegel taugen noch nicht wirklich, ein Blatt Papier ist deutlich besser (Werte bis 700!). Die kleine Box vorne rechts enthält das Hochspannungsteil für die Lampe. Jetzt brauch ich nur noch etwas mehr KI um die Teststrecke zu schaffen.

Gruß

mic

radbruch
07.03.2008, 01:09
Hallo

Echt krass was die Lampe bringt. Das Programm ist immer noch minimal, aber das Ergebniss ist trotzdem prima:

http://s3.ytimg.com/vi/r2VC2YF7ycM/2.jpg (http://www.youtube.com/watch?v=r2VC2YF7ycM)
http://www.youtube.com/watch?v=r2VC2YF7ycM


// Einfaches Linienfolgen mit RP6-Sensoren (Test der Funktion 2) 6.3.2008 mic

#include "RP6RobotBaseLib.h"

// Achtung! Die PWM-Werte werden hier OHNE Rampe verändert!
void setMotorPWM(uint8_t power_links, uint8_t power_rechts)
{
extern uint8_t mleft_ptmp, mright_ptmp;

if(power_links > 210) power_links = 210;
if(power_rechts > 210) power_rechts = 210;
mleft_power=mleft_ptmp=power_links;
mright_power=mright_ptmp=power_rechts;

OCR1BL = power_links;
OCR1AL = power_rechts;

if(power_links || power_rechts)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
else
TCCR1A = 0;
}
int main(void)
{
initRobotBase();
while(1)
{
writeInteger(readADC(ADC_LS_L), 10);
writeString_P(" - ");
writeInteger(readADC(ADC_LS_R), 10);
writeString_P("\n\r");
if (readADC(ADC_LS_L) > readADC(ADC_LS_R))
{
setLEDs(4);
setMotorPWM(100,50);
}
else
{
setLEDs(32);
setMotorPWM(50,100);
}
mSleep(100);
}
return(0);
}

Der "Reflektor" ist ein Blatt Papier, die Werte auf den Fliesen sind über 800!

Gruß

mic

ibo
19.03.2008, 21:54
Es hat sogar bei mir im Bett geklappt. Ich hab nur eine dünne schwarze Schnur auf die unebene Bettdecke gelegt und los gings mit der Linienverfolgung.

Ihr seit echt zum Loben!


DANKE

_AJ_
01.05.2008, 09:23
Moin,

ich hab mich auch mal mit einem Linienfolger befasst und 2 CNY70 an meine M32 angeschlossen bekommen. So weit funktioniert alles, nur leider sind die mitgelieferten Fahrfunktionen des RP6 viel zu träge, um einigermaßen vernünftig zu reagieren.

Nun würde ich gerne wissen, ob es schon ein paar ausgereifte und erprobte Modifizierungen der Libraries gibt, mit denen der RP6 ein bisschen schneller wieselt. Ich habe das Beispielprog von radbruch weiter oben schon gesehen, aber ich steurere den RP6 ja von meiner M32 aus und somit funktioniert dieser Ansatz leider nicht.

Würde mich über Antworten freuen :-)

radbruch
01.05.2008, 12:48
Hallo

Auch wenn das M32 den RP6 lenkt, die Motorfunktionen werden doch weiterhin von der Base gesteuert. Dann müßte meine setMotorPWM()-Funktion auch funktionieren. Sie ergänzt die Lib mit der Möglichkeit die PWM-Werte für die Motoren direkt zu setzen. Natürlich mit dem Risiko eines Getriebeschadens bei falscher Anwendung!

Gruß

mic

_AJ_
01.05.2008, 13:19
Moin,

du hast Recht, hab ganz vergessen, dass die Ansteuerung über die Base gehen muss. Ich hab jetzt einfach die beiden IIC-Programme um deine Funktion ergänzt und kann diese somit auch von der M32 aus aufrufen =)

Das mit dem Getriebeschaden ist das, was mir nicht so behagt. Ich lasse mit setMotorPWM die Motoren maximal um eine Geschwindigkeit von 30 "springen", wäre mir aber trotzdem lieber, wenn das mindestens linear geregelt wäre. Ich habe glaube ich auch irgendwo im Quelltext gelesen, dass der implementierte Regler nur integral ist. Hat hier vielleicht schon jemand probiert einen PID-Regler zu realisieren, der besser und vor allem schneller regelt?

Immerhin funktioniert jetzt alles so, wie ich es mir gedacht habe. Danke ^^

RP6conrad
04.05.2008, 21:18
Ich bin auch daran um mit der RP6 einen Linienfolger zu schaffen. Bei mir geht das mit die LDR. Beleuchtet wird mit 4 rote LEDS. Wen da nicht zufiel Fremdlicht ist, geht das einigermasse. Die PWM Steurung von Motor ist relatif "Soft". In der RP6baselib.c konnen sie das verscharfen.
// Soft PWM adjustment and automatic PWM shutdown if motor power is 0:
if(speed_adjust_timer++ > 2) {//Waarde verhoogd van 2 naar 8 voor softere PWM
if(mright_ptmp != mright_power) {
if(mright_ptmp < mright_power)
mright_ptmp++;
else
mright_ptmp--;
OCR1AL = mright_ptmp;
}
if(mleft_ptmp != mleft_power) {
if(mleft_ptmp < mleft_power)
mleft_ptmp++;
else
mleft_ptmp--;
OCR1BL = mleft_ptmp;
}
if(mleft_ptmp || mright_ptmp)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
else
TCCR1A = 0;
speed_adjust_timer = 0;
}
Momentan warte ich auf andere Sensoren (IR) um das ganse nach zu bessern. Allerdings ist die Geheimnis auch in die Regelparameter von Info Sensoren bis Soll Speed motoren. Er scheint mir auch wichtig das die Sensor info plausibel bleibt in eine grosse Fenster, wen moglich die ganse Breite von RP6. Wird verfolgt...

radbruch
04.05.2008, 22:09
So wird wenigstens noch eine kleine Rampe beachtet, meine Lösung war da radikaler:

// Achtung! Die PWM-Werte werden hier OHNE Rampe verändert!
void setMotorPWM(uint8_t power_links, uint8_t power_rechts)
{
extern uint8_t mleft_ptmp, mright_ptmp;

if(power_links > 210) power_links = 210;
if(power_rechts > 210) power_rechts = 210;
mleft_power=mleft_ptmp=power_links;
mright_power=mright_ptmp=power_rechts;

OCR1BL = power_links;
OCR1AL = power_rechts;

if(power_links || power_rechts)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
else
TCCR1A = 0;
}

PWM wird direkt gesetzt (und die nötigen Lib-Variablen werden angepasst), ohne Rücksicht auf Verluste. Mit allen Vor- und Nachteilen die diese Ansteuerung mit sich bringt.

Gruß

mic

abugilgil
13.03.2010, 11:47
hi Leute, tut mitr leid dass ich den thread ausgrabe aber ich hätte da eine Frage.

Ich habe es so gelöst wie radbruch es beschrieben hat, also auch eine Lichtquelle vorne angebracht und ein blatt Papier als reflektor im richtigen Winkel angeklebt. Funktioniert ziemlich gut, hängt eben stark von der Position des Reflektors ab.

Ich habe dafür den zweiten Quelltext benutzt den radbruch gepostet hat, allerdings versteh ich den Quelltext nicht wirklich. könnte jemand den Quelltext von radbruch kommentieren, damit die befehle und zeilen etwas verständlicher sind. Also so Kommentare zu den Absätzen hinzufügen damit es verständlicher ist was die Befehle nun genau machen.

Auserdem frage ich mich was der Unterschied nun zwichen den 3 Quelltexten von radbruch ist.

Gruß

Morpheus1997
21.03.2011, 18:22
keine angst, ich versteh sie auch nicht ;)

fabqu
23.09.2012, 18:39
Hi!
Ich habe hier drei CNY70 rumliegen und darf kommende Woche ne Platine meiner Wahl fräsen :D oder auch zwei

Daher wollte ich dafür natürlich was mitnehmen und habe eine Frage an euch:
Wie nah sollten die CNY's nebeneinander angebracht werden? Habe momentan 2mm von CNY zu CNY eingeplant... reicht das?
Mehr? Weniger?
Gibts da Erfahrungswerte?

Danke Euch!
Fabian

RolfD
24.09.2012, 03:37
Was ist an dem Programm von radbruch denn so schwierig zu verstehen?

if (readADC(ADC_LS_L) > readADC(ADC_LS_R))

da liest er die LDR Sensoren ein und entscheidet je nach Lichteinfall ob er mehr nach links oder mehr nach rechts steuert.. mit Hilfe von

setMotorPWM(100,50); und
setMotorPWM(50,100);

was 25% und 50% PWM Puls entweder links oder rechts gibt. Und das ganze als Schleife...
Also einfacher gehts wirklich kaum.
@fabqu
Zu den CNY's
Aus http://www.rn-wissen.de/index.php/CNY70
Da es dort aber um einen Encoder, und bei einem Linienfolger weniger um die Absolutwerte als eher die relativen Differenzen der Sensoren geht, ist es relativ egal wie weit sie auseinander stehen... nur muss dann ggf. eben die Linienbreite angepasst werden.
Ich würde mal grob schätzen.. Abstand der CNY=Linienbreite und min. 5mm bis max 15mm. Schwarzes oder weißes Isolierband eignet sich gut für Linien auf glatten Böden, man kann aber auch seine Musterteppiche abfahren...
LG Rolf

fabqu
24.09.2012, 08:23
Super, danke dir!
Dann werde ich etwa 5mm einbauen.

Grüße


EDIT: Habe nun 8,9mm von Sensorfläche zu Sensorfläche. Sollte passen

fabqu
12.10.2012, 23:16
So, hier mal Fotos von der Platine :D
Hat super geklappt! Jetzt fehlt nur noch die Zeit, da was auf dem Robby zu machen... aber kommt noch!
Die ganze Platine ist durch Jumper oder BC847 (de-)aktivierbar.
23444 23445
Grüße

Filou89
22.12.2012, 10:13
Hallo Zusammen,
ich wollte mal fragen, ob ihr schon gute erfahrungswerte gemacht habt punkto Positionierung der Phototransistoren.
Ich habe eine 2cm breite Linie und plane, in der mitte eine IR-Diode anzubringen. Wie gross würdet ihr den Abstand zwischen den beiden Phototransistoren wählen?
a) weniger als 2cm
b) 2cm, also beide auf dem Linienrand
c) mehr als 2cm
:)

Wichtige Info: Es kann auch eine Abzweigung vorkommen, diese kann aber ignoriert werden, bzw darf nicht Störungen verursachen.

Grüsse Filou

Dirk
22.12.2012, 15:32
Guckst du: https://www.roboternetz.de/community/threads/55187-Sensoren-für-Linienfolger

Kookaburra
01.02.2013, 11:01
Hallo liebe Roboternetz Community,

als Fahrzeugtechniker mit bescheidenem Wissen in Elektrotechnik aber hohem Interesse an autonomer Fortbewegung habe ich für meinen RP6 einen Liniensensorcluster gebaut. Dieser besteht aus fünf nebeneinander montierten CNY70 Optokopplern. Habe das ganze auch schon getestet und funktioniert einwandfrei.

Meine Fragen beziehen sich nun auf die Elektrotechnische Schaltung des Clusters.
Da die Sensoren parallel geschaltet sind habe ich eine kurze Rechnung (siehe Skizze) unternommen um die Stromaufnahme zu bestimmen. Ist diese Rechnung plausibel und verkraftet der RP6 die Stromaufnahme von 0,114 A (?) problemlos?
Die elektrische Leistung wird über die Platinenpunkte VCC & GND auf dem M32 Bord entnommen. Kann ich dies auch direkt über die ADC-Stecker tun, so dass der gesamte Kabelstrang zusammengeführt werden kann oder dürfen hier nur die maximalen 20mA des µC entnommen werden?

Vielen Dank für jede Hilfe!

Gruß
Chris

24392243932439424395

Dirk
01.02.2013, 13:34
Hallo Chris,
den Gesamtstrom kannst du theoretisch auch am ADC-Stecker entnehmen.

Was die Schaltung angeht, geht das aber viel günstiger:
Du kannst 3 und dann nochmal 2 der CNY in REIHE an VCC schalten. Dadurch ist die Stromaufnahme viel geringer, als wenn du jeden der CNY an 5V anschließt.
Da du die CNY-Emitter mit 220 Ohm Vorwiderständen betreibst, fließt ein Strom für 5 CNY von ca. 84 mA (ca. 17 mA pro CNY bei Vf = 1,3V).

Wenn du von den 5 CNY 3 in Reihe an 5V schaltest, könntest du einen Vorwiderstand von 68 Ohm nehmen.
Die andere Reihe mit den restlichen 2 CNY bekäme dann an 5V einen Vorwiderstand von 150 Ohm.
Der Gesamtstrom würde sich damit auf nur ca. 34 mA errechnen, also eine Stromeinsparung von 60%.

N.B.: Ich würde den CNYs auch etwas mehr Strom geben, z.B. 30 oder 40 mA. Dann müßtest du nochmal neu rechnen.

EK9
30.10.2013, 07:58
Guten Tag, suche für den Arexx RP6 V2, den Sensor, mit dem ich eine linienverfolgung machen kann, bitte um Hilfe

fabqu
30.10.2013, 11:52
Hi EK9,

also da gibts viele Möglichkeiten. Es gibt fertige module, sind aber teilweise teuer.
Oder du baust dir einen aus den CNY70-Reflexoptokopllern, siehe z.B. im RN-Wissen, dort gibts einen extra Artikel über diese Bausteine. Auch hier (http://www.rn-wissen.de/index.php/RP6_Multi_IO_Projekt#Liniensucher-Board).

Am einfachsten ist wohl das Prinzip LED mit zwei Helligkeitssensoren, z.B. LDR (lichtsensitive Widerstände). Das wurde glaube ich beim ASURO so umgesetzt, da findet sich vieles Im Internet, einfach mal googlen oder im RN-Wissen suchen oder hier im Forum.

Viele Grüße

TrainMen
30.10.2013, 11:59
Hallo,
willkommen hier im Forum.
Soweit mir bekannt gibt es keine fertige Lösung zum Linienfolgen für den RP6. Du mußt dann also selber bauen. Als Sensor kann man den CNY70 verwenden. Ideen und Bauvorschläge findest Du hier im Forum. Suche mal nach Linienfolger.

EK9
10.11.2013, 11:18
Hallo

Echt krass was die Lampe bringt. Das Programm ist immer noch minimal, aber das Ergebniss ist trotzdem prima:

http://s3.ytimg.com/vi/r2VC2YF7ycM/2.jpg (http://www.youtube.com/watch?v=r2VC2YF7ycM)
http://www.youtube.com/watch?v=r2VC2YF7ycM


// Einfaches Linienfolgen mit RP6-Sensoren (Test der Funktion 2) 6.3.2008 mic

#include "RP6RobotBaseLib.h"

// Achtung! Die PWM-Werte werden hier OHNE Rampe verändert!
void setMotorPWM(uint8_t power_links, uint8_t power_rechts)
{
extern uint8_t mleft_ptmp, mright_ptmp;

if(power_links > 210) power_links = 210;
if(power_rechts > 210) power_rechts = 210;
mleft_power=mleft_ptmp=power_links;
mright_power=mright_ptmp=power_rechts;

OCR1BL = power_links;
OCR1AL = power_rechts;

if(power_links || power_rechts)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
else
TCCR1A = 0;
}
int main(void)
{
initRobotBase();
while(1)
{
writeInteger(readADC(ADC_LS_L), 10);
writeString_P(" - ");
writeInteger(readADC(ADC_LS_R), 10);
writeString_P("\n\r");
if (readADC(ADC_LS_L) > readADC(ADC_LS_R))
{
setLEDs(4);
setMotorPWM(100,50);
}
else
{
setLEDs(32);
setMotorPWM(50,100);
}
mSleep(100);
}
return(0);
}

Der "Reflektor" ist ein Blatt Papier, die Werte auf den Fliesen sind über 800!

Gruß

mic



Wie kann ich hier veranlassen das der Robby rückwärts statt vorwärts fährt?

radbruch
10.11.2013, 11:27
Hallo

Die Drehrichtungen der Antriebe kann man mit setMotorDir() aus der Library RP6RobotBaseLib.c festlegen:


/**
* Sets the rotation direction of both motors.
*
* DO NOT CHANGE THE DIRECTION OF THE MOTORS WHILE THEY
* ARE RUNNING AT HIGH SPEEDS!!!
* It will not instantly damage the motors/gears, but they will
* wear out much faster if you do it at high speeds - better wait
* until speed has slowed down - and change direction AFTER this.
*
* -------------------------------------------------------------
* IT IS A BETTER IDEA NOT TO USE THIS FUNCTION AT ALL!
* Use moveAtSpeed together with task_motionControl instead.
* YOU CAN NOT USE setMotorPower AND setMotorDir WHEN YOU USE
* task_motionControl! This will not work!
* -------------------------------------------------------------
*
* task_motionControl also ensures that the direction is changed
* slowly and only after the motors have stopped!
*
* Example:
* // DO NOT perform these commands directly after each
* // other in your programs - this is just a LIST of possible
* // combinations:
* setMotorDir(FWD,FWD); // Move forwards
* setMotorDir(BWD,FWD); // Rotate right
* setMotorDir(FWD,BWD); // Rotate left
* setMotorDir(BWD,BWD); // Move backwards
*
*/
void setMotorDir(uint8_t left_dir, uint8_t right_dir)
{
mleft_dir = left_dir;
mright_dir = right_dir;
mleft_des_dir = left_dir;
mright_des_dir = right_dir;
if(left_dir)
PORTC |= DIR_L;
else
PORTC &= ~DIR_L;
if(right_dir)
PORTC |= DIR_R;
else
PORTC &= ~DIR_R;
}Wie beschrieben sollten die Drehrichtungen nicht bei Vollgas umgeschaltet werden!

Gruß

mic

EK9
10.11.2013, 11:54
könntest du mir anhand dem Programm welches ich gesendet habe, aufzeigen? lg

fabqu
11.11.2013, 08:08
Hi EK9,

sorry, aber da wirst du selber ran müssen. In dem Forum wird keiner für dich den Code umschreiben ;)
Schau mal in die Anleitung und in die Beispielprogramme. Dort findest du viele Beispiele und Erklärungen zu den ganzen Funktionen, auch zu setMotorDir() usw.

Ist gar nicht so schwer, und durch ausprobieren lernst du mehr als durch ablesen.
Wenns dann scheitert, hilft dir hier sicherlich jeder herauszufinden, warum!

EK9
11.11.2013, 08:23
habe schon ein paar sachen ausprobiert und mit den beispielprogrammen wurde ich auch nicht fündig

RolfD
14.11.2013, 00:15
Die Funktion setMotorDir() kannst du dir - wie schon von Radbruch gezeigt - in der RP6RobotBaseLib.c ansehen, wie sie verwendet wird z.B. in RP6Base_SELFTEST.c
Dort findet sich z.B. setMotorDir(FWD,FWD); ... wobei FWD wiederum in der RP6RobotBaseLib.h definiert ist, ebenso wie eine Zeile tiefer der Rückwärtsgang...
Einfach mal selber suchen und lesen... und nicht andere suchen lassen... so lernt man nichts.

Gruß Rolf

EK9
14.11.2013, 13:04
Möchte den Arexx vom Start an rückwärts laufen lassen und nicht umschalten

EK9
14.11.2013, 17:35
Danke euch, bin leider noch nicht der Prof beim RP6. setMotorDir(BWD,BWD);

komme aus dem staunen kaum raus das es nur nach dem einfügen dieses Satzes funkioniert.

RolfD
17.11.2013, 23:43
Aha! ok.. man muss auch nicht Prof sein um mit dem RP6 was zu machen.. lesen, lernen und umsetzen hilft meist schon.

Die Erklärung dazu: Mit SetMotorDir setzt man "eiskalt" die Drehrichtung der Ketten/Motoren wobei der Befehl eben direkt und schlagartig in die Hardware greift. Es gibt noch andere Befehle für den Motor, die z.B auch verhindern das man sich mit dem SetMotorDir das Getriebe schrottet - indem Anfahr- und Bremsrampen vor einem Richtungswechsel genutzt werden. Da Du nun schon mal was in den Quellcodes gefunden hast, sollte es dir nicht schwer fallen, z.B. alle Textstellen mit "Motor" zu suchen und durchzuarbeiten. Usw. usw. usw... Learning by doing.
Gruß Rolf

EK9
18.11.2013, 19:38
Guten Abend, kann mir jemand diese einzelnen Instruktionen erklären, was diese heissen?



void setMotorPWM(uint8_t power_links, uint8_t power_rechts)
{
extern uint8_t mleft_ptmp, mright_ptmp;

if(power_links > 210) power_links = 210;
if(power_rechts > 210) power_rechts = 210;
mleft_power=mleft_ptmp=power_links;
mright_power=mright_ptmp=power_rechts;

OCR1BL = power_links;
OCR1AL = power_rechts;

if(power_links || power_rechts)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
else
TCCR1A = 0;

radbruch
18.11.2013, 20:03
Hallo

Es ist mir völlig unklar, warum du dich bei der umfangreichen RP6-Library ausgerechnet auf diese Funktion stürzt anstatt die Library anhand ihrer einzelnen Demoprogramme zu erkunden. Der RP6 ist so komplex, da wirst du nicht weit kommen, wenn du nicht etwas Eigeninitiative entwickelst.

Kurz zur Funktion setMotorPWM(). Sie dient dazu die PWM-Werte für die Antriebe direkt zu setzen und die entsprechenden Variablen der Library anzupassen:

Die erste Hälfte stellt den Bezug zu den in der Library verwendeten Variablen her, begrenzt die PWM-Werte auf den in der Lib verwendeten und in dieser Timerbetriebsart durch das ICRA-Register gesetzten Maximalwert von 210 und lädt schließlich die Libraryvariablen mit den geänderten Werten. Im zweiten Teil der Funktion werden die Compare-Register der beiden Seiten mit dem PWM-Wert geladen und der Timer aktiviert, wenn die PWM-Werte dies erfordern.

Gruß

mic

RolfD
18.11.2013, 20:14
Anmerkung... hat sich mit Radbruchs Post überschnitten...

Eigentlich recht wenig. Von unten hoch... stell dir vor, irgendwo im RP6 (Prozessor) gibts einen Taktgenerator den man VOReinstellen kann... das passiert indem auf das Register TCCR1A geschrieben wird. Damit der Zähler weis wie weit er zählen soll, beschreibt man die Register OCR1BL und OCR1AL wobei das Einfluß auf die Energiemenge der Motoren hat. 0 heisst Motor hat kein Strom bzw. 0%, 210 ist Vollgas und 100%... bei 2 Ketten bzw. 2 Motoren (OCR1BL=links und OCR1AL=rechts) kann man also je Kette getrennt die angelegte Leistung kontrollieren. Da der Wert von 210 nicht überschritten werden sollte ( hängt u.a. mit dem Teilerfaktor zusammen ), werden die Werte zwischengespeichert und geprüft bzw. auf max=210 gesetzt.

Jetzt von oben nach unten...
Die Funktion bekommt die Speed für beide Motoren übergeben, prüft diese auf positive 210 max und setzt sie ggf. runter, zwischenspeichert das in eine externe Variable, schreibt beide Werte in die jeweiligen PWM Zählerregister OCR1xx und setzt PWM Modus, Vorteiler usw.

Die Funktion ist also quasi das Gaspedal für den RP6.
Würde man dort z.B. auch die Richtung setzen wollen.. was nicht mal so dumm wäre... würde man schreiben:

void setMotorPWM_spezial(uint8_t power_links, uint8_t power_rechts, uint8_t left_dir, uint8_t right_dir)
{
extern uint8_t mleft_ptmp, mright_ptmp;

if(power_links > 210) power_links = 210;
if(power_rechts > 210) power_rechts = 210;
mleft_power=mleft_ptmp=power_links;
mright_power=mright_ptmp=power_rechts;
mleft_dir = left_dir;
mright_dir = right_dir;
mleft_des_dir = left_dir;
mright_des_dir = right_dir;

OCR1BL = power_links;
OCR1AL = power_rechts;
if(left_dir)
PORTC |= DIR_L;
else
PORTC &= ~DIR_L;
if(right_dir)
PORTC |= DIR_R;
else
PORTC &= ~DIR_R;

if(power_links || power_rechts)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
else
TCCR1A = 0;
}


dann noch den Prototypen bauen... nen "extern" muss da glaub ich auch noch rein.. damit c nicht meckert.. und schon hast du eine Funktion die nicht nur Geschwindigkeit sondern auch die Richtung verarbeitet. Bei der Richtungsverarbeitung wird einfach nur festgelegt, an welchen der 4 möglichen Pins die Signale abgegeben werden soll wobei nur 2 aktiv sein dürfen. Nachteil ist, das man nun auch ständig die Richtung mitgeben muss und sie sollte sich nicht spontan ändern wenn das Getriebe läuft. Schaut man sich die anderen Motorfunktionen an (was ich Dir empfohlen hatte!!!), stellt man aber fest, das es sowas schon in der RP6lib gibt.
Da steht auch sehr deutlich: IT IS A BETTER IDEA NOT TO USE THIS FUNCTION AT ALL!
Man kann das ganze noch aufhübschen.. in dem man z.B. auf echte % umrechnet, negative Werte als rückwärts verarbeitet und damit die 2 extra Parameter spart... aber "zweckmäßig" reicht meist auch vollkommen und ist meist kürzer im Speicher.
Nun solltest du dich aber mal mit der Theorie und Praxis von PWM beschäftigen... dazu finden sich schöne Artikel im WIKI ebenso wie in der Docu vom Prozessor.
Gruß Rolf