-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Servo-Steuerung

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    09.11.2006
    Ort
    Hamburg
    Alter
    32
    Beiträge
    199

    Servo-Steuerung

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Moin!
    Ich habe mir an meinen Roboter letztens einen Servo gebaut. Das Problem was ich jetzt hab ist die ansteuerung. Erstmal stellt sich mir die Frage ob ich den direkt an mit dem Taktanschluß an meinen uC schließen kann, aber denke schon, oder?

    Die Programmierung hab ich folgendermaßen gemacht:
    Code:
    //-----PWM-Inizialisierung-----
    DDRD |= (1<<PWM_ServoPort);
    TCCR2 |= ((1<<WGM20) | (1<<WGM21)); //Fast PWM
    TCCR2 |= (1<<COM1); //Clear OC0 on Compare Match, Set OC0 on Top
    TCCR2 |= ((1<<CS00) | (1<<CS02)); // CLK/1024 = 15625Hz (15625p/s), 1p=64µs
    dann muss ich mir ja jetzt irgendwie ausrechen wo ich diesen OCR2 setzen muss, damit ich 1-2ms impulse bekomme. Die Periodenlänge am ausgang bleibt ja immer 64µs, bloß Tein und Taus sind ja unterschiedlich. Irgendwie steh ich jetzt aufm Schlauch. Geht die PWM-Methode vielleicht gar nicht? Gibts bessere Möglichkeiten? Würde mich über Vorschläge echt freuen!

    MfG Jan
    Habe Mut, dich deines eigenen Verstandes zu bedienen.

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    11.09.2007
    Ort
    Leipzig
    Alter
    37
    Beiträge
    31
    Gut, dass ich diese Woche grade an meiner 3 Kanal Servoansteuerung saß

    Den Taktanschluß steckst du direkt an den PWM des Atmel. Beim Mega 8 sind das PB1,2,3.

    Dann solltest du einen Prescaler und ein entsprechend breites Vergleichsregister wählen, damit du auf eine Periode von etwa 20ms kommst.

    Ich betreibe bspw. gerade einen Mega8 mit 12MHz. 256er Prescaler und 9Bit PWM machen dann: 1 / (12.000.000 / 256 / 512) * 2 = 0.0218s

    Den OCR rechne ich indem ich die maximale Pulsbreite die der Servo hat durch 180 teile und mit der gewünschten Gradzahl multipliziere. Das ergibt die Pulsbreite für die gewünschte Position in ms. Und danach:

    OCR1A = 512 - Pulsbreite * F_CPU/256/1000000 / 2
    (also Breite * Zeit für einen Tick durch 2, weil er ja auch wieder runterzählt und das Ganze halt von den 9BIT abgezogen)

    Hoffe, das hilft dir weiter. Ansonsten fragen

    PS.: Ich betreibe die Servos in inverted PWM

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    09.11.2006
    Ort
    Hamburg
    Alter
    32
    Beiträge
    199
    Dann solltest du einen Prescaler und ein entsprechend breites Vergleichsregister wählen, damit du auf eine Periode von etwa 20ms kommst.
    Ein endsprechend breites vergleichsregister???
    Wie heißt das denn bei dir? Ich hab im Datenblatt gar nichts davon gesehen.
    Dann würde ich mein Prescaler auf CLK/512 stellen (CLK = 16MHz). Und dann auch einen 9 bit PWM nehmen.
    Am ende würde ich dann auf eine Periode von 16,384ms kommen. Das wäre doch ok, oder?

    also Breite * Zeit für einen Tick durch 2, weil er ja auch wieder runterzählt und das Ganze halt von den 9BIT abgezogen
    Meiner Zählt glaub ich nur rauf.

    Wenn ich meinen servo anschließe macht der keinen Mucks. Der zuckt nicht mal. Hab den aus einem alten Fernsteuerauto. Der is von Robbe...
    Hoffe der läuft auch bei 5V.

    MfG Jan
    Habe Mut, dich deines eigenen Verstandes zu bedienen.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    09.11.2006
    Ort
    Hamburg
    Alter
    32
    Beiträge
    199
    Hab den grade an meinem Netzteil getestet. Heil is der. Wenn ich den PWM offen lasse und 5Vund Masse anschließe zuckt der.

    MfG Jan
    Habe Mut, dich deines eigenen Verstandes zu bedienen.

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.11.2006
    Ort
    Geislingen a. d. Steige
    Alter
    26
    Beiträge
    344
    hi, schau dir mal den code an:
    http://www.roboternetz.de/wissen/ind...d_Analogservos

    Der code funktionierte bei mir mit bis zu 8 Servos!

    MfG Martin

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    11.09.2007
    Ort
    Leipzig
    Alter
    37
    Beiträge
    31
    Vergleichsregister... naja, ich meine halt den PWM-Mode. 8 o. 9 o. 10 Bit

    Meiner Zählt glaub ich nur rauf.
    Das wär mir wiederrum neu. Ich lass mich natürlich gerne eines besseren belehren.
    Bei 16MHz müsstest du m.E. den Prescaler auf 256 und den Timer auf 9Bit nehmen. Damit zählt er also in 8.192ms einmal auf 512 (9Bit) hoch, danach in der gleichen Zeit wieder runter. Macht 16.384ms Periodendauer. Sollte hoffentlich für die Servos reichen.

    -> ein Tick (Inkrement des Zählers) dauert 16.384/512 = 0.032ms
    -> für eine Pulsdauer von beispielsweise 1.5ms: 1.5ms/0.032ms = 46.875 Ticks
    -> das Ganze durch 2 Teilen und ins OCR reinschreiben: 46/2 = 23 = OCR2 oder bei inverted PWM: 512 - 23 = 489 = OCR2

    Hast du dir schon mal die Grafiken auf http://www.mikrocontroller.net/artic...WM-Betriebsart
    angeschaut? Ich finde dort ist das Ganze relativ gut nachzuvollziehen.

    Und nicht vergessen den Port zu aktivieren (da bin ich nämlich dran gescheitert)
    Code:
       	DDRB |= (1 << PB3);       						//PB3 output
       	PORTB |= ( 1 << PB3 );      					//enable PB3 Pull-up

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    09.11.2006
    Ort
    Hamburg
    Alter
    32
    Beiträge
    199
    @Zimble:
    Ich blick irgendwie nich richtig durch.
    Hab im datenblatt wieder "bisschen" rumgesucht. Ich konnte nur enddecken das man die CPU Frequenz per vorteiler (prescaler) teilern kann. Dann hat man die Frequenz mit der Periodenlänge von Tein+Taus. Diese ein/ausschaltzeit kann man dann per OCR2 beliebig verändern. Wie heißt den das Register bzw. die Bits mit denen du den Timer auf z.B. 9Bit nehmen kannst, also nochmal durch 512 teilen?

    @MartinFunk:
    Ich versteh den Code nicht ganz. Also:
    "servopos" beinhaltet die aktuelle Dauer des Signals in 1/100ms.
    Wo wird das den Vorgegeben? Das is doch nur als Variable deklariert, oder?
    TIMSK|=(1<<TOIE2) Bedeutet das bei jedem overflow ein Interrupt ausgelöst wird, oder? Aber wozu?
    WGM21 gesetzt. Laut Datenblatt CTC-Mode.(TOP=OCR2, Update of OCR2 Immediate, TOV2-Flag set on MAX) ??? Naja, verstehe ich nicht so ganz...
    CS20= No Prescaling (Das verstehe ich )

    Ich verstehe nicht wie das ganze so zusammen funktioniert.

    Dumm ist auch das ich kein Osci da hab.

    Achja, wieso sind bis zu 8 Servos mit dem Code möglich bei einem genutzten Pin? Das verstehe ich nicht.

    MfG Jan
    Habe Mut, dich deines eigenen Verstandes zu bedienen.

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    09.11.2006
    Ort
    Hamburg
    Alter
    32
    Beiträge
    199
    Kann das sein das ich für diese ganze sache ein 16-Bit PWM-Register brauche? Hab da nämlich grade im Datenblatt die auswahlmöglichkeit zwischen 8, 9 und 10-Bit PWM gesehen.

    MfG Jan
    Habe Mut, dich deines eigenen Verstandes zu bedienen.

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    11.09.2007
    Ort
    Leipzig
    Alter
    37
    Beiträge
    31
    Beim Code vom Roboternetz, nimmt man den Timer2 dazu, aller 10us einen Overflow auszulösen.
    Dies geschieht, indem man den OCR in Abhängigkeit von der CPU-Frequenz setzt und bei erreichen des OCR-Wertes den Timer wieder auf null setzt (CTC=Clear Timer on Compare)
    Code:
    TCCR2 |= (1<<WGM21) | (1<<CS20);	//Prescale=1, CTC mode
    OCR2 = F_CPU/100000;			//alle 10µS ein IRQ
    In der entsprechenden Interrupt-Routine wir nun zum einen bis 2000 gezählt um 2000x10us = 20ms Periode zu erreichen. Ist der count unter bspw. 150(servopos) wird der Port angeschaltet (150x10us=1500ms), ansonsten wird er abgeschaltet.
    Das Ganze kann man dann auf beliebig viele Servos ausweiten, indem man einfach die entsprechenden Ports und Servo-Positionen da mit einbaut.
    Als Port nimmst du da die ganz normalen I/O-Pins, da das hier ja eher ein Software-PWM ist (das togglen der Pins wird ja vom Programmierer vorgegeben)

    Ja und mit den Registern... ich red ja blöderweise auch die ganze Zeit vom Timer1, weil ich alle 3 PWM Channels benutze. Da kann man das noch angeben, beim Timer2 (den du ja benutzen willst) nicht.
    Bei mir sieht das Ganze dann so aus:
    Code:
    cli();  //disable interrupts
     
    TCCR1A |= (1<<WGM11)|(1<<COM1A1)|(1<<COM1A0);	//9BIT PWM, inverted
    TCCR1B = (1<<CS12); 							//Prescaler 256
     // macht bei meinem 12MHz mega8 21.84ms 
     
    	servo1_move(defaultPos); //setzt den OCR1A entsprechend
     
     
    //TIMSK |= (1<<OCIE1A);							//activate timer1 compare match interrupt for timing debugging
    DDRB |= (1 << PB1);       						//set PB1 output
    PORTB |= ( 1 << PB1 );      					//set PB1 Pull up on 
     
     
    sei();
    Was benutzt du zum programmieren? AVRStudio? Da kann man das relativ gut debuggen und sieht, was für Timings rauskommen. Spart man sich den Oszi.

  10. #10
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    09.11.2006
    Ort
    Hamburg
    Alter
    32
    Beiträge
    199
    Dann benutz ich auch einen anderen Timer. Bis jetzt is an meinem Roboter nur ein LDR-Spannungsteiler auf ADC0. Dann will ich noch meine Antriebsmotoren über PWM steuern (Kette links, Kette rechts), aber das kann ich ja auch mit jedem PWM machen.

    Code:
    cli();
    Das ist bestimmt eine fertige Function, oder? Woher kennst du die?

    Code:
    servo1_move(defaultPos); //setzt den OCR1A entsprechend
    Dazu hast du noch ne Function in deinem Code, oder?

    Code:
    sei();
    Das ist sicherlich auch eine fertige function, oder? Was macht die?

    Glaub ich komm klar, wenn du das noch erklährst

    MfG Jan
    Habe Mut, dich deines eigenen Verstandes zu bedienen.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •