PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Servo Modelcraft Standard-Servo RS 2 an M32-Board



dirty_bird_981
05.01.2012, 16:02
Hallo alle zusammen!

Ich stehe vor einem Rätsel! Ich habe zwei Typen Servos gekauft:

- Modelcraft Standard-Servo RS 2 (Conrad-Nr. 233751 - 6)
- Modelcraft Mini-Servo ES-05 (Conrad-Nr. 230500 - 62)

Diese habe ich an die freien I/O-Pins des M32 angeschlossen. Die Mini-Servos (3 Stück) verrichten ihren Dienst auch 100%ig. Nur die Standard-Servos (3 Stück) zeigen keinerlei Funktion. Lediglich beim Einschalten zucken diese einmal kurz. Ich habe daraufhin beide Servotypen mal an einen meiner RC-Helis angeschlossen. Dort funktionieren ALLE. Ich habe die Standard-Servos dann mal durchgemessen ob diese evtl. zuviel Strom ziehen. Sie brauchen fast genauso viel wie die Minis.
Angeschlossen habe ich die Servos wie folgt:

Orange (Steuer-Signal): I/O-Port (z.B PC2) am Wannenstecker des M32
ROT (Versogungsspannung): +UB
Braun (Masse): GND

Ich kann einfach keinen Grund finden warum die Minis funktionieren und die Standard nicht. Hier im Forum habe ich auch an vielen Stellen gelesen das die Standard-Servos bei allen super laufen. Und, wie gesagt, die Minis machen ja bei mir auch keine Probleme. Einen Programmfehler kann ich eigentlich auch ausschließen da die Standard-Servos auch nicht funktionieren wenn ich sie an einen Port stecke wo vorher ein Mini dran war. Und das ich drei defekte Standard-Servos gekauft habe kann auch nicht sein, weil sie ja an dem Heli super funktionieren.

Kann mir bitte jemand weiterhelfen?

Vielen lieben Dank im Vorraus!

radbruch
05.01.2012, 16:55
Hallo

Das m32 hat wohl Probleme beim Versorgen von größeren Servo. Meist hilft eine eigene Stromquelle für die Servos. Möglicherweise hilft auch ein dicker Elko.

Gruß

mic

dirty_bird_981
05.01.2012, 17:04
Danke für die schnelle Antwort.

Ich habe aber schon von einigen gelesen die diese Servos erfolgreich am M32 betrieben haben. Ausserdem hole ich mir die Versorgungsspannung ja direkt von +UB. Das einzige was das M32 macht ist das Steuersignal geben. Wenn es heisst das das M32 Probleme mit größeren Servos hat, dann bezieht sich das doch auf die Leistung der Versorgungsspannung und nicht auf das Taktsignal. Ich meine, größere Servos benötigen doch eigentlich kein "stärkeres" Taktsignal, oder?

radbruch
05.01.2012, 17:09
Es bezieht sich auf die Stromaufnahme des Servos. Ich finde grad den richtigen Thread nicht. Beispiele mit ähnlichen Problemen:
https://www.roboternetz.de/community/threads/46023-!!!M32-stürzt-mit-Servo-ab!!!
https://www.roboternetz.de/community/threads/40567-RP6-Servo-Ansteuerung?p=389654&viewfull=1#post389654

Woher kommt eigentlich das +UB? Vom RP6 über die XBus-Steckverbindungen dreimal quer über die Platinen?

dirty_bird_981
05.01.2012, 17:13
Hmm, finde ich aber trotzdem nicht logisch, weil ich mir die Spannungsversorgung ja gar nicht vom M32 hole. Und meine Messungen haben ergeben das die Standard-Servos nicht wirklich mehr wie die Minis brauchen. Und abstürzen tut bei mir auch nichts, da ansonsten alles normal weiterläuft.

Dirk
05.01.2012, 17:14
Das Taktsignal dürfte nicht das Problem sein.
Du solltest aber die pos. Versorgungsspannung für die Servos nicht von +UB nehmen, weil hier bis zu 10V aus der Batterie liegen können.
Besser wäre ein Anschluß an VDD (+5V).
Auch dabei ist es besser, VDD z.B. von der Hauptplatine des RP6 (http://www.rn-wissen.de/index.php/RP6#VDD.2FGND.2F.2BUB_Anschlu.C3.9F) in der Nähe des Spannungsreglers zu nehmen.

dirty_bird_981
05.01.2012, 17:39
So, habe den Servo mal an die Anschlüsse auf der Hauptplatine neben C4 gehängt und das Taktsignal auf den I/O vom M32. Und, was soll ich sagen: keinerlei Funktion!

Dirk
05.01.2012, 17:56
Da gibts einige Möglichkeiten.
Check mal:
1. Servos sind (nach dem +UB-Anschluß) noch heile? Testen am Heli.
2. Ansteuerung der Servos? Software prüfen.
3. VDD/GND/Takt ohne Wackelkontakte verbunden?
4. Mini-Servos an VDD ok?
...

dirty_bird_981
05.01.2012, 18:02
zu 1.: Habe die vorhin kontrollehalber nochmal am Heli gehabt: Sind alle OK!
zu 2.: Da ich die I/O-Pins mit Stifleisten versehen habe kann ich die kleinen und großen Servo leicht wechseln und mit den kleinen überprüfe ich regelmäßig ob noch ein gültiges Taktsignal anliegt. Daher muss die SW eigentlich OK sein.
zu 3.: Ja
zu 4.: Auch ja

rolber
05.01.2012, 18:07
Hallo !

Ich kann mich noch erinnern, dass Hanno bei seinem Vinculum Projekt exakt die gleichen Probleme wie Du hatte.
Im Endeffekt lag es an der Spannungsversorgung durch sein Netzgerät.
Nachdem Er seinen Lipo angeschlossen hatte funktionierte alles Einwandfrei.

Roland

dirty_bird_981
05.01.2012, 18:22
Nur mal zur Sicherheit: Wie muss ich den LiPo denn anschließen?
LiPo-Minus an GND, LiPo Plus an Servo-Plus und Servo-Minus an GND?

rolber
05.01.2012, 18:38
Richtig !
Und falls Du noch eine andere Spannungsquelle für die Versorgung des M32 benutzt die Minus Leitungen miteinander verbinden.
Nur wirst Du keinen Lipo finden, den Du direkt an deine Servos anschliessen kannst.


Roland

dirty_bird_981
05.01.2012, 18:42
Habe ich gerade so gemacht mit dem LiPo. Auch kein Erfolg. Ich dreh' noch durch.

rolber
05.01.2012, 18:51
Ich habe genau die gleichen Servos für meine Kamerahalterung in Betrieb, von jedem eins.
Auch an einem Mega32 und es funktioniert einwandfrei.
Ich bin fast sicher, dass es an der Versorgungsspannung liegt.
Entweder Verkabelung oder Spannungseinbrüche.
Hast Du ein Oszi zur Hand?

Roland

dirty_bird_981
05.01.2012, 18:53
Nein, habe ich leider nicht.
Ich habe gerade mal anstatt des LiPos ein Netzteil drangehängt. Auch nichts.

rolber
05.01.2012, 19:09
Du sagst, die 3 Mini - Servos funktionieren einwandfrei !
Die 3 Grossen nicht, aber an deinem Heli tadellos !
Wenn Du alle Servos abziehst und nur ein Grosses dort ansteckst, wo sonst ein Mini - Servo war, funktioniert es dann ?
Probiere aber alle 3 Grossen einzeln aus, evtl. ist ja eins defekt .

Roland

dirty_bird_981
05.01.2012, 19:13
Ich habe die ganze Zeit schon zwischen einem kleinen und einem großen gewechselt. Also, ich hatte immer nur einen Servo am System. Habe dann den kleinen an dem Port angeschlossen um zu sehen ob wirklich ein Servo-Signal anliegt, habe dan den kleinen abgezogen und den großen dran gehängt (am selben Port). So habe ich das mit allen dreien gemacht und die Versorgungsspannung jeweils den Tipps entsprechend aufgebaut.

Nachtrag: Habe auch noch ein stärkeres Netzteil probiert (max 1,5 A). Auch keine Änderung!

SlyD
06.01.2012, 11:51
Hallo,

die Pins auf den Erweiterungsports sind standardmäßig alle als Eingang konfiguriert.
Bist Du Dir also sicher das die I/O Ports richtig konfiguriert sind und auch richtig schalten?
(Ausgang! Nicht nur einfach bei nem als Eingang konfigurierten Pin den Pullup hin und her schalten!)


Falls das OK ist, schalte mal einen der Pins langsam an und aus (mit 3 Sekunden pause dazwischen) und mess die Spannung mit einem Multimeter.
Häng dann auch mal eine LED über einen Widerstand (470 Ohm bis 2K Ohm) dran und schau ob die blinkt.

MfG,
SlyD

dirty_bird_981
06.01.2012, 12:53
Ich denke mal wenn die kleinen Servos an einem Port funktionieren dann ist dieser korrekt geschaltet. Aber zur Sicherheit hier trotzdem mal mein Code:

void ServoInit(void);
{
DDRC |= IO_PD6;
DDRC |= IO_PC4;
DDRC |= IO_PC6;

servo1_pos_d=12;
servo2_pos_d=5;
servo3_pos_d=22;
}

void servo(int servo_nr,int position, int speed)
{
switch (servo_nr)
{
case 1:
servo1_pos_d=position;
break;
case 2:
servo2_pos_d=position;
break;
case 3:
servo3_pos_d=position;
break;
}

}
------------------------------------------------

und dies steht in der Timer-ISR in der rp6controllib.c



if(servo_timer>servo1_pos_d) PORTD &= ~IO_PD6; else PORTD |= IO_PD6;
if(servo_timer>servo2_pos_d) PORTC &= ~IO_PC4; else PORTC |= IO_PC4;
if(servo_timer>servo3_pos_d) PORTC &= ~IO_PC6; else PORTC |= IO_PC6;

if(servo_timer<200) servo_timer++; else servo_timer=0;

radbruch
06.01.2012, 13:13
PD6 ist kein Ausgang:

DDRC |= IO_PD6;

Drehbereich von 0,5 bis 2,2 Millisekunden erscheint mir zuviel für ein RS2-Servo.

SlyD
06.01.2012, 13:15
... und bei
void ServoInit(void);

das Semikolon gehört da nicht hin - dürfte so eigentlich nicht fehlerfrei übersetzt werden.

dirty_bird_981
06.01.2012, 13:20
Ich habe das Beispiel aus der Anleitung genommen und umgeschrieben:

Zitat Anleitung: DDRC |= IO_PC7; // PC7 ist nun Ausgang

Und, wenn der Port kein Ausgang ist, dann sollten doch die kleinen Servos auch nicht funktionieren, oder? Im übrigen habe ich auch die anderen beiden Ports probiert: kleine OK, große nicht.


Nachtrag:

Habe es jetzt umgeschrieben in:

DDRC = IO_PD6 | IO_PC4 | IO_PC6;

jetzt tun die großen an PC4 und PC6, aber nicht an PD6. Warum nicht?

SlyD
06.01.2012, 13:23
PD6 ist kein Ausgang weil Du ins DDR--C Register schreibst und nicht ins DDR--D:

DDRC |= IO_PD6; // falsch,

DDRD |= IO_PD6; // korrekt


DDRC ist natürlich für den PortC gedacht.

SlyD
06.01.2012, 13:26
> Und, wenn der Port kein Ausgang ist, dann sollten doch die kleinen Servos auch nicht funktionieren, oder?

Je nach Servo Typ kann der Signaleingang auch signifikanten Strom ziehen - wenn der nur über den internen Pullup Widerstand geliefert wird reicht das manchmal aus, manchmal aber eben nicht.
(Eine 1 im PORTx Register schaltet den Pullup zu wenn der Pin als Eingang konfiguriert ist also DDRx 0 ist.)

radbruch
06.01.2012, 13:27
Na also, das passt doch. Wie von SlyD schon vermutet steuerst du die Servos mit Eingängen über die internen PullUps an. Bei analogen Servos wird aus dem Signal direkt die Motoransteuerung erzeugt und deshalb wird das Signal belastet. Vermutlich bricht das Signal bei den stärkeren RS2 zusammen:


void ServoInit(void)
{
DDRD |= IO_PD6;
DDRC |= IO_PC4;
DDRC |= IO_PC6;

servo1_pos_d=12;
servo2_pos_d=12;
servo3_pos_d=12;
}

Vermutlich ignoriert der Kompiler den Block nach dem ;

dirty_bird_981
06.01.2012, 13:30
Ach verd.....!

Was so ein einziger Buchstabe alles ausmachen kann! Ich habe es jetzt angepasst und...

ES FUNKTIONIERT!!!!! ALLE SERVOS LAUFEN JETZT!!! AN ALLEN DREI PINS! :)

SUPER!!!

Ich bedanke mich bei euch und allen anderen die mir geholfen haben das Problem einzukreisen und schließlich zu lösen! Herzlichsten Dank dafür!

Filou89
07.02.2012, 13:36
Hallo zusammen.
Ich weiss, das Thema ist eigentlich erledigt.
Ich habe genau das selbe Problem mit den selben Servos aber anderem Programm.
An meiner M32 Möchte ich am I/O Port ES-05 und RS-2 Servos betreiben.
Die ES-05 Miniservos funktionieren mittlerweile einwandfrei.
Wenn ich aber am selben Port einen RS-2 Servo anschliesse, resetet das Programm immer wieder.
Am Servo sollte es eigentlich nicht liegen, da der neu ist. Zudem habe ich einen 1000uF Kondensator an die Speisung kurz vor dem Servo angelötet.
Als ServoLib verwende ich die Lib von Dirk.
Woran könnte das liegen?
Ich hoffe, ihr könnt mir auch so super helfen.

Grüsse,
Filou

SlyD
07.02.2012, 15:20
> Ich hoffe, ihr könnt mir auch so super helfen.

Naja um Softwareprobleme zu lösen müsste man natürlich die Software sehen.

Wenn Du den Thread gelesen hast, siehst Du ja das ein falscher Buchstabe reicht...

MfG,
SlyD

Filou89
07.02.2012, 15:52
Okay dann hier alles, was es dazu braucht. Da ich vorher alles sorgfältig gelesen habe, kann ich keinen Fehler an einem falschen Buchstaben feststellen. Aber ich hab ja auch nur 2 Augen. =)

RP6ControlServoLib.h:


/* ************************************************** **************************
* _______________________
* \| RP6 ROBOT SYSTEM |/
* \_-_-_-_-_-_-_-_-_-_/ >>> RP6 CONTROL
* ----------------------------------------------------------------------------
* ------------------------ [c]2008 - Dirk ------------------------------------
* ************************************************** **************************
* File: RP6ControlServoLib.h
* Version: 1.0
* Target: RP6 CONTROL - ATMEGA32 @16.00MHz
* Author(s): Dirk
* ************************************************** **************************
* Description:
* This is the RP6ControlServoLib header file.
* You have to include this file, if you want to use the library
* RP6ControlServoLib.c in your own projects.
*
* ************************************************** **************************
* THE CHANGELOG CAN BE FOUND AT THE END OF THIS FILE!
* ************************************************** **************************
*/

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

#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!

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

// Servo constants:
#define SERVO1 0b00000001
#define SERVO2 0b00000010
#define SERVO3 0b00000100
#define SERVO4 0b00001000
#define SERVO5 0b00010000
#define SERVO6 0b00100000
#define SERVO7 0b01000000
#define SERVO8 0b10000000

// Servo movement limits (depending on servo type):
// Standard servos need an impulse every 20ms (50Hz). This impulse must have
// a length of 1ms (0.7 .. 1ms) to move the servo lever to the left touch
// and a length of 2ms (2 .. 2.3ms) for moving it to the right touch. In the
// middle position the servo needs an impulse length of 1.5ms (1.3 .. 1.6ms).
// If you want to modify the following constants for a certain servo type,
// you must adapt the LEFT_TOUCH constant first (values ~70 .. 100 = ~0.7 ..
// 1ms at 100kHz) by using a servo position value (servoX_position) of zero.
// After that you have two "screws" to adjust the servo movement limits:
// First you may change the RIGHT_TOUCH constant. If you choose a higher
// value than 255, you will use 16-bit values. Higher values mean a longer
// impulse length, but longer impulses than 2.3ms do not make sense.
// Second you may alter the Timer 1 frequency constant (F_TIMER1).
// A higher frequency leads to smaller steps of the servo movement. This of
// course reduces the impulse length and may be compensated again by a higher
// RIGHT_TOUCH constant. As a possible range of Timer 1 frequency values you
// may use 50kHz (20us) .. 105.263kHz (9.5us).
// HINT: If you alter F_TIMER1, you'll have to adapt LEFT_TOUCH and
// RIGHT_TOUCH again as you can see in the following table!
// Steps -> 9.5 10 12.5 15 17.5 20 [us]
// ------------------------------------------------------------------
// LEFT_TOUCH 74 71 57 47 41 35
// RIGHT_TOUCH 169 162 129 107 92 80
// F_TIMER1 105263 100000 80000 66667 57143 50000 [Hz]
#define LEFT_TOUCH 71//22 //ES-05: 22 alter miniservo: 32 // Left servo touch (~0.7ms)
#define RIGHT_TOUCH 162//220//ES-05_ 220 alter miniservo: 235 // Right servo touch (~2.3ms)
#define MIDDLE_POSITION (RIGHT_TOUCH / 2) // Middle position (~1.5ms)
#define PULSE_REPETITION 17 // Pulse repetition freq. (~50Hz)
#define F_TIMER1 100000 // Timer 1 frequency (100kHz)

// Servo ports:
#define SERVO1_PULSE_ON (PORTC |= IO_PC2) // PC2
#define SERVO1_PULSE_OFF (PORTC &= ~IO_PC2)
#define SERVO2_PULSE_ON (PORTC |= IO_PC3) // PC3
#define SERVO2_PULSE_OFF (PORTC &= ~IO_PC3)
#define SERVO3_PULSE_ON (PORTC |= IO_PC4) // PC4
#define SERVO3_PULSE_OFF (PORTC &= ~IO_PC4)
#define SERVO4_PULSE_ON (PORTC |= IO_PC5) // PC5
#define SERVO4_PULSE_OFF (PORTC &= ~IO_PC5)
#define SERVO5_PULSE_ON (PORTC |= IO_PC6) // PC6
#define SERVO5_PULSE_OFF (PORTC &= ~IO_PC6)
#define SERVO6_PULSE_ON (PORTC |= IO_PC7) // PC7
#define SERVO6_PULSE_OFF (PORTC &= ~IO_PC7)
#define SERVO7_PULSE_ON (PORTD |= IO_PD5) // PD5
#define SERVO7_PULSE_OFF (PORTD &= ~IO_PD5)
#define SERVO8_PULSE_ON (PORTD |= IO_PD6) // PD6
#define SERVO8_PULSE_OFF (PORTD &= ~IO_PD6)
// -----------------------------------------------------------
// Other possible ports for connecting servos to RP6Control:
//#define SERVOx_PULSE_ON (PORTA |= ADC6) // PA6
//#define SERVOx_PULSE_OFF (PORTA &= ~ADC6)
//#define SERVOx_PULSE_ON (PORTA |= ADC7) // PA7
//#define SERVOx_PULSE_OFF (PORTA &= ~ADC7)
// -----------------------------------------------------------

/************************************************** ***************************/
// Variables:

uint16_t servo1_position; // Servo 1 position [0..RIGHT_TOUCH]
uint16_t servo2_position; // Servo 2 position [0..RIGHT_TOUCH]
uint16_t servo3_position; // Servo 3 position [0..RIGHT_TOUCH]
uint16_t servo4_position; // Servo 4 position [0..RIGHT_TOUCH]
uint16_t servo5_position; // Servo 5 position [0..RIGHT_TOUCH]
uint16_t servo6_position; // Servo 6 position [0..RIGHT_TOUCH]
uint16_t servo7_position; // Servo 7 position [0..RIGHT_TOUCH]
uint16_t servo8_position; // Servo 8 position [0..RIGHT_TOUCH]

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

void initSERVO(uint8_t servos);
void startSERVO(void);
void stopSERVO(void);
void pulseSERVO(void);
void task_SERVO(void);

/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0 (initial release) 31.12.2008 by Dirk
*
* ************************************************** **************************
*/

/************************************************** ***************************/
// EOF

RP6ControlServoLib.c:


/* ************************************************** **************************
* _______________________
* \| RP6 ROBOT SYSTEM |/
* \_-_-_-_-_-_-_-_-_-_/ >>> RP6 CONTROL
* ----------------------------------------------------------------------------
* ------------------------ [c]2008 - Dirk ------------------------------------
* ************************************************** **************************
* File: RP6ControlServoLib.c
* Version: 1.0
* Target: RP6 CONTROL - ATMEGA32 @16.00MHz
* Author(s): Dirk
* ************************************************** **************************
* Description:
* This is my simple RP6 Control Servo Library for up to 8 Servos.
*
* COMMENT: It is a good idea to use a separate power supply for the servos!
*
* Servo connections:
* SERVO1 -> I/O Pin 7 (IO_PC2) SERVO5 -> I/O Pin 4 (IO_PC6)
* SERVO2 -> I/O Pin 5 (IO_PC3) SERVO6 -> I/O Pin 1 (IO_PC7)
* SERVO3 -> I/O Pin 6 (IO_PC4) SERVO7 -> I/O Pin 9 (IO_PD5)
* SERVO4 -> I/O Pin 3 (IO_PC5) SERVO8 -> I/O Pin 8 (IO_PD6)
*
* ************************************************** **************************
* ATTENTION: Stopwatch 8 is used for the servo task! Please do
* not use this stopwatch elsewhere in your program!
*
* ************************************************** **************************
* THE CHANGELOG CAN BE FOUND AT THE END OF THIS FILE!
* ************************************************** **************************
*/

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

#include "RP6ControlServoLib.h"

/************************************************** ***************************/
// Variables:

uint8_t usedservos;
uint8_t servo_on = FALSE;

uint16_t impulselength1 = 0;
uint16_t impulselength2 = 0;
uint16_t impulselength3 = 0;
uint16_t impulselength4 = 0;
uint16_t impulselength5 = 0;
uint16_t impulselength6 = 0;
uint16_t impulselength7 = 0;
uint16_t impulselength8 = 0;

volatile uint16_t intcounter = 0;

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

/**
* INIT SERVO
*
* Call this once before using the servo function.
* Timer 1 is configured to work in "Clear Timer On
* Compare Match Mode" (CTC). So no PWM is generated!
* The timer runs on a fixed frequency (100kHz).
*
* Input: servos -> Used servos
* Examples:
* - initSERVO(SERVO1 | SERVO2) -> Use only servos 1 and 2
* - initSERVO(SERVO1 | SERVO6) -> Use only servos 1 and 6
* - initSERVO(SERVO1 | SERVO2 | SERVO8) -> Use servos 1, 2 and 8
*
*/
void initSERVO(uint8_t servos)
{
usedservos = servos; // Save used servos
impulselength1 = 0;
impulselength2 = 0;
impulselength3 = 0;
impulselength4 = 0;
impulselength5 = 0;
impulselength6 = 0;
impulselength7 = 0;
impulselength8 = 0;
if (servos & SERVO1) {DDRC |= IO_PC2; PORTC &= ~IO_PC2;}
if (servos & SERVO2) {DDRC |= IO_PC3; PORTC &= ~IO_PC3;}
if (servos & SERVO3) {DDRC |= IO_PC4; PORTC &= ~IO_PC4;}
if (servos & SERVO4) {DDRC |= IO_PC5; PORTC &= ~IO_PC5;}
if (servos & SERVO5) {DDRC |= IO_PC6; PORTC &= ~IO_PC6;}
if (servos & SERVO6) {DDRC |= IO_PC7; PORTC &= ~IO_PC7;}
if (servos & SERVO7) {DDRD |= IO_PD5; PORTD &= ~IO_PD5;}
if (servos & SERVO8) {DDRD |= IO_PD6; PORTD &= ~IO_PD6;}
// -----------------------------------------------------------
// Other possible ports for connecting servos to RP6Control:
// if (servos & SERVOx) {DDRA |= ADC6; PORTA &= ~ADC6;}
// if (servos & SERVOx) {DDRA |= ADC7; PORTA &= ~ADC7;}
// -----------------------------------------------------------
cli();
// Timer 1: Normal port operation, mode 4 (CTC), clk/8
TCCR1A = (0 << COM1A1)
| (0 << COM1A0)
| (0 << COM1B1)
| (0 << COM1B0)
| (0 << FOC1A)
| (0 << FOC1B)
| (0 << WGM11)
| (0 << WGM10);
TCCR1B = (0 << ICNC1)
| (0 << ICES1)
| (0 << WGM13)
| (1 << WGM12)
| (0 << CS12)
| (1 << CS11)
| (0 << CS10);
OCR1A = ((F_CPU/8/F_TIMER1)-1); // 19 at 100kHz
// ------------------------------------------------------
// Possible OCR1A values (F_CPU = 16000000):
// OCR1A = 2000000 / F_TIMER1 - 1 // F_TIMER1 (Steps)
// OCR1A = 18; // 105263Hz (9.5us)
// OCR1A = 19; // 100000Hz (10us)
// OCR1A = 24; // 80000Hz (12.5us)
// OCR1A = 29; // 66667Hz (15us)
// OCR1A = 34; // 57143Hz (17.5us)
// OCR1A = 39; // 50000Hz (20us)
// ------------------------------------------------------
// Enable output compare A match interrupts:
startSERVO();
sei();
startStopwatch8(); // Needed for 20ms pulse repetition
}

/**
* START SERVO
*
* If the servo function was stopped with the
* function stopSERVO() before, it can be
* started again with this function.
*
*/
void startSERVO(void)
{
TIMSK |= (1 << OCIE1A);
servo_on = TRUE;
}

/**
* STOP SERVO
*
* The servo function uses a certain amount of the
* processor's calculating time. If the servos are
* not moving for a while, the Timer 1 interrupt
* can be stopped with this function.
*
*/
void stopSERVO(void)
{
TIMSK &= ~(1 << OCIE1A);
servo_on = FALSE;
}

/**
* 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
* position = MIDDLE_POSITION : Middle position
*
* ! Please make sure in your main program, that the !
* ! servo position values (servoX_position) don't !
* ! exceed RIGHT_TOUCH!!! !
*
* COMMENT: The pulses are only started here!
* The pulses end in the Timer 1 ISR!
*
*/
void pulseSERVO(void)
{
if (servo_on) {
intcounter = RIGHT_TOUCH; // Avoid interference of Timer 1 ISR!
// (Only necessary, if pulseSERVO() is called
// from outside of this library!)
if (usedservos & SERVO1) {
SERVO1_PULSE_ON; impulselength1 = LEFT_TOUCH + servo1_position;}
if (usedservos & SERVO2) {
SERVO2_PULSE_ON; impulselength2 = LEFT_TOUCH + servo2_position;}
if (usedservos & SERVO3) {
SERVO3_PULSE_ON; impulselength3 = LEFT_TOUCH + servo3_position;}
if (usedservos & SERVO4) {
SERVO4_PULSE_ON; impulselength4 = LEFT_TOUCH + servo4_position;}
if (usedservos & SERVO5) {
SERVO5_PULSE_ON; impulselength5 = LEFT_TOUCH + servo5_position;}
if (usedservos & SERVO6) {
SERVO6_PULSE_ON; impulselength6 = LEFT_TOUCH + servo6_position;}
if (usedservos & SERVO7) {
SERVO7_PULSE_ON; impulselength7 = LEFT_TOUCH + servo7_position;}
if (usedservos & SERVO8) {
SERVO8_PULSE_ON; impulselength8 = LEFT_TOUCH + servo8_position;}
intcounter = 0;
}
}

/**
* TIMER1 ISR
*
* In this ISR the servo pulses are finished, if the
* correct pulse length of each servo is reached.
*
*/
ISR (TIMER1_COMPA_vect)
{
intcounter++;
if (intcounter == impulselength1) {SERVO1_PULSE_OFF;}
if (intcounter == impulselength2) {SERVO2_PULSE_OFF;}
if (intcounter == impulselength3) {SERVO3_PULSE_OFF;}
if (intcounter == impulselength4) {SERVO4_PULSE_OFF;}
if (intcounter == impulselength5) {SERVO5_PULSE_OFF;}
if (intcounter == impulselength6) {SERVO6_PULSE_OFF;}
if (intcounter == impulselength7) {SERVO7_PULSE_OFF;}
if (intcounter == impulselength8) {SERVO8_PULSE_OFF;}
}

/**
* SERVO TASK
*
* This is the servo task. The task performes the pulse repetition
* with the help of a stopwatch.
* At the next call of the servo task (earliest about 3ms after the
* last servo pulse generation) the compare A match interrupt will
* be disabled to reduce the interrupt load. It will be enabled
* again after the next pulseSERVO() function call.
*
*/
void task_SERVO(void)
{
if (getStopwatch8() > 2) {TIMSK &= ~(1 << OCIE1A);}
if (getStopwatch8() > PULSE_REPETITION) { // Pulse every ~20ms
pulseSERVO(); // Servo pulse generation
if (servo_on) {TIMSK |= (1 << OCIE1A);}
setStopwatch8(0);
}
}

/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0 (initial release) 31.12.2008 by Dirk
*
* ************************************************** **************************
*/

/************************************************** ***************************/
// EOF


RP6Control_Servo.c:


// Uncommented Version of RP6ControlServo.c
// written by Dirk, modyfied by Filou
// ------------------------------------------------------------------------------------------
#include "RP6ControlServoLib.h"

uint16_t pos = LEFT_TOUCH;

int main(void)
{
initRP6Control();

initLCD();

showScreenLCD("################", "################");
mSleep(500);
showScreenLCD("<<RP6 Control>>", "<<LC - DISPLAY>>");
mSleep(500);
showScreenLCD(" Servo - Test 1 ", " Version 1.00 ");
mSleep(500);
clearLCD();

setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

initSERVO(SERVO1 | SERVO2);

startStopwatch2();
int turn=1;

while(true)
{
if (getStopwatch2() > 48)
{
servo1_position = pos;
servo2_position = pos;
setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(pos, DEC);
writeStringLCD_P(" ");
if(turn==0)
pos=pos-4;
if(turn==1)
pos=pos+4;
if (pos >= RIGHT_TOUCH && turn == 1)
turn= 0;
if (pos <= LEFT_TOUCH && turn == 0)
turn=1;
//pos=LEFT_TOUCH;
setStopwatch2(0);
}
task_SERVO();
mSleep(3);
}
return 0;
}


Ist da Tatsächlich nur ein Buchstabe falsch?

Grüsse Filou


Ist es möglich, dass der Port D mehr belastet werden kann als Port C ?? Wenn ich den Servo als Servo 8 am IO_PD6 anschliesse, stürtzt nichts mehr ab.

SlyD
07.02.2012, 16:19
Sieht OK aus!

Ich hatte aber deinen vorherigen Beitrag nicht genau genug gelesen weil du von "gleichem Problem" geredet hattest ;)
Sieht aber nach nem anderen Problem aus.


Wenn ich aber am selben Port einen RS-2 Servo anschliesse, resetet das Programm immer wieder.

--> Wenn der Controller nen Reset auslöst, solltest Du die Servos anders mit Strom versorgen.
Ich vermute Du hast das direkt am M32 angeschlossen - das ist NICHT für die Versorgung von großen Servomotoren ausgelegt.
Du musst die 5V möglichst nah vom 5V Spannungsregler abgreifen.
(XBUS2 Anschluss oder direkt an den VDD Lötpads neben dem Spannungsregler).

Btw. nur ein 1000µF Kondensator alleine muss nicht viel bringen - LC Filter ist angesagt also Spule --> Kondensator --> Servo.
(Spule in Serie, Kondensator parallel zum Servo --> Suchfunktion verwenden wurde schon oft diskutiert)


MfG,
SlyD