Hallo, habe mal wieder en kleines Problem und ich hoffe ihr könnt mir helfen! Ich will einen kleinen Servo mit einem Atmega8 ansteuern, was ja auch kein Problem ist. Nur fährt er die Sollposition viel zu schnell an, was für mein Projekt sehr ungünstig ist. Hab auch schon probiert die Sollposition in mehreren Schritten anzunähern, doch entweder er macht garnichts oder fährt normal zur Sollposition. Kann mir vielleicht jemand einen Tipp geben, wie man das richtig macht, also dass der Servo langsam eine Position anfährt. Achso ich habe alles in C Programmiert und kenne mich mit den anderen Sprachen nicht sonderlich gut aus. Vielen Dank schon mal an alle im Voraus! Gruß Patrick
du musst die strecke von der ist- zur sollposition in ausreichend viele schritte aufteilen (je nach gewünschter geschwindigkeit) und die dann der reihe nach anfahren und an jeder position kurz warten...
Patrick A. schrieb: > Hab auch schon probiert die Sollposition in mehreren Schritten > anzunähern, doch entweder er macht garnichts oder fährt normal zur > Sollposition. > > Kann mir vielleicht jemand einen Tipp geben, wie man das richtig macht, > also dass der Servo langsam eine Position anfährt. Genau so, wie du das versucht hast. Indem man das Servo in kleinen Schritten an die Zielposition führt. Wenn das immer noch zu schnell ist, dann müssen da eben noch mehr Zwischenschritte rein oder die zeitliche Distanz zwischen den Schritten vergrößert werden.
Hallo, habe noch mal etwas rum probiert aber es funktioniert immer noch nicht. Erst soll er von der Mittelstellung schnell(hier ist es ok wenn es schnell geht) nach links fahren und da bleiben. Soweit so gut und dann kommt das Problem: Von dort soll er dann langsam wieder nach rechts fahren und zu einem späteren zeitpunkt wieder nach links. Ich fasse mal kurz zusammen was er macht: Von links nach rechts>> er fährt schnell und brummt bis das Signal zu Ende ist. Von rechts nach links>> er brummt nur und bewegt sich garnicht. Ich füge mal den Code hier ein. Vielleicht sieht ja jemand den Fehler. a = 50; // Schnell nach links while (a>0) { PORTB |= (1<<PB2); _delay_us(2000); PORTB &=~(1<<PB2); _delay_ms(18); a--; } . . uint8_t b=60; // Langsam nach rechts uint8_t c=2000; uint8_t d; while (b>0) { d=0; PORTB |= (1<<PB2); while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); PORTB |= (1<<PB2); d=0; while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); PORTB |= (1<<PB2); d=0; while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); PORTB |= (1<<PB2); d=0; while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); b--; a=20; while (a>0) { a--; c--; } //c=c-20; . . . b=60; // Langsam wieder nach links c=800; while (b>0) { d=0; PORTB |= (1<<PB2); while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); PORTB |= (1<<PB2); d=0; while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); d=0; PORTB |= (1<<PB2); while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); d=0; PORTB |= (1<<PB2); while(d<c) { _delay_us(1); d++; } PORTB &=~(1<<PB2); _delay_ms(18); b--; a=20; while (a>0) { a--; c++; } } Viellen Dank noch mal!!! Gruß Patrick
so wird das nix. Mach dir mal eine Funktion die als Parameter die Microsekunden erwartet (integer). Dort setzt du den Portpin, wartest die übergebene Zeit, schaltest den Pin aus und wartest die 18 Milisekunden. Im Hauptprogramm rufst du diese Funktion mit den Werten von 1000 bis 2000 auf. Und dann überlegst du dir wie oft und mit welchen Werten du die Funktion aufrufst. Besser wäre das mit Timer, aber soweit bist du noch nicht. Holger
Hallo Holger W. schrieb: > Besser wäre das mit Timer, aber soweit bist du noch nicht. Der M8 hat einen 16 Bit timer, mit welchem du ganz easy einen Servo ansteuern kannst. Dafür reichen sogar 8 Bit. Dazu ein PWM Signal erzeugen, hab das auch schon mit einem Tiny13 gemacht. Ich würde den 1. Timer dazu verwenden alle viertel Sekunde den Servostand um x Grad zu verschieben, den 8 Bit Timer für die PWM. Es gibt zig Beispiele im Netz dazu. Nettes Pdf: http://mil.ufl.edu/5666/handouts/ATMPWM.pdf Tm
Hallo, meintest du das mit der Funktion so oder habe ich da was falsch verstanden? void servo(uint8_t warten) { PORTB |=(1<<PB2); _delay_us(warten); PORTB &=~(1<<PB2); _delay_ms(18); } im Hauptprogramm dann: Von 2000 nach 800 a=60; b=2000; while (a>0) { servo(b); b=b-20; a--; } Gruß Patrick
so in der Art, aber uint8_t ist nur 8 Bit, hier also einen 16 Bit verwenden. Holger
OK Vielen Dank Hab nur noch das Problem, dass der Compiler merkert, dass bei _delay(warten) keine Variable verwendet werden könnte. Wie kann ich das Umgehen? Gruß Patrick
Dann warte in einer Scheife den übergebenen Wert 1 Microsekunde lang. Der Lösungsansatz insgesamt ist nicht sehr schön, aber um einen Servo zu bewegen und zu verstehen wie das geht, schon ok. Holger
Holger W. schrieb: > Dann warte in einer Scheife den übergebenen Wert 1 Microsekunde lang. > Der Lösungsansatz insgesamt ist nicht sehr schön, aber um einen Servo zu > bewegen und zu verstehen wie das geht, schon ok. Nicht wirklich, denn die Wartezeiten sind dann völlig daneben. Bei 1 Mhz Prozessortakt wäre eine Mikrosekunde genau einen Taktzyklus lang. Ich weiß jetzt nicht, ob _delay_us inzwischen überhaupt so eine kurze Wartezeit machen kann, aber die Schleife braucht für sich selbst noch zusätzlich mehrere Taktzyklen, also sind die tatsächlichen Wartezeiten ein Vielfaches von der angegebenen.
Holger W. schrieb: > Besser wäre das mit Timer, aber soweit bist du noch nicht. @Patrick Das wär die beste Lösung. Daher solltest du da reinbeissen. Servoansteuerung, bei der man sowohl das Pulssignal als auch Verfahrzeiten im Auge behalten muss, machen keinen Spass. Die Pulserzeugung muss von alleine ablaufen und von den Verfahrzeiten und Wegen gestrennt sein. Alles andere bedeutet Aufwand ohne Ende
Rolf Magnus schrieb: > Holger W. schrieb: >> Dann warte in einer Scheife den übergebenen Wert 1 Microsekunde lang. >> Der Lösungsansatz insgesamt ist nicht sehr schön, aber um einen Servo zu >> bewegen und zu verstehen wie das geht, schon ok. > > Nicht wirklich, denn die Wartezeiten sind dann völlig daneben. Bei 1 Mhz > Prozessortakt wäre eine Mikrosekunde genau einen Taktzyklus lang. Ich > weiß jetzt nicht, ob _delay_us inzwischen überhaupt so eine kurze > Wartezeit machen kann, aber die Schleife braucht für sich selbst noch > zusätzlich mehrere Taktzyklen, also sind die tatsächlichen Wartezeiten > ein Vielfaches von der angegebenen. Ein Modellservo mit einer Auflösung von 1µs anzusteuern ist schon gewagt. Sowas geht natürlich wunderbar mit der o.g. Methode, dass ein Timer mit der OnCapture-Einheit verwendet wird, dem man alle paar ms einen neuen Vergleiswert vorgibt. Wenn man unbedingt Delay-Konstrukte verwenden will, sollte eine Auflösung von 10µs ausreichen. Dann kann man auch das ganz einfach in geschachtelten Schleifen realisieren: Pseudocode: setze Endmarke setze Impulsmarke wiederhole bis Impulsmarke = Endmarke: { setze Pulsdauer auf 0 wiederhole bis Pulsdauer = Impulsendmarke erreicht: { warte 10µs inkrementiere Pulsdauer } wiederhole bis Pulsdauer = 20ms erreicht: { warte 10µs inkremtieren Pulsdauer } setze Impulsmarke auf neuen Wert } Das Setzen der der Pulsdauer kann durch Inkrementieren oder Dekrementier erfolgen. Je nachdem, in welche Richtung gedreht werden soll.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.