PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fernsteuerung für den RP6



Mc Delta
09.03.2010, 17:37
Hallo alle zusasmmen!
Nachdem ich bereits 2 Projekte erfolgreich vollendet habe, wollte ich jetzt etwas "Neues" anfangen. Ich weiß, dass zu dem Thema Fernsteuerungen + RP6 schon ein paar Themen existieren aber Ich konnte daraus nicht schlau werden. Mein Ziel ist es mit der 4-Kanal Fernsteueranlage von Conrad (Best.-Nr. : 2331736M) Funksignale zu senden und mit dem RP6 zu empfangen und und ihn darauf reagieren zu lassen. Was Ich wissen muss:
1. Wo muss Ich welchen Pin anschließen? ( Ich benötige erstmal nur 2 Kanäle.)
2. Wie kann ich das Empfängersignal mit dem RP6 auswerten? (Software)
3. Habt ihr bessere Vorschläge welche Fernbedienung gut ist ?
http://www.conrad.de/ce/de/product/233173/4-KANAL-FERNSTEUERUNGS-SET-40-MHZ/SHOP_AREA_19785 < Das ist der Link zu den wichtigsten Daten und Downloaddokus.
Vielen Dank!

Mc Delta
09.03.2010, 17:39
Ach ja nur um das klar zu stellen mir stehen alle Ports des RP6 zur Verfügung. Die Fernsteuerung werde Ich mir auch erst besorgen wenn ich weiß wie das Alles funktioniert und ein Programm habe.

roboter14
15.03.2010, 16:38
Was willst du mit der Fernsteuerung alles fernsteuern? Und reicht es dir nicht aus, dass du über IRComm mit einer RC5 Fernbedienung (Radio, Fernseher,etc...) den RP6 steuern kannst?

RobbyMartin
15.03.2010, 16:52
@ roboter14 die RC5 Fernbedienung kannst du nur bei Sichtkontakt benutzen und ausserdem nur auf geringe distanz über funk kann man ihn viel weiter fernsteuern

LG
martin

karmic_koala
16.03.2010, 15:32
@Mc Delta!
Um den Empfänger mit den Ports zu verbinden, brauchst du erst einmal ein Kabel (z.B. vom großen C (http://www.conrad.de/ce/de/product/384193/SERVOKABEL-ZINN-30CM/SHOP_AREA_34608)).Anschlussbelegung siehe hier (http://privat.swol.de/radolfzell/Modellbaugruppe/Tips_tricks/pinbel_servo.htm). "Signal Puls" dann mit einem Eingangs-Port verbinden. Signale sind wie hier (http://bahn-in-haan.de/_servodec.html). Dein Robby wird dann wie ein Servo behandelt - abhängig von der Signallänge könntest du dann die Geschwindigkeit sowie den Radius steuern.
karmic_koala

Mc Delta
17.03.2010, 14:31
Hi
Ich habe mir überlegt, dass man die Kanalausgänge an die beiden ADCs dranmacht und dann nur die Verschiedenen Eingangsspannungen auswertet. Allerdings bräuchte ich da sone art durchschnittswert funktion, damit die Schwankungen je Messung nicht so extrem sind und man mit den Werten was anfangen kann.
Gingen eigentlich aucch die Ports SDA und SCL und wie könnte ich dann das Eingangsignal auswerten?
Danke!

Mc Delta
17.03.2010, 15:15
Gibt es eventuell eine Funktion in der lib mit der man überprüfen kann ob SCL und SDA (als Eingänge) high oder low sind?

roboter14
17.03.2010, 16:03
Hi McDelta,
ich habe auf YouTube ein Video entdeckt (von radbruch) :http://www.youtube.com/watch?v=A_GYUeFAgY8

Kannst dazu auch mal radbruch eine PN schreiben wie er das gemacht hat.
Hier der Originaltext von ihm:



Anstelle der Linie kann man ja erst mal softwaremässig eine Route vorgeben nach der die Steine gesetzt werden. Oder man steuert den RP6 mit einer Modelbaufernbedienung:


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

Blöderweise klemmt grad mal wieder der linke Antrieb, er fährt nicht zurück. Aber das hatte er schon immer. Ich mache noch ein schöneres Video, wenn er wieder richtig läuft.

Das Auswerten der RC-Signale ist unglaublich einfach. Ich verwende dazu die selbe ISR wie beim Ansteuern der Servos (beides zusammen funktioniert übrigens auch prima). Wenn man die Aufrufe der ISR bei gesetztem RC-Eingangspin zählt, erhält man Werte die denen der Servosteuerung entsprechen. Der RP6 kann so sogar seine eigenen Servoimpulse zählen:


Code:// RC-RP6 erster Versuch 18.11.07 mic

#include "rblib.h"
#include "rblib.c"

uint8_t y, z;
uint8_t rc_input_pwr, rc_input_dir;
uint8_t rc_pwr, rc_dir;

ISR(TIMER0_COMP_vect)
{
//static uint16_t count=0;
static uint16_t rc_temp_pwr=0;
static uint16_t rc_temp_dir=0;
//if(count>x) PORTA &= ~16; else PORTA |= 16; // E_INT1 (Pin8)
//if(count>y) PORTC &= ~1; else PORTC |= 1; // SCL (Pin10)
//if(count>z) PORTC &= ~2; else PORTC |= 2; // SDA (Pin12)
//if(count<1000)count++; else count=0;
if (PINC & 1) rc_temp_dir++; else
if (rc_temp_dir) { rc_input_dir=rc_temp_dir-1; rc_temp_dir=0; }
if (PINC & 2) rc_temp_pwr++; else
if (rc_temp_pwr) { rc_input_pwr=rc_temp_pwr-1; rc_temp_pwr=0; }
}
void servo_init(void)
{
//DDRA |= 16; // E_INT1 als Ausgang
//DDRC |= 3; // SCL und SDA als Ausgang

TCCR0 = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0 |= (0 << COM00) | (0 << COM01); // ohne OCR-Pin
TCCR0 |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE0); // Interrupt ein
OCR0 = 9; // 100kHz?
}
int main(void)
{
rblib_init();
servo_init();

setLEDs(0b1001);
setMotorDir(FWD,FWD);
setMotorPWM(0,0);

while(1)
{
rc_pwr=0;
rc_dir=0;

if (rc_input_dir<120) { rc_dir=150-rc_input_dir; setMotorDir(BWD,FWD); }
if (rc_input_dir>140) { rc_dir=rc_input_dir-110; setMotorDir(FWD,BWD); }
if (rc_input_pwr<120) { rc_pwr=150-rc_input_pwr; setMotorDir(FWD,FWD); }
if (rc_input_pwr>140) { rc_pwr=rc_input_pwr-110; setMotorDir(BWD,BWD); }
rc_pwr*=3;
if (rc_pwr)
{
if (rc_input_dir<120) setMotorPWM(rc_pwr-rc_dir,rc_pwr+rc_dir);
else if (rc_input_dir>140) setMotorPWM(rc_pwr+rc_dir,rc_pwr-rc_dir);
else setMotorPWM(rc_pwr,rc_pwr);
}
else
{
setMotorPWM(rc_dir*3, rc_dir*3);
}

}

return 0;
}

radbruch
17.03.2010, 18:26
Hallo

Bitte, bitte, bitte keine PNs an mich! Persönliche Beratung lehne ich grundsätzlich ab.

Inzwischen verwende ich bei Servoansteuerung mit geringer Auflösung die Timer1-Overflow-ISR. Sie wird von der Lib nicht genutzt und steht damit zur freien Verfügung:

http://i3.ytimg.com/vi/fGHDkUlJuh0/default.jpg (http://www.youtube.com/watch?v=fGHDkUlJuh0)
http://www.youtube.com/watch?v=fGHDkUlJuh0

Libverträglich und mit wenig Aufwand einzubauen.

Gruß

mic

_|Alex|_
17.03.2010, 19:09
könnte man nicht einfach ein RC Auto ausschlachten?

Mc Delta
17.03.2010, 19:41
Natürlich kannst du das machen. Aber dann kannst du genauso gut eine Fensteueranlage kaufen.(oder servos, motoren und empfänger was du eben ausschlachten willst...)

_|Alex|_
17.03.2010, 19:44
war ne idee da ich ein altes Auto hab wo der Servo für die Lenkung Defekt ist

Mc Delta
18.03.2010, 18:07
An Radbruch!
Hi,
das Demoprogram zur Ansteuerung von Servos habe ich soweit verstanden. Da geht es ja drum ein Positives Signal zu senden aber ich möchte eines empfangen. Wie geht das? ( Mit den gleichen Ports: SCL, SDA) Der Empfänger dessen Signal hier ausgewertet werden soll sendet ganz normale Servo Impulse. Mir geht es eben nur darum zu wissen wie ich dass Empfängersignal auswerten kann.
Danke!!

radbruch
18.03.2010, 18:27
Hallo

Schon klar, dass du die Impulslängen der Servosignale des RC-Empfängers messen und auswerten willst. Aber wenn du kapiert hast, wie die Impulse in der ISR erzeugt werden, ist der Schritt zur Impulslängenmessung mit der selben ISR nicht mehr weit:
https://www.roboternetz.de/phpBB2/viewtopic.php?p=356247#356247

bzw. wird hier der Code in einer Timer0-ISR verwendet und ist deshalb nicht mit der RP6-Lib verträglich. Eine Kombination mit der Timer1-Overflow-ISR wäre der optimale Kompromiss:
https://www.roboternetz.de/phpBB2/viewtopic.php?p=328824#328824

Damit geht dann das:
http://img.youtube.com/vi/A_GYUeFAgY8/2.jpg (http://www.youtube.com/watch?v=A_GYUeFAgY8)
http://www.youtube.com/watch?v=A_GYUeFAgY8

Gruß

mic

Mc Delta
01.04.2010, 13:25
Hallo nchmal,
Ich habe mir gestern die oben verlinkte Fernsteueranlage von Conrad gekauft. Sie funktioniert wunderbar und auch das Fernsteuerprogramm von Radbruch läuft super. Nur wollte ich auch mal ein "eigenes" Program schreiben um den RP6 fernsteuern zu können. Es funktioniert leider nicht so wie ich es mir vorgestellt hatte. Deswegen brauche ich noch ml Hilfe!!
Undzwar hatte ich das Teilprogramm um die Signale auszulesen von Radbruch. ( In dem Program werden Werte von SCL und SDA ausgegeben)
Dieses habe ich ein wenig gekürzt und wollte mithilfe einer Ergänzung erreiche, dass die Signalwerte in Motorbefehle umgewandelt werden. Doch wenn ich das Program starte und die Fernsteuerrung anschalte macht der RP6 was er will. Manchmal dreht sich die rechte Kette dann wieder die Linke ohne das ich es beeinflussen kann. (Ein Hardware Problem liegt definitiv nicht vor, weil das rb-programm ja tadellos funktioniert.)
Noch was zu den Variablennamen: Ich habe die absichtlich umbenannt, weil ich jeden Motor einzelnd ansteuern will. (pwrr= rechter Motor, pwrl= linker Motor.)
Die anderen Variablen(y,x,c,v) Sind als Eingrenzung gedacht, damit man die ausgewerteten Signale auch VERWERTEN kann. Ich glaube allerdings nicht, dass das Problem daher kommt. Denn ich habe schon ein Program zum einlesen der Variablen rc_input... laufen lassen und die Eingrenz-Variaben danach ausgerichtet.
Hier ist nun der Code: (mir ist es wichtig die orginal RP6.h Lib zu verwenden, deshalb benutze ich auch nicht Radbruchs Programm mit der rb-Lib als Ansatz.)


#include "RP6RobotBaseLib.h"

volatile uint8_t rc_input_pwrr=26, rc_input_pwrl=26;

int main(void)
{
initRobotBase();
TIMSK |= (1 << TOIE1); // Die Timer1 Overflow-ISR zur Signalauslesung
powerON();
uint8_t y=29;
uint8_t x=26;
uint8_t c=24;
uint8_t v=28;

while(1)
{
if (rc_input_pwrl>y ) {changeDirection(BWD); while (rc_input_pwrl<y) {moveAtSpeed(0,60);}}
if (rc_input_pwrl<x ) {changeDirection(FWD); while (rc_input_pwrl>x) {moveAtSpeed(0,60);}}
if (rc_input_pwrr<c ) {changeDirection(BWD); while (rc_input_pwrl<c) {moveAtSpeed(60,0);}}
if (rc_input_pwrr>v ) {changeDirection(FWD); while (rc_input_pwrl>v) {moveAtSpeed(60,0);}}
task_motionControl();
}
return 0;
}

ISR (TIMER1_OVF_vect) // RC-Signale an SCL und SDA messen
{
static uint16_t rc_temp_pwrl=0;
static uint16_t rc_temp_pwrr=0;
if (PINC & 1) rc_temp_pwrl++; else
if (rc_temp_pwrl) { rc_input_pwrl=rc_temp_pwrl-1; rc_temp_pwrl=0; }
if (PINC & 2) rc_temp_pwrr++; else
if (rc_temp_pwrr) { rc_input_pwrr=rc_temp_pwrr-1; rc_temp_pwrr=0; }
}



Diejenigen von euch deMir helfen wollen und eine eigene Fernsteuerung besitzen können das Programm ja mal ausprobieren und rumprbieren. Ich bin wirklich dankbar wenn ihr mir helfen könnt.

radbruch
01.04.2010, 13:49
Hallo

Bei x/y stimmen die > und < nicht. Wäre diese Abfrage nicht besser?

if (rc_input_pwrl>y )
{
changeDirection(BWD);
pwr_l=60;
}
else if (rc_input_pwrl<x )
{
changeDirection(FWD);
pwr_l=60);
}
else pwr_l=0;

if(pwr_l || pwr_r)
moveAtSpeed(pwr_l, pwr_r);
else
stop();(ungetestet, drehen mit beiden Motoren geht so aber auch nicht)

Schön dass es quasi auf Anhieb funktioniert ;)

Gruß

mic

Mc Delta
02.04.2010, 14:07
Hi,
Die Werte für x und y stimmen schon. Die sind nur anders weil ich Die Laufrichtung der Servos geändert habe, aber deine Anregung habe ich umgesetzt und folgendes ist dabei rasgekommen:


#include "RP6RobotBaseLib.h"

volatile uint8_t rc_input_pwrr=26, rc_input_pwrl=26, rc_input_schalt;

int main(void)
{
initRobotBase();
TIMSK |= (1 << TOIE1); // Die Timer1 Overflow-ISR zur Signalauslesung
powerON();
setACSPwrHigh();
setLEDs(0b111111);
uint8_t y=21;
uint8_t x=29;
uint8_t c=22;
uint8_t v=29;
uint8_t pwr_l=0;
uint8_t pwr_r=0;
void acsStateChanged(void)
{
if(!obstacle_left && !obstacle_right)
{
move(160, FWD, DIST_MM(50), true);
}
while(true)
{

if(!obstacle_left && !obstacle_right)
{
move(160, FWD, DIST_MM(50), true);
}
else
{

if(obstacle_right)
{
rotate(160, LEFT, 2,true);
}
else
{
while((obstacle_left && obstacle_right) || obstacle_left)
{
rotate(160, RIGHT, 2,true);
}
}
}
task_Bumpers();
if(getBumperLeft() && getBumperRight()) // Beide Bumper
{
move(160, BWD, DIST_MM(30), true);
rotate(160, LEFT, 35,true);
}
if(getBumperLeft()) // Bumber Links
{
move(160, BWD, DIST_MM(30), true);
rotate(160, RIGHT, 25,true);
}
if(getBumperRight()) // Bumber Rechts
{
move(160, BWD, DIST_MM(30), true);
rotate(160, LEFT, 25,true);
}
mSleep(10);




}
}

while(1)
{
task_motionControl();
task_ACS();
if (rc_input_schalt>x) // Umschalten auf Autopilot
{
while (rc_input_schalt>x)
{
ACS_setStateChangedHandler(acsStateChanged); // ACS Event Handler registrieren
}
}
if (rc_input_pwrr<17 && rc_input_pwrl<17 && rc_input_pwrr>32 && rc_input_pwrl>32)
{
stop();
}
if (rc_input_pwrr<c && rc_input_pwrl<y)
{ while (rc_input_pwrr<c && rc_input_pwrl<y)
{
rotate(60, LEFT, 1, true);
}
}
if (rc_input_pwrr>v && rc_input_pwrl>x)
{ while (rc_input_pwrr>v && rc_input_pwrl>x)
{
rotate(60, RIGHT, 1, true);
}
}

if (rc_input_pwrr<c )
{
changeDirection(FWD);
pwr_r=60;
}
else if (rc_input_pwrr>v )
{
changeDirection(BWD);
pwr_r=60;
}
else pwr_r=0;
if (rc_input_pwrl<y )
{
changeDirection(BWD);
pwr_l=60;
}
else if (rc_input_pwrl>x )
{
changeDirection(FWD);
pwr_l=60;
}
else pwr_l=0;

if(pwr_l || pwr_r)
{
moveAtSpeed(pwr_l, pwr_r);
}
else
stop();

}
return 0;
}

ISR (TIMER1_OVF_vect) // RC-Signale an SCL und SDA messen
{
static uint16_t rc_temp_pwrl=0;
static uint16_t rc_temp_pwrr=0;
static uint16_t rc_temp_schalt=0;
if (PINC & 1) rc_temp_pwrl++; else
if (rc_temp_pwrl) { rc_input_pwrl=rc_temp_pwrl-1; rc_temp_pwrl=0; }
if (PINC & 2) rc_temp_pwrr++; else
if (rc_temp_pwrr) { rc_input_pwrr=rc_temp_pwrr-1; rc_temp_pwrr=0; }
if (PINA & 16) rc_temp_schalt++; else
if (rc_temp_schalt) { rc_input_schalt=rc_temp_schalt-1; rc_temp_schalt=0; }



}



Funktiniert ganz ausgezeichnet =D>

radbruch
02.04.2010, 14:16
Glückwunsch. Das Auswerten der RC-Signale hast jetzt echt gut im Griff. Die Umschaltung zwischen Autopilot und Fernsteuerung ist eine prima Idee.