PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Servo hat das große Zittern



IgelIgel
31.01.2009, 02:12
Hallo zusammen,

mein Servo hat das große Zittern:

Ich versuche ihn über das Control M32 Board des RP6 anzusteuern. Dabei verwende ich die Standard PWM Betriebsart des Timers 1 und der Servo liegt mit seiner Steuerleitung an PIND5.

Das Problem:
Der Servo dreht zwar wie befohlen, zittert aber mächtig.
Kann ich ihm das Zittern abgewöhnen ?

Viele Grüße

Igeligel




Hier mein Code:



#include "RP6ControlLib.h"

void initServo(void)
{
DDRD |= (1 << PD5); // define PIND5 as output
TCCR1B |= (1 << CS12); // systemclock :256
TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM11); // 9bit PWM-mode
OCR1A = 26; // set compare value
sei(); // enable interrupts
}


int main(void)
{
uint8_t counter=0;

initRP6Control();
initServo();

startStopwatch1(); // Stopwatch1 starten!

while(true)
{
// Check if a key is pressed:
uint8_t key = getPressedKeyNumber();

// If button 1 is pressed => turn servo to the right
if (key==1 || ch=='u') {
OCR1A++;
setStopwatch1(0);
while(getStopwatch1() < 200) {
counter++;
}
}

// If button 2 is pressed => turn servo to the left
if (key==2 || ch=='d') {
OCR1A--;
setStopwatch1(0);
while(getStopwatch1() < 200) {
counter++;
}
}


// If no button is pressed => do nothing
if (key==0) {
}
}
}

Dirk
31.01.2009, 08:52
Hallo IgelIgel,

so kann das nicht gehen.
Aber es gibt genau für deinen Ansatz (Servo-Ansteuerung an PIND5 mit PWM) eine fertige Version für die RP6Control M32 hier ...:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=34407
Such mal in dem Thread nach der Datei RP6Control_Servo2.zip (8.10.07)!

Gruß Dirk

IgelIgel
31.01.2009, 13:22
Hallo Dirk,

Danke für die schnelle Antwort und den Link.

Nachdem mein Code den Servo so erzittern ließ, hatte ich Deinen Code ebenfalls schon ausprobiert.

Gleiches Ergebnis: ebenfalls viel Zittern und Gewackel.

Du schreibst "so kann das nicht gehen".
Warum kann das so nicht gehen ?
Was ist grundsätzlich falsch an meinem Code ?

Viele Grüße
Igeligel

radbruch
31.01.2009, 13:52
Hallo

Ich dachte immer die Hardware-PWM würde bei Servos nicht funktionieren. Offensichtlich lag ich da falsch:

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

Allerdings ist mit dieser Technik die Anzahl der Servos durch die vorhandenen (und sonst nicht genutzten) PWM-Timer beschränkt. Oder liege ich da auch falsch? Eine echte Alternative scheint mir da nur die Verwendung eines Counters der die Impulse für mehrere Servos nacheinander erzeugt. Nacheinander ist auch zur Verringerung der Anlaufströme (Gleichzeitigkeitsfaktor) sinnvoll.

Gruß

mic

IgelIgel
31.01.2009, 14:49
Hallo Radbruch,

Danke für die Mühen und den Link.
Ich verstehe nur den Zusammenhang zu meinem "Zitterservo" nicht.
Sollte ich diesen anderen Code ebenfalls ausprobieren ?

Viele Grüße
Igeligel

IgelIgel
31.01.2009, 14:52
Hi Leute,

soeben schaut mir mein Sohn (7 Jahre) über die Schulter (je länger er mir zuschaut, desto weniger muß er Mathe machen ...) und hat die Lösung des Problems:

Papa, der Servo zittert so, weil er sich so anstrengen muß.

Viele Grüße

Igeligel

Dirk
31.01.2009, 14:59
Nachdem mein Code den Servo so erzittern ließ, hatte ich Deinen Code ebenfalls schon ausprobiert. Gleiches Ergebnis: ebenfalls viel Zittern und Gewackel.
Also, bei mir zittert oder wackelt nichts.
Was ich mir vorstellen kann:
Wenn die beiden Anschlagswerte (LEFT_TOUCH und RIGHT_TOUCH) nicht auf dein Servo abgestimmt sind, dann gibt es in beiden Endstellungen ein "Brummen". Das liegt daran, dass das Servo gegen seinen Anschlag arbeitet.

Das kann man in meinem Programm einfach durch Anpassen der beiden Konstanten verhindern: Danach gibt es das Brummen oder Zittern nicht mehr und der Drehbereich des Servos ist richtig eingestellt.
Also: Dein Sohn hat Recht! Das Servo strengt sich an, weil seine Bewegungsgrenzen noch nicht abgeglichen sind.

Gruß Dirk

IgelIgel
31.01.2009, 20:06
Hallo Dirk,

ein Zittern im Rechts-/Links-Anschlagbereich wäre zu erklären.

Der Servo zuckt aber auch auf seiner Fahrt von rechts nach links (z.B. wenn ich Dein Testprogramm laufen lasse).

Ich glaube, ich werde ihn mal an mein myAVR MK1 Board mit einem ATmega8 hängen und schauen, was dann passiert.

Viele Grüße

Igeligel

Dirk
31.01.2009, 20:39
Hallo IgelIgel,

Der Servo zuckt aber auch auf seiner Fahrt von rechts nach links (z.B. wenn ich Dein Testprogramm laufen lasse).
Ok, ich werde auch noch mal einen Testlauf machen, das Oszi dranhalten und wieder berichten ...

Gruß Dirk

Dirk
31.01.2009, 22:38
Hallo IgelIgel,

so, ich habe die Anschlagswerte auf die Norm (1ms..2ms Impuls) gesetzt:
#define LEFT_TOUCH 1000 // Left servo touch (~1.0ms)
#define RIGHT_TOUCH 1000 // Right servo touch (~2.0ms)

... und die task auf die Schnelle so verändert, dass sich das Servo ganz langsam auf seine 3 Hauptpositionen (Links/Mitte/Rechts) bewegen kann:

void task_SERVO(void)
{static uint8_t pos;
// -----------------------------------------------------------------------
// Your test code for positioning the servo here:
if (getStopwatch1() > 5000) { // Change position every ~5s
if (pos == 0) {
while (position > 1) {
position -= 2;
setSERVO(position);
setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(position, DEC);
writeStringLCD_P(" ");
mSleep(10);
}
} // Position of servo
if (pos == 1) {
while (position < MIDDLE_POSITION) {
position += 2;
setSERVO(position);
setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(position, DEC);
writeStringLCD_P(" ");
mSleep(10);
}
}
if (pos == 2) {
while (position < RIGHT_TOUCH) {
position += 2;
setSERVO(position);
setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(position, DEC);
writeStringLCD_P(" ");
mSleep(10);
}
}
if (pos == 3) {
while (position > MIDDLE_POSITION) {
position -= 2;
setSERVO(position);
setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(position, DEC);
writeStringLCD_P(" ");
mSleep(10);
}
}

pos++;
if (pos > 3) {pos = 0;}
setStopwatch1(0);
}
// -----------------------------------------------------------------------
}
Ergebnis:
Das Servo bewegt sich ganz ruhig von links nach rechts und umgekehrt. Laut Oszi liegt der Impuls zwischen 1 und 2 ms, also ok.

Wie ist das bei dir? Reagiert das Servo irgendwie merkwürdig?

Gruß Dirk

andieh
01.02.2009, 02:04
Hi Leute!

Ich benutze auch die ServoLib und mit der funktioniert einfach alles einwandfrei.
Hab aber vorher auch ewig rumgetüftelt und mir die Haare ausgerissen, weil mein Servo einfach nichts gemacht hab. Bis dann einfach nen neuen gekauft hab und siehe da, der lief wunderbar auf Anhieb.

IgelIgel
01.02.2009, 02:25
Hallo Leute,

ganz großes Dankeschön für Eure Mühen (insbesondere an Dirk, der extra seinen Code nochmals mit Oszi getestet hat).

Habe inzwischen den Servo an mein myAVR MK1 Board angeschlossen.
Das Ergebnis: auch dort gibt's das große Zittern.

Ich glaub' ich kaufe mir einen neuen Servo bevor ich noch mehr Zeit investiere. Irgendwie doof.

Trotzdem ein dickes Dankeschön für Eure Mühen.

Igeligel


PS: hier der PWM-Code des myAVR MK1 Boards für die Nachwelt. (beachte: ATmega32 führt OC1A an PortD5 heraus während ATmega8 OC1A an PortB1 herausführt)



/*

Description: ATmega8 uses Timer1 in PWM-Mode to control servo
Code runs on myAVR MK1 Development Board (SP2) NOT on RP6

Usage: By default you get a 1ms/20ms PWM-signal on Port PB1
Use pushbutton "Taster1" to enlarge the 1ms-signalshoulder
Use pushbutton "Taster2" to shrink the 1ms-signalshoulder

Wires: PD6 -> Taster2
PD7 -> Taster1

Lo -> Servo (black)
Hi -> Servo (red)
PB1 -> Servo (orange)
PC0 -> LED (green)
PC1 -> LED (yellow)

Date: 01.02.2009
Author: Igel
Reference: http://www.mikrocontroller.net/topic/103629

*/


// Takt
#define F_CPU 3686400UL


#include <avr/io.h>
#include <util/delay.h>


void initServo(void) {
// init timer 1:
//ICR1 = 7200; // PWM cycle time in usec
ICR1 = 9216; // PWM cycle time in usec
TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11); // OC1A/B clr on match, set on TOP
//TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS12) | (1<<CS10); // TOP = ICR1, clk = sysclk/8 (->1us)
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11) | (1<<CS11); // TOP = ICR1, clk = sysclk/8 (->1us)
TCNT1 = 0; // reset Timer

OCR1A = 461; // set Servo 1 to 1ms-position

}


int main(void) {

DDRD &= ~((1 << PD6) | (1 << PD7)); /* PIN PD6 + PD7 auf Eingang (Taster) */
PORTD |= (1 << PD6) | (1 << PD7); /* Pullup-Widerstand aktivieren */

DDRC |= (1 << PC0) | (1 << PC1); /* PIN PC0 + PC1 als Ausgang (LED) */

DDRB = (1 << PB1) | (1 << PB2); // OC1A and OC1B for PWM
initServo();

while(1) {
if(PIND & ( 1 << PD6 )) {
PORTC &= ~(1 << PC0); }
else {
PORTC |= (1 << PC0);
OCR1A -= 10;
_delay_ms(200);
}
if(PIND & ( 1 << PD7 )) {
PORTC &= ~(1 << PC1); }
else {
PORTC |= (1 << PC1);
OCR1A += 10;
_delay_ms(200);
}
}
return(0);
}

Manf
01.02.2009, 07:23
Wenn Du noch einen größeren Elko zur Verfügung hast (4700µF oder je nach Vorrat), schließe ihn doch mal zum Test an die Versorgugsspannung des Servos an, wenn es hilft weiß man dann etwas mehr wenn nicht dann eben nicht.

IgelIgel
01.02.2009, 19:37
Hi Manf,

Danke für die verzweifelten Versuche, mir zu helfen - ich weiß Eure Hilfsbereitschaft sehr zu schätzen.

Ich hatte den empfohlenen großen Elko nicht parat. Ein 220uF brachte keiner Veränderung.

Bitte müht Euch jedoch nicht weiter ab. Meine Diagnose lautet "Schrott" und ich werde mir einen Ersatzservo besorgen. Weitere Mühen - von mir oder von Euch - stehen nicht mehr im Verhältnis zu den 5,- EUR, die solch ein Tierchen kostet.

Ihr hört von mir an dieser Stelle, wenn der neue Servo eingetroffen und getestet ist.

Viele Grüße

Igeligel

Manf
01.02.2009, 21:17
Du hast völlig recht, zur Lösung Deiner Aufgabe ist ein Servo der leicht im Betrieb genommen werden kann sicher das beste.

Ein Bisschen geht es mir noch darum, ob man ein Heilmittel für irgendwelche Macken von Billigservos finden kann.

Wenn besipielsweise ein solcher Servo immer, oder eben in diesem Fall wieder einmal, mit einem großen Elko zu beruhigen ist, dann wüßte man weigstens für welchen Preis man so eine Billigversion doch in Betrieb nehmen kann, oder was sich der Hersteller dabei gedacht hat, der ja auch nicht riskieren will beliebig viele zurükzunehmen.

Wirf ihn mal erst nicht weg.

IgelIgel
25.02.2009, 09:03
Hallo Leute,

nur um diesen Thread auch sauber zu Ende zu bringen, möchte ich Euch noch berichten, wie die Geschichte ausging:

Das Ende der Story ist dabei eher profan: Ich bin in den nächstbesten Spielzeugladen marschiert, habe mir für 8,99 EUR den billigsten dort verfügbaren Servo gekauft und ihn an mein myAVR-Entwicklungsboard angeschlossen.

Ergebnis: der neue Servo funktionierte direkt vom Start weg. Das "große Zittern" lag also eindeutig an einem Defekt im alten Servo - da half auch kein Elko oder sonstiges gutes Zureden.

Vielen Dank an dieser Stelle nochmals für Eure Unterstützung und Eure Mühen

Igeligel

vohopri
25.02.2009, 10:55
Hallo,

nur zur Ergänzung für zukünftige Leser.

Schon öfter habe ich die Billigservos zur Mitarbeit überreden können, in dem ich ihnen einen 10nF Kondensator parallel zu Eingang spendiert habe.

In den Schaltungen, wo das notwendig war, war das ein ganz zuverlässig beobachtbarer und mit anderen Servos des selben Typs wiederholbarer Effekt.

grüsse,
Hannes

aircode
02.06.2009, 01:18
@Hannes oder alle die das sonst noch wissen...

Hab anscheinend ebenfalls Billig-Servos. Der eine zittert ziemlich stark und der andere zittert immerhin noch ein wenig... auch ohne Last und in Mittelstellung (1,5ms - Flanke). Sind übrigens die Dinger von Conrad -> RS-2...

Bevor ich mir aber andere kaufe würd ich gern diese mithilfe des 10nF Kondensators mal zur Vernuft bringen... rein aus Interesse...

Wo soll ich den 10nF parallel schalten? Eingang und wo noch? Plus oder Minus?

Danke...

vohopri
02.06.2009, 08:37
Hallo air,

mit "parallel zum Eingang" ist natürlich gemeint: zwischen Signalleitung und Masseleitung.

Vorher solltest du aber getrennte Stromversorgung versuchen Die häufigste Fehlerquelle ist unsaubere Spannungsversorgung: Innenwiderstand passt nicht, irgendwo fehlt einer der Kondensatoren der Spikes schlucken soll, Ungünstige Leitungsführung, schlechter Kontakt usw.

grüsse,
Hannes

aircode
02.06.2009, 20:39
Danke einmal für deine Antwort...

Die Spannungsquelle sollte ja eigentlich sauber sein, da sie ja am Spannungsregler des RP6 hängt... Werde ich aber trotzdem mal mit externer U-Quelle testen.

Zu dem Kondensator noch ne Frage: Was passiert da eigentlich elektrisch gesehen? Ohne Kondensator sollte ich ja am Signaleingang ein "schönes" Rechtecksignal anliegen. Wenn aber der Kondensator dazu kommt, dann würde doch das Rechtecksignal geglättet werden, oder? Warum also hilft ein 10nF am Signaleingang des Servos?

Werd mir mal ein Oszi zulegen um meine Fragen selber beantworten zu können :-k

MfG Air

vohopri
02.06.2009, 21:35
Hallo air,

wenn man auf der Fehlersuche ist, muss man seine Überzeugungen vorrübergehend ablegen, denn die Überzeugungen haben einem ja den Fehler eingehandelt. Soll heissen: egal ob du meinst, dass die Spannungsquelle sauber ist, trenne testweise die Versorgungen. Eine Flachbatterie fürs Servo reicht schon zum Testen.

Dann klammerst du schon wieder die Frage der Spikeschlucker aus: Ist jeder IC mit einem ausreichenden Kondensator an der Versorgungsspannung augestattet? Ist keiner der Kondensatoren kaputt? Ist die Leiterbahnenführung und Verkabelung perfekt? Alle Motoren entstört? Immer erst die einfachen Massnahmen ergreifen.

Der 10 nf glättet kein Servosignal, schluckt aber einzelne Störimpulse, die kapazitiv oder induktiv eingekoppelt werden. Das ist meine Erklärung dafür. Mit meinem Softwareoszi kann ich das messtechnisch nicht nachvollziehen. Aber die Tests sind eindeutig: Manche Servos brauchen das, dann gehts perfekt, nimmst du die Kondensatoren weg, dann spinnen sie wieder. Hat nicht nur in einer Schaltung mit einem Servo so funktioniert, sondern in mehreren Schaltungen und bei mehreren Servos.

Wenn die Ursache aber in einer überlasteten oder unsauberen Versorgungsspannung liegt, dann wird dir der 10 nf Kondensator auch nicht helfen.

grüsse,
Hannes