PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : rp6 anschlussbelegungen



Morpheus1997
15.01.2011, 13:54
hey leute...ich hab da mal ne frage zu dem roboter rp6..
ich habe aus meinem alten, nicht mehr fahrendem ferngesterertem auto eine "Kanone" aus gebaut, die einen kleinen Pfeil abschießt, wenn ich spannung anlege. nun möchte ich sie an meinem rp6 anschließen, so dass sie einen Pfeil schießt, wenn dem Acs etwas im weg ist! geht das so ohne weiteres?
muss ich die erweiterungsplatine haben oder geht das auch mit der experimentierplatine? und wo muss ich sie anschließen?
Mfg Morpheus1997

fabqu
15.01.2011, 15:17
Du hast auf deiner Base zwei ADCs, ADC0 und ADC1 (Analog-Digital-Wandler), die sich als Ausgänge nutzen lassen und theoretisch vier weitere I/Os, die aber mit deinen LEDs zusammenhängen.
Daher würde ich dir raten: Löte eine dreier-Stiftleiste (gibts bei Konrad in allen Längen) an diesen ADC, Schließe Stecker dort dran und an den Stecker kannst du dann löten: (Gnd, also Minus) an GND deines ADC0 oder 1 (siehst du auf deiner Base recht weit vorne, etwas hinter dem IR-Empfänger), das +Kabel schließt du an den dortigen anschluss ADC0. Jetzt musst du das eben noch in dein Programm einbinden, was heißt: Den betreffenden ADC auf Ausgang schalten und dann eben High setzen für Schuss, Low für nicht-schießen. Wie das geht, findest du eigentlich komplett in deiner Anleitung.
Sollte dir die Base dabei abstürzen, dann zieht dein Schussaparat wohl zu viel Strom, dann musst du eben einen Transistor dazwischen schalten. Aber ich würds erst mal so veruschen.
Gruß,
Fabian

Morpheus1997
15.01.2011, 15:37
ahh ok... hm.. is aber schon sehr nah an dem prozessor dran...
habe etwas angst. dass ich da was kapput mache ;)

fabqu
15.01.2011, 15:43
Schon mal gelötet?
Dann ist das kein Problem.
Wenn du noch nie gelötet hast, dann wär ich vorsichtiger. Prinzipiell kann nicht allzu viel schief gehen, solange du nicht mit deinem Lötkolben auf dem Prozessor zumkratzt :D
Veilleicht übst du vorher mal ein bisschen, kaufst dir ne kleine Experimentierplatine beim Conrad (so zwischen 1 und 3 Euro) und lötest dort mal ein paar Kabel an, villeicht auch mal zwei drei solche Stiftleisten oder so. Wenn du dir dann halbwegs sicher bist, dann würd ich mich mal an die Base machen.
Tipp: Wenn dein Lötpunkt glänzt und nicht zu groß ist, ists meist ein guter Lötpunkt. Ist er zu groß oder matt, dann lieber nochmal weg machen. Bei Conrad gibts auch ein nettes Löt-Einstiegsset, Kolben + Halter + Lötzinn + Entlötpumpe, 10 Euro glaube ich.
Gruß,
Fabian

Morpheus1997
15.01.2011, 15:54
nene also ich löte schon ungefair ein jahr ziemlich regelmäßig und hab auch schon 5 oder 6 platinen usw gelötet...
aber da kann wirklich nichts passieren?
also dann einfach die base aufschrauben, als ob ich akkus reinbauen würde und dann so wie du beschrieben hast weitermachen?
wäre ja ziemlich einfach;)
Lg Morpheus1997

Dirk
15.01.2011, 16:14
... eine "Kanone" aus gebaut, die einen kleinen Pfeil abschießt, wenn ich spannung anlege.
Wichtig wäre zuerst:
Welche Spannung braucht die "Kanone" und welcher Strom fließt da beim "Schießen".
Wenn man das weiß, kann man auch auf dem RP6 eine Lösung finden.


aber da kann wirklich nichts passieren? also dann einfach die base aufschrauben, als ob ich akkus reinbauen würde und dann so wie du beschrieben hast weitermachen?
Da kann schon ne ganze Menge passieren! Aufschrauben brauchst du den RP6 eigentlich nicht, weil alle Anschlüsse, die du brauchst, oben auf dem Mainboard verfügbar sind.

Gruß Dirk

fabqu
15.01.2011, 16:17
Jo! So ein ding ist das nicht. Aber vielleicht noch ein tipp: um den worst case zu vermeiden, würd ich zwischen das +kabel deiner kanone und den ausgang adc0 eine normale diode löten damit niemals (z.b. Bei kurzschluss oder defekt der kanone) ein strom in deinen auf ausgang geschalteten adc läuft. Ich weiß nichts genaues, aber zur sicherheit kann ein diode für 2 Cent nicht schaden. Wie rum weißt du?

Morpheus1997
15.01.2011, 16:17
hm.. also die kanone braucht aufjeden fall 4,5 volt. stromstärke weiß ich so nicht, müsste ich nach messen!
aber wie soll ich das denn fest löten ohne das mainboard aufzuschrauben? wenn man eine platine lötet muss man sie doch auch umdrehen so ist das da doch auch oder?
LG

Morpheus1997
15.01.2011, 16:44
hm... ich glaub die braucht doch einwenig mehr als 4,5 volt...also 6-9 volt sowas braucht die
stromstärke hab ich grade gemessen, 0,5 ampère und widerstand ist 0,16kOhm

Morpheus1997
15.01.2011, 16:44
geht das trotzdem=?

Fabian E.
15.01.2011, 17:29
Zumindest nicht so einfach wie vorher beschrieben.
Du bräuchtest dann eine externe Stromquelle die du über ein Relais und einen Transistor schalten kannst. Der ADC kann nämlich nur ca. 20mA Strom liefern...
Bei mehr läufst du Gefahr das der uC kaputt geht.

SlyD
15.01.2011, 17:45
> Relais

Dafür braucht man aber i.d.R. auch einen Transistor um das anzusteuern ;)


@Morpheus:
Also besser direkt einen passenden Transistor/MOSFET verwenden und Freilaufdiode und einen Stützkondensator (mind. 100µF Elko) nicht vergessen.
Direkt an einen Mikrocontroller kann man sowas jedenfalls nicht anschließen.

Externe Stromquelle brauchst Du aber nicht, kannst die +UB Spannung vom Akkupack verwenden sofern ca. 7V reichen.

MfG,
SlyD

ralf
15.01.2011, 18:02
Hallo,
wenn Du die Platine nicht abschrauben willst, habe ich eine Lösung --
an ADC0 einen einzelnen Draht von oben anlöten( geht problemlos).
Die Spannung (bzw. GND -) kannst Du von der Experimentierplatine +/- abnehmen, muß logischerweise natürlich mit den beiligenden Anschlußkabeln mit der Hauptplatine verbunden sein.
Die Spannung +UB (Akkupack) kannst Du auch direkt von der Experimentierplatine abnehmen und auch gleich die Transistorstufe löten.


Viel Erfolg !

SlyD
15.01.2011, 18:07
Noch als Ergänzung:
Du musst gar nix auf dem Mainboard löten - wenn keine anderen Erweiterungen verwendet werden kann man auch die 3 I/O Pins vom XBUS verwenden (I2C Bus und Interrupt Signal - dann kannst Du da aber natürlich nix anderes mehr anschließen).

Alternative Lösung wäre ein I2C Portexpander --> Suchfunktion PCF8574

MfG,
SlyD

Fabian E.
15.01.2011, 18:58
> Relais

Dafür braucht man aber i.d.R. auch einen Transistor um das anzusteuern ;)


Steht doch da ;) Hab nur das "n" vergessen, vielleicht hast du es deswegen überlesen ;)

Morpheus1997
15.01.2011, 19:24
so... ich hab nun den adc angesteuert und ein programm dafür geschrieben...
welchen transistor könnt ihr mir empfehlen??

Dirk
15.01.2011, 21:03
...also 6-9 volt sowas braucht die. stromstärke hab ich grade gemessen, 0,5 ampère und widerstand ist 0,16kOhm
Also: Bei 9 V würden bei 160 Ohm etwa 56 mA fließen.

Wenn es aber doch 500 mA sind, würde ich dir den BC337 empfehlen. Basiswiderstand 220 Ohm an den Portpin (ADC0/1 oder SCL oder SDA oder E_INT1), Emitter an GND.
Deine "Kanone" an den Collector, den 2. Pol der Kanone an +UB.
100 uF zwischen GND und +UB direkt am BC337.
Diode 1N4001 parallel zur Kanone, Kathode (Strich auf der Diode) an +UB.

Gruß Dirk

fabqu
15.01.2011, 21:23
@ Dirk: braucht man die 100uF? Was bewirken die? Entstörung? Denn bei meiner transistorschaltung hab ich keinen extra angebracht.
Und wofür ist die Diode? ist auch nur zu Schutzzwecken?!
Gruß,
Fabian

Dirk
16.01.2011, 16:17
@Fabian:
Der Elko hilft dabei, einen starken Spannungseinbruch zu vermeiden, wenn die "Kanone" (mit wohl 500 mA) plötzlich abgeschossen wird. Das könnte Probleme machen und z.B. den Prozessor des RP6 resetten. Noch besser wäre ein Tiefpaß (das schreibt SlyD immer, wenn es um hohe impulsartige Ströme geht, z.B. für Servos oder wie hier für einen großen Verbraucher).

Die Diode habe ich angegeben, weil ich mir denke, dass die "Kanone" von Morpheus1997 keine ohmsche Last ist, sondern eine induktive. Das könnte z.B. ein Elektromagnet sein, der den Pfeil bei Stromfluß frei gibt. Der fliegt dann z.B. durch eine gespannte Feder los. Zu solchen nicht ohmschen Lasten gehört z.B. auch jedes Relais. Dabei kommt es zu hohen induzierten Abschalt-Spannungsspitzen, deren Polarität umgekehrt ist wie die Spannung, mit der man den Elektromagneten schaltet. Diese Spannungsspitzen können den Treibertransistor zerstören.
Daher schaltet man eine Diode "antiparallel" zur Relaisspule. Die Kathode kommt also an den Pluspol. Normalerweise fließt also kein Strom durch diese Diode. Sie ist aber für die Spannungsspitzen beim Abschalten in Durchlaßrichtung und schließt diese kurz. So bleibt alles andere am Leben!

Gruß Dirk

fabqu
16.01.2011, 17:03
Cool, danke. Wird künftig beachtet!!!

Morpheus1997
16.01.2011, 18:13
@ dirk:
ja genau es ist eine induktive last... hab ich ein wenig vertan :)
ähmm du hast ja jetzt eine spezielle diode angegeben...
ich hab noch ein paar dioden über die heißen irgendwie v 50sq100 1027r 122a0 geht die auch?
übrigens du hasst die kanone genau richtig beschrieben... sie hat auch eine spule und eine gespannte feder gibt die pfeile frei (:
aber wie rum muss der elko??
Lg MArcel

fabqu
16.01.2011, 18:19
Auf nem Elektrolytkondensator müsste es meistens draufstehen. Wenn ein fettes "-" draufgedruckt is, muss das an Gnd (Minus). Bitte nicht falsch rum, sonst könn(t)en die platzen... Und Elektrolyt im Auge tut Aua :D

Morpheus1997
16.01.2011, 18:26
;) ich will es lieber gar nicht riskieren :)

Morpheus1997
16.01.2011, 18:38
dürfte ich es auch mit dem transistor bc546 probieren??
davon hab ich nämlich noch 15 auf lager :D

Dirk
16.01.2011, 21:19
dürfte ich es auch mit dem transistor bc546 probieren??
Klar, aber lad dir vorher das Datenblatt herunter und schau dir den Kollektorstrom (Ic) an. Wenn der für deine "Kanone" reicht, dann nimm den BC546. O:)

Gruß Dirk

SlyD
18.01.2011, 11:59
Das ist nen 100mA typ der reicht nicht.

Morpheus1997
18.01.2011, 16:44
und welcher reicht dann =?

Dirk
18.01.2011, 19:32
Dirk (15.1.2011, 22:03):

... würde ich dir den BC337 empfehlen.

Gruß Dirk

Morpheus1997
18.01.2011, 20:35
gut, ich geh morgen los und kauf mir einen :)

Morpheus1997
03.02.2011, 17:42
so ich hab nun die teile erhalten...
ich hab nun einen schaltplan entwickelt.. aber ich weiß nicht genau, wie man fotos hochlädt... ich beschreib ihn einfach mal..
Wie empfohlen habe ich den bc337 transistor gewählt. an die basis kommt dann adc0(dazwischen einen 270 Ohm Widerstand)
an den Kollektor anschluß kommt dann meine Kanone. parallel zur kanone geht dann eine diode ab. und das ende geht dann an +ub also die gesamte batteriespannung. und emiter geht an masse, also gnd. geht das so? ich habe ja den Elko nun nicht benutzt.

Dirk
04.02.2011, 17:17
... klingt doch gut ...

Gruß Dirk

Morpheus1997
05.02.2011, 12:30
hm.., danke dirk :) aber muss ich denn noch den elko mit einbauen, so wie du es mir gesagt hast? oder geht es auch ohne?
und wenn ja, einfach gnd mit +ub mit dem elko verbinden, ja?

Dirk
05.02.2011, 13:07
... einfach gnd mit +ub mit dem elko verbinden, ja?
Ja, also Elko+ an +UB und Elko- (Markierung) an GND. Den Elko direkt in die Nähe der deiner Schaltung.

Zum Ausprobieren verbindest du am besten nur +UB und GND mit deiner Schaltung, aber noch nicht den 270 Ohm Widerstand mit dem ADC0 Pin.
Wenn du dann das offene Ende des 270 Ohm Widerstands kurz an +5V (VCC) hälst, müßte der Pfeil losfliegen.
Wenn das so klappt, müßte es auch mit einem Programm klappen, in dem man ADC0 z.B. für 300ms auf high setzt und dann wieder auf low.

Gruß Dirk

Morpheus1997
05.02.2011, 15:16
cool vielen dank!! ich probier es aus!!

Morpheus1997
06.02.2011, 18:15
so ich war heute 2stunden beim roboter und nun tuts... naja zumindest vom mechanischem her. ich stelle euch mein programm mit rein, falls es euch interessiert. das funktioniert nämlich so: ich habe als grundlage ersteinmal das beispielprogramm 'acs' genommen und immer wenn der linke bumper gedrückt wird, werden die pfeile geschoßen :

// Includes:

#include "RP6RobotBaseLib.h" // Always needs to be included!

/************************************************** ***************************/


/**
* This function works similar to the ACS function and gets called everytime the
* Bumpers are hit (the Bumpers need to be pressed down for at least 100ms to make
* sure that it is registered by the program!)
*/
void bumpersStateChanged(void)
{
writeString_P("Bumpers state changed! BPL: ");

if(bumper_left) // Left Bumper
{
writeChar('o');
schuss();

}
else
writeChar(' ');

writeString_P(" | BPR: ");

if(bumper_right) // Right Bumper
writeChar('o');
else
writeChar(' ');

writeChar('\n');
}

void schuss(void){
writeChar('s');
if(PORTA == 0)
PORTA = 1;
else
PORTA = 0;


}


/************************************************** ***************************/
// Main - The program starts here:

int main(void)
{
initRobotBase(); // Always call this first! The Processor will not work
// correctly otherwise.

// Write Message to UART:
writeString_P("\nRP6 ACS - Testprogram\n");
writeString_P("_____________________\n\n");

setLEDs(0b111111);
mSleep(1000);
setLEDs(0b001001);

// ---------------------------
// Register Event Handlers:

// Set Bumpers state changed event handler:
BUMPERS_setStateChangedHandler(bumpersStateChanged );

// ---------------------------

powerON(); // Activate all important Systems and turn power LED on.
// You always need to perform this command before you can
// use the ACS!
// Usually some of the RP6 Systems like the encoders, the ACS
// (and thus also IRCOMM reception),
// the current sensors and the power on LED are turned off to
// save Battery power (saves about 10mA).
// You can use powerOFF() to disable all those systems.

// ---------------------------

setACSPwrMed(); // Set ACS to medium power/range

// These are the __alternative__ settings:
// setACSPwrLow(); // Low power
// setACSPwrHigh(); // High Power
// and of course you can use:
// setACSPwrOff(); to turn it off completely!
// You can uncomment (= remove the "//" in front of a line) ONE of these
// lines and test how it affects the maximum range of the ACS and which
// Obstacles it can detect.

// ---------------------------

// selbst geschriebener Abschuss

DDRA = 1; // ADC0 auf Ausgang


// Main loop
while(true)
{
// This very very important function:
task_RP6System();
// handles a lot of things for you. For this example, it controls the
// ACS and sets the obstacle_right and obstacle_left values if it detects
// an obstacle. If you registered an event handler (s. above), it calls this
// event handler automatically as soon as one of these two values changes.
// Nearly the same applies for the bumpers - you can check the state
// of each bumper with bumper_left and bumper_right and everytime the
// state changes the event handler is called automatically.

// In some of the next examples you will see that this function also
// controls the motors and some motion functionality.

// But be careful with delay functions or other things that take a long
// time (gets problematic if there are delays greater than 50ms) if you
// use this! The delays may disturb the automatic control of all those
// systems mentioned above.

// Why do we need such a function?
// Well, several things that the MEGA32 needs to take care about are not
// that easy to understand (look at the task_ACS function
// and some of the other functions in the RP6RobotBaseLib.c!)
// and this makes it a lot easier for you!
// The only thing you really need to take care about is to call
// task_RP6System frequently! Then you will not have big problems usually.
}
return 0;
}


problem dabei ist immoment nur, dass wenn ich einmal den linken bumper drücke, dann schießt die kanone so lange, bis ich nochmal auf den linken bumper drücke. doch eigentlich soll es ja so sein, dass wenn man den bumper einmal berührt, dass er dann einen pfeil schießt. und wenn man ihn dann noch mal berührt, soll noch ein pfeil rausgeschoßen werden... wo liegt der fehler?

radbruch
06.02.2011, 18:38
Hallo

Prima. Allerdings sind deine Portmanipulationen nicht ganz korrekt:

DDRA |= 1; // ADC0 auf Ausgang, alle anderen Pins bleiben unbeeinflußt

Die Funktion schuss() würde ich rausschmeissen:


if(bumper_left) // Left Bumper
{
writeChar('o');
PORTA |= 1; //ADC0 high = Schuss
}
else
{
writeChar(' ');
PORTA &= ~1; // ADC0 low = Ende Schuss
}
Das schiesst solange du drückst.

Gibts schon ein Video?

Gruß

mic

Morpheus1997
06.02.2011, 19:11
hallo, radbruch,
wenn du willst, kann ich morgen gerne ein video machen,
doch zu dem programm nochmal,
könntest du das vielleicht mal versuchen in mein programm einzubinden?
bei mir kam da beim kompilieren ne fehlermeldung :(

radbruch
06.02.2011, 19:24
Mit den oben beschriebenen Änderungen kann ich dein Progamm so übersetzen:

// Includes:

#include "RP6RobotBaseLib.h" // Always needs to be included!

/************************************************** ***************************/


/**
* This function works similar to the ACS function and gets called everytime the
* Bumpers are hit (the Bumpers need to be pressed down for at least 100ms to make
* sure that it is registered by the program!)
*/
void bumpersStateChanged(void)
{
writeString_P("Bumpers state changed! BPL: ");

if(bumper_left) // Left Bumper
{
writeChar('o');
PORTA |= 1; //ADC0 high = Schuss
}
else
{
writeChar(' ');
PORTA &= ~1; // ADC0 low = Ende Schuss
}

writeString_P(" | BPR: ");

if(bumper_right) // Right Bumper
writeChar('o');
else
writeChar(' ');

writeChar('\n');
}

/************************************************** ***************************/
// Main - The program starts here:

int main(void)
{
initRobotBase(); // Always call this first! The Processor will not work
// correctly otherwise.

// Write Message to UART:
writeString_P("\nRP6 ACS - Testprogram\n");
writeString_P("_____________________\n\n");

setLEDs(0b111111);
mSleep(1000);
setLEDs(0b001001);

// ---------------------------
// Register Event Handlers:

// Set Bumpers state changed event handler:
BUMPERS_setStateChangedHandler(bumpersStateChanged );

// ---------------------------

powerON(); // Activate all important Systems and turn power LED on.
// You always need to perform this command before you can
// use the ACS!
// Usually some of the RP6 Systems like the encoders, the ACS
// (and thus also IRCOMM reception),
// the current sensors and the power on LED are turned off to
// save Battery power (saves about 10mA).
// You can use powerOFF() to disable all those systems.

// ---------------------------

setACSPwrMed(); // Set ACS to medium power/range

// These are the __alternative__ settings:
// setACSPwrLow(); // Low power
// setACSPwrHigh(); // High Power
// and of course you can use:
// setACSPwrOff(); to turn it off completely!
// You can uncomment (= remove the "//" in front of a line) ONE of these
// lines and test how it affects the maximum range of the ACS and which
// Obstacles it can detect.

// ---------------------------

// selbst geschriebener Abschuss

DDRA |= 1; // ADC0 auf Ausgang


// Main loop
while(true)
{
// This very very important function:
task_RP6System();
// handles a lot of things for you. For this example, it controls the
// ACS and sets the obstacle_right and obstacle_left values if it detects
// an obstacle. If you registered an event handler (s. above), it calls this
// event handler automatically as soon as one of these two values changes.
// Nearly the same applies for the bumpers - you can check the state
// of each bumper with bumper_left and bumper_right and everytime the
// state changes the event handler is called automatically.

// In some of the next examples you will see that this function also
// controls the motors and some motion functionality.

// But be careful with delay functions or other things that take a long
// time (gets problematic if there are delays greater than 50ms) if you
// use this! The delays may disturb the automatic control of all those
// systems mentioned above.

// Why do we need such a function?
// Well, several things that the MEGA32 needs to take care about are not
// that easy to understand (look at the task_ACS function
// and some of the other functions in the RP6RobotBaseLib.c!)
// and this makes it a lot easier for you!
// The only thing you really need to take care about is to call
// task_RP6System frequently! Then you will not have big problems usually.
}
return 0;
}


Videos sind immer klasse :)

Morpheus1997
06.02.2011, 19:27
bei mir kommt da dann beim kompilieren
> "make.exe" all

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 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.

make.exe: *** No rule to make target `RP6Base_ACS.elf', needed by `elf'. Stop.

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

Morpheus1997
08.02.2011, 15:05
hat dazu niemand eine lösung??

SlyD
08.02.2011, 15:10
Das liegt nicht an dem Quelltext!
Du hast was mit dem Makefile falsch gemacht (der Compiler sagt mit der Fehlermeldung das er nicht weiss was er tun soll).

MfG,
SlyD

Morpheus1997
08.02.2011, 16:33
hm.. ich hab noch nich so viel ahnung von c programmierung... wie kann ich das problem den beheben?

Morpheus1997
08.02.2011, 17:09
hm.. irgendiw versteh ich das generell nicht mit dem make all file und make clean file und make file.

Dirk
08.02.2011, 17:34
Z.B. hier:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=51109

Gruß Dirk

Morpheus1997
09.02.2011, 19:30
ähm, ich hab das so geändert, wie es in dem zeigebeitrag steht... nichts hat sich verändert :(
edit:
weiß niemand wo der fehler liegt??

Morpheus1997
13.03.2011, 13:22
naja, also es tut nun zwar, allerdings habe ich die kanone nun auf einen mini-servo von conrad gepackt, und ihn mit gnd, vdd und scl verbunden. ich habe keine erweiterungsplatine angeschlossen.doch wenn ich den servo dann mit dem tv-remote beispiel ansteuern wollte, dann hat er nicht geschossen, es lag wahrscheinlich daran, dass der cpu überlastet war! also mein programm(also davon der teil für den servo) sah so aus:
/**
* INIT SERVO
*
* Call this once before using the servo task.
*
*/
void initSERVO(void)
{
DDRC |= SERVO_OUT; // SERVO_OUT -> OUTPUT
PORTC &= ~SERVO_OUT; // SERVO_OUT -> LO
startStopwatch5(); // Needed for 20ms pulse repetition
}

/**
* PULSE SERVO
*
* This is the servo pulse generation. This function
* must be called every 20ms (pulse repetition).
*
* position = 0 : Left touch
* position = RIGHT_TOUCH : Right touch
*
* ATTENTION: ! This function is BLOCKING all other activities for about 1 !
* ! to 2ms (depending on the value of position)!!! !
* ! If you generate a pulse every 20ms 5-10% of the processor's !
* ! calculating time is wasted by this kind of pulse generation. !
* ! If this is a problem for the rest of your program, you !
* ! cannot use this method. !
* ! You will need an interrupt-based solution instead. !
*
*/
void pulseSERVO(uint8_t position)
{
cli();
PORTC |= SERVO_OUT; // SERVO_OUT -> HI (pulse start)
delayCycles(LEFT_TOUCH);
while (position--) {
delayCycles(PULSE_ADJUST);
}
PORTC &= ~SERVO_OUT; // SERVO_OUT -> LO (pulse end)
sei();
}

/**
* SERVO TASK
*
* This is the servo demo task.
* The positioning demo shows the servo lever rapidly
* moving to the left touch, then slowly moving to
* the right touch and so on ...
*
*/
void task_SERVO(void)
{
if (getStopwatch5() > PULSE_REPETITION) { // Pulse every ~20ms
pulseSERVO(pos); // Servo pulse [1..2ms]
// ---------------------------------------------------------------------
setStopwatch5(0);
}
}


vielen dank schon mal im vorraus !!

Dirk
13.03.2011, 19:12
@Morpheus1997:

Die geposteten Funktionen zur Servoansteuerung können so funktionieren.

Morpheus1997
14.03.2011, 16:09
hm... wenn es man tun würde!
soll ich euch einfach mal das ganze programm posten=?
mach ich einfach mal!

/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - ROBOT BASE EXAMPLES
* ************************************************** **************************
* Example: RP6 Remote Controlled
* Author(s): Dominik S. Herwald
* ************************************************** **************************
* Description:
*
* This demo program shows how to use a RC5 TV Remote Control to control your
* RP6 like a RC-Car.
* It also implements acceleration and deceleration functionality.
* (yes it is intentionally that the robot accelerates and decelerates so
* slow ;) Of course you can change this if you want!)
*
* First you need to get a Remote Control that transmits RC5 Code - like
* Conrad Promo8 or EuroSky Universal remote controls - which are very cheap
* --> about 10 Euro. Then you may need to try out some different codes - look
* at the manual of these remote controls how to change the transmit code!
*
* Attention: The codes listed in this sample program will not match even
* when you use the same remote control - it depends on specific protocol
* that it uses.
*
* You can test if the remote transmits RC5 code when you start this program
* and look at the Terminal output. If it receives a RC5 code, it will display
* the keycode, address and the toggle bit.
*
* MAKE SURE THAT THE RP6 CAN NOT MOVE,
* or uncomment the line #define DO_NOT_MOVE!
*
* As soon as this works, you can change the key mapping - look at your
* remote control and decide yourself which keys are best for move left/right,
* forwards/backwards, drive left/right curve fwd/bwd, only left/right motor
* forwards/backwards and stop.
* Typically there are some keys with ideal layout for this
* (usually intended for cursor movement and stuff like that)!
* Press them and look what their keycode is. Then enter the keyvalues in the
* source code - like in this example:
*
* #ifdef RC_YOUR_OWN // Standard Numbers on every Remote control
* #define RC5_KEY_LEFT 4
* #define RC5_KEY_RIGHT 6
* #define RC5_KEY_FORWARDS 2
* #define RC5_KEY_BACKWARDS 8
* #define RC5_KEY_STOP 5
* //...
* #endif
*
* Outcomment the #define RC_PROMO8
* like this: //#define RC_PROMO8
* and Uncomment //#define RC_YOUR_OWN
* like this: #define RC_YOUR_OWN
*
* Then recompile the program, upload it, start it again and test if
* the RP6 reacts when you press those keys on your remote control.
* You need to HOLD DOWN the key - then the RP6 will accelerate slowly to the
* MAX_SPEED values defined in this program. If you release the key again,
* it starts to deccelerate slowly.
* You can control the RP6 also with
* press key - release key - press key - release key - press key - release key
* ....
* This will result in a slower movement than just holding the key down
* continously.
*
* ************************************************** **************************
*/

/************************************************** ***************************/
// Includes:

#include "RP6RobotBaseLib.h"

/************************************************** ***************************/
/************************************************** ***************************/
static uint8_t schussAktiv = 0;
static uint8_t stopwatchgestartet = 0;

// If you only want to look at the RC5 Keycodes received from the Remote
// Control, uncomment this line:
//#define DO_NOT_MOVE
// The RP6 will not move then!



/************************************************** ***************************/
/************************************************** ***************************/
// Key Belegung
// müsste eigt erst weiter unten stehen, aber so kann ich sie bei dieser Switch
// schon mitbenutzen und muss sie nicht doppelt deifineren.
// RC Type: Phillips RC5 - Bp2
#define RC5_KEY_LINKS_ROT 60
#define RC5_KEY_RECHTS_ROT 42
#define RC5_KEY_VOR 32
#define RC5_KEY_RUECK 33
#define RC5_KEY_STOP 59
#define RC5_KEY_CURVE_LEFT 17
#define RC5_KEY_CURVE_RIGHT 16
#define RC5_KEY_SCHUSS 12
#define RC5_SERVO_LINKS 1
#define RC5_SERVO_RECHTS 2

//... you can add more Remote control keymappings or implement something
// better than this if you like...


void schuss(void)
{
if(stopwatchgestartet == 1 && PORTA==0) // Hier nochmal genau prüfen
setStopwatch3(0);
if(schussAktiv==1)
{
if(PORTA == 0)
PORTA = 1;
if(getStopwatch3()>30){
PORTA = 0;
schussAktiv = 0;
stopwatchgestartet = 0;

}

}

}





/************************************************** ***************************/
// Defines:

// RP6 Base Servo Connection:
#define SERVO_OUT SCL // PINC1 XBUS Pin 12

// Servo movement limits (depending on servo type):
#define LEFT_TOUCH 950 // Left servo touch
#define RIGHT_TOUCH 154 // Right servo touch [max. 255]
#define PULSE_ADJUST 4
#define PULSE_REPETITION 19 // Pulse repetition frequency
static uint8_t pos=100;


/************************************************** ***************************/
// Functions:

/**
* INIT SERVO
*
* Call this once before using the servo task.
*
*/
void initSERVO(void)
{
DDRC |= SERVO_OUT; // SERVO_OUT -> OUTPUT
PORTC &= ~SERVO_OUT; // SERVO_OUT -> LO
startStopwatch5(); // Needed for 20ms pulse repetition
}

/**
* PULSE SERVO
*
* This is the servo pulse generation. This function
* must be called every 20ms (pulse repetition).
*
* position = 0 : Left touch
* position = RIGHT_TOUCH : Right touch
*
* ATTENTION: ! This function is BLOCKING all other activities for about 1 !
* ! to 2ms (depending on the value of position)!!! !
* ! If you generate a pulse every 20ms 5-10% of the processor's !
* ! calculating time is wasted by this kind of pulse generation. !
* ! If this is a problem for the rest of your program, you !
* ! cannot use this method. !
* ! You will need an interrupt-based solution instead. !
*
*/
void pulseSERVO(uint8_t position)
{
cli();
PORTC |= SERVO_OUT; // SERVO_OUT -> HI (pulse start)
delayCycles(LEFT_TOUCH);
while (position--) {
delayCycles(PULSE_ADJUST);
}
PORTC &= ~SERVO_OUT; // SERVO_OUT -> LO (pulse end)
sei();
}

/**
* SERVO TASK
*
* This is the servo demo task.
* The positioning demo shows the servo lever rapidly
* moving to the left touch, then slowly moving to
* the right touch and so on ...
*
*/
void task_SERVO(void)
{
if (getStopwatch5() > PULSE_REPETITION) { // Pulse every ~20ms
pulseSERVO(pos); // Servo pulse [1..2ms]
// ---------------------------------------------------------------------
setStopwatch5(0);
}
}









/************************************************** ***************************/
// Speed values:

#define MAX_SPEED_MOVE 200
#define MAX_SPEED_TURN 100

#define MAX_SPEED_CURVE 120
#define MAX_SPEED_CURVE2 40
#define ACCELERATE_CURVE 10
#define ACCELERATE_CURVE2 4
#define DECELERATE_CURVE 4
#define DECELERATE_CURVE2 2

#define MAX_SPEED_1_MOTOR 120

#define ACCELERATE_VALUE 8
#define DECELERATE_VALUE 4

uint8_t max_speed_left; // Maximum speed variable left
uint8_t max_speed_right; // Maximum speed variable right
uint8_t acl_left;
uint8_t acl_right;
uint8_t decl_left;
uint8_t decl_right;

/************************************************** ***************************/

/**
* Just a small helper function to set speed params.
*/
void setDefaultSpeedParameters(void)
{
max_speed_left = MAX_SPEED_MOVE;
max_speed_right = max_speed_left;
acl_left = ACCELERATE_VALUE;
acl_right = ACCELERATE_VALUE;
decl_left = DECELERATE_VALUE;
decl_right = DECELERATE_VALUE;
uint16_t tmp = (getDesSpeedLeft() + getDesSpeedRight())/2;
moveAtSpeed(tmp , tmp);
}

/**
* RC5 Data reception handler - this function is called automatically from the
* RP6lib if new RC5 Data has been received.
*/
void receiveRC5Data(RC5data_t rc5data)
{
// Output the received data:
writeString_P("Toggle Bit:");
writeChar(rc5data.toggle_bit + '0');
writeString_P(" | Device Address:");
writeInteger(rc5data.device, DEC);
writeString_P(" | Key Code:");
writeInteger(rc5data.key_code, DEC);
writeChar('\n');


uint8_t movement_command = false; // used to store if we have received
// a movement command.
// Any other key is ignored!

// Check which key is pressed:
switch(rc5data.key_code)
{
case RC5_KEY_LINKS_ROT: // Turn left:
writeString_P("LEFT\n");
setDefaultSpeedParameters();
max_speed_left = MAX_SPEED_TURN;
max_speed_right = max_speed_left;
changeDirection(LEFT);
setLEDs(0b100000);
movement_command = true; // Store that we have received a movement command!
break;
case RC5_KEY_RECHTS_ROT: // Turn right:
writeString_P("RIGHT\n");
setDefaultSpeedParameters();
max_speed_left = MAX_SPEED_TURN;
max_speed_right = max_speed_left;
changeDirection(RIGHT);
setLEDs(0b000100);
movement_command = true;
break;
case RC5_KEY_VOR: // Move forwards
writeString_P("FORWARDS\n");
setDefaultSpeedParameters();
changeDirection(FWD);
setLEDs(0b100100);
movement_command = true;
break;
case RC5_KEY_RUECK: // Move backwards
writeString_P("BACKWARDS\n");
setDefaultSpeedParameters();
changeDirection(BWD);
setLEDs(0b001001);
movement_command = true;
break;
case RC5_KEY_STOP: // Stop!
writeString_P("STOP\n");
max_speed_left = 0;
max_speed_right = max_speed_left;
moveAtSpeed(0,0);
setLEDs(0b011011);
movement_command = true;
break;
case RC5_KEY_CURVE_LEFT: // Drive curve left - forwards
writeString_P("CURVE LEFT FWD\n");
max_speed_left = MAX_SPEED_CURVE2;
max_speed_right = MAX_SPEED_CURVE;
acl_left = ACCELERATE_CURVE2;
acl_right = ACCELERATE_CURVE;
decl_left = DECELERATE_CURVE2;
decl_right = DECELERATE_CURVE;
changeDirection(FWD);
setLEDs(0b110100);
movement_command = true;
break;
case RC5_KEY_CURVE_RIGHT: // Drive curve right - forwards
writeString_P("CURVE RIGHT FWD\n");
max_speed_left = MAX_SPEED_CURVE;
max_speed_right = MAX_SPEED_CURVE2;
acl_left = ACCELERATE_CURVE;
acl_right = ACCELERATE_CURVE2;
decl_left = DECELERATE_CURVE;
decl_right = DECELERATE_CURVE2;
changeDirection(FWD);
setLEDs(0b100110);
movement_command = true;
break;
case RC5_KEY_SCHUSS:
stopwatchgestartet = 1;
schussAktiv = 1;
break;

case RC5_SERVO_LINKS:
pos--;
if (pos < LEFT_TOUCH) {pos = 0;} // pos: 0..RIGHT_TOUCH

break;
case RC5_SERVO_RECHTS:
pos++;
if (pos > RIGHT_TOUCH) {pos = RIGHT_TOUCH;}
break;

}

if(movement_command) // Did we receive a move command?
{
// Accelerate if neccessary:
if(getDesSpeedLeft() < max_speed_left) // If we have not reached the left maximum speed...
{ // ... accelerate!
moveAtSpeed(getDesSpeedLeft()+acl_left, getDesSpeedRight());
if(getDesSpeedLeft() < 10)
moveAtSpeed(10, getDesSpeedRight());
}
if(getDesSpeedRight() < max_speed_right) // If we have not reached the right maximum speed...
{
// ... accelerate!
moveAtSpeed(getDesSpeedLeft(), getDesSpeedRight()+acl_right);
if(getDesSpeedRight() < 10)
moveAtSpeed(getDesSpeedLeft(), 10);
}

// Start Stopwatch 1 - it starts decceleration after 250ms of no RC5 reception! (s. below)
setStopwatch1(0);
startStopwatch1();
}


}


/************************************************** ***************************/

/**
* This function is called frequently out of the main loop and checks if
* Stopwatch1 has counted at least 250ms. If this is the case, decceleration is started
* and the Stopwatch is resetted and the progtam waits for next 250ms to pass by.
* Stopwatch1 ist set to 0 and started from the RC5 reception handler after
* each reception of a valid keycode. (s. above)
*/
void deccelerate(void)
{
if(getStopwatch1() > 250) // After 250ms with no reception...
{
if(getDesSpeedLeft() <= 10) // If left speed is less or equal than 10...
moveAtSpeed(0, getDesSpeedRight()); // ... stop the left motor
else // Otherwise continue to deccelerate:
moveAtSpeed(getDesSpeedLeft()-decl_left, getDesSpeedRight());

if(getDesSpeedRight() <= 10) // If right speed is less or equal than 10...
moveAtSpeed(getDesSpeedLeft(), 0); // ... stop the right motor
else // Otherwise continue to deccelerate:
moveAtSpeed(getDesSpeedLeft(), getDesSpeedRight()-decl_right);

if (getDesSpeedRight() == 0 && getDesSpeedLeft() == 0)
stopStopwatch1(); // Decceleration has finished!

max_speed_left = getDesSpeedLeft(); // Update max_speed value
max_speed_right = getDesSpeedRight(); // Update max_speed value
setLEDs(0b000000); // and clear LEDs
setStopwatch1(0);
}

// Make sure we don't move after Direction has changed and key is released too fast.
// This prevents the RP6 from moving when the direction has just changed and temporary saved
// speed value is written back again in the task_motionControl function.
if(getDesSpeedLeft() > max_speed_left)
{
if(getDesSpeedLeft() <= 10) // If left speed is less or equal than 10...
moveAtSpeed(0, getDesSpeedRight()); // ... stop the left motor
else // decelerate:
moveAtSpeed(getDesSpeedLeft()-decl_left, getDesSpeedRight());
}
if(getDesSpeedRight() > max_speed_right)
{
if(getDesSpeedRight() <= 10) // If right speed is less or equal than 10...
moveAtSpeed(getDesSpeedLeft(), 0); // ... stop the right motor
else // decelerate:
moveAtSpeed(getDesSpeedLeft(), getDesSpeedRight()-decl_right);
}
}

/************************************************** ***************************/
// Main - The program starts here:

int main(void)
{
initRobotBase();

setLEDs(0b111111);
writeChar('\n');
writeString_P("RP6 controlled by RC5 TV Remote\n");
writeString_P("___________________________\n");
mSleep(500);
setLEDs(0b000000);
powerON();

// Set the RC5 Receive Handler:
IRCOMM_setRC5DataReadyHandler(receiveRC5Data);


startStopwatch2();



// Für Schuss
startStopwatch3();
DDRA = 1; // ADC0 auf Ausgang

// Für Servo
initSERVO();
startStopwatch4(); // Used for the demo task

task_SERVO();
// Main loop
while(true)
{
deccelerate(); // Call the deceleration function.
task_RP6System(); // Motion Control tasks etc.
schuss();
//task_SERVO();

}
return 0;
}




edit:
wenn man dann mit der Fernbedienung eine Taste drückt, dann empfämgt der Roboter nicht immer die Signale im Terminal! Nur manchmal, also ganz sporalisch!
Deswegen gehe ich nämlich davon aus, dass der Cpu ausgelastet ist. Geht das dann denn gar nicht ohne die Erweiterungsplatine?

Mfg Morpheus

Morpheus1997
19.03.2011, 16:12
weiß wirklich niemand eine lösung???

RolfD
19.03.2011, 16:38
Tsss... Ich poste glaub ich heute echt auf jeden Beitrag... :)

Mach mal aus
//#define DO_NOT_MOVE

ein

#define DO_NOT_MOVE

und schau Dir an ob er damit besser empfängt. Damit schaltest Du die Motorsteuerung ab... und die Encoder irq usw...
Wenn es eine Lastfrage wäre, was ich sehr stark bezweifel, könnte es damit jedenfalls etwas besser gehen.

Die CPU ist immer zu 100% ausgelastet weil sie ständig im Kreis läuft. Nur kommt sie je nach "Last" unterschiedlich oft durch die Mainloop.
Wenn Du das genau wissen willst, schreib dir einfach was, das pro Sek ausgibt wie oft die mainloop durchlaufen wurde.
Denk aber dran ein uint16 oder Long zu verwenden... :) Ich würde schon auf paar tausend mal/sek tippen. :) Und später //#define DO_NOT_MOVE nicht vergessen... sonst wird sich kein Schuß lösen.

LG Rolf

Morpheus1997
20.03.2011, 16:28
hm.. wo denn?

Mach mal aus
//#define DO_NOT_MOVE

ein

#define DO_NOT_MOVE

und schau Dir an ob er damit besser empfängt. Damit schaltest Du die Motorsteuerung ab... und die Encoder irq usw...
Wenn es eine Lastfrage wäre, was ich sehr stark bezweifel, könnte es damit jedenfalls etwas besser gehen.

RolfD
20.03.2011, 23:03
hm.. wo denn?Auf dem Mond! :D

Mensch, in dem von Dir zuletzt geposteten Programm... Zeile 81 ...
Irgendwie irritiert mich deine Frage... du weist schon, das es im Editor eine Suchfunktion gibt, oder?
Stell Dir vor, die kann man auch benutzen...

LG Rolf

EDIT: Du denkst übrigends auch dran, das IR Empfänger Leuchtstofflampen und ähnliche pulsierende Lichtquellen nicht mögen?

Morpheus1997
23.03.2011, 18:39
bleib mal ruhig ;)
ich habs nu gefunden :) aber trotzdem löst dies nicht mein servo-problem!
kennt jemand vielleicht eine andere "servo-ansteuerungs-möglichkeit"=?

RolfD
24.03.2011, 08:28
bleib mal ruhig ;)
kennt jemand vielleicht eine andere "servo-ansteuerungs-möglichkeit"=?

Klar doch... du ahnst ausserdem nicht, wie ruhig ich bin *lach
http://tinyurl.com/4cqon3w

Morpheus1997
26.03.2011, 07:34
hm.. da hab ich schon geguckt, aber nix gescheites gefunden...:(