-         

+ Antworten
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: PWM für Servo mit eingebautem PWM gen. (Atmel 2313)

  1. #1
    Philipp_c
    Gast

    PWM für Servo mit eingebautem PWM gen. (Atmel 2313)

    Anzeige

    Hallo

    kann ich zum ansteuern eines Modellbau Servos, den eingebauten PWM des 2313 nutzen oder muss ich das selber basteln? Ich programmiere in ASM (bzw fange gerade damit an). Ideal wäre natrürlich wenn ich irgendwo dann einfach mein Byte reinschreiben könnte was dann direkt in die Servostellung umgesetzt wird.

    Vielen Dank für die Hilfe

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Das Hardware-PWM könnte für EIN Servo funktionieren(steht im Datenblatt, wie man das einstellt(das Intervall sollte irgendwas um 20ms sein, ist aber unkritisch.). Ich nehme an, du weisst, wie ein Servosignal aufgebaut ist?). Wenn du die genauen Werte haben willst, die du in die Register schreiben musst, poste mal deine Taktfrequenz.
    Bei der geringen Frequenz kannst du aber(zumal in ASM) auch ohne weiteres eine Software-Version erzeugen(hängt davon ab, was du sonst noch gleichzeitig machen willst.). Damit lassen sich dann auch mehrere Servos stellen(was hast du eigentlich damit vor?).
    Ich hab' mal den Code von meinem Software-PWM drangehängt(das Programm kann gleichzeitig noch Servosignale verstehen. Mehr war bei mir nicht nötig, deshalb lässt sich wahrscheinlich noch viel verfeinern.).
    Code:
    .include "2313def.inc"			;Definitionsdatei laden
    .Def RXtemp =r27
    .Def S1Pos = r28                        ;Servo1 invertiert an PB0 - Position in 64tel
    .Def S2Pos = r29
    .equ S1Offset=4                         ;Offset in 256µS
    .equ S2Offset=4
    .equ CLOCK = 8000000
    .equ BAUD = 9600
    .equ UBRRVAL = CLOCK/(BAUD*16)-1
    .org 0x000
             rjmp start                     
    .org 0x00B 
             rjmp onRXD                     ;Interupt für RX
    
    start:	ldi	r16,low(ramend)		;Stackpointer auf
    	out	spl,r16			;RAM-Ende setzen
    	ldi	r16,0x0f		
    	out	ddrb,r16		;PortB.0-3 aus Ausgang setzen
            ldi     r16,0
            out     portb,r16               ;Interne Pullups von PortD abstellen, Ausgänge auf low
            ldi     r16,0b00000010          
            out     TCCR1B,r16              ;Prescaler für Timer1 auf 8 stellen 
            ldi     r16, UBRRVAL            
            out     UBRR, r16               ;Baudrate einstellen
            ldi     r16, 0b10011000         
            out     UCR, r16                ;TX anmachen, RX anmachen, RX-Int anmachen
            ldi     S1Pos,32                ;Startpositionen setzen
            ldi     S2Pos,32
            sei                             ;interupts an
    
    loop:
            ldi r16,0                       ;Timer1 zurücksetzen
            out TCNT1H,r16
            ;ldi r16,0
            out TCNT1L,r16
            LDI r16,0                       
            out portb,r16                   ;Signal an 
    anloop:                                 ;Endlosschleife die die Servopulse überwacht und nach ca. 20ms zu loop zurückspringt
            IN r18,TCNT1L
            IN r16,TCNT1H
            
            ;ÜBERPRÜFEN,OB PULS FÜR SERVO1 FERTIG
            SBIC portb,0
            rjmp s1fertig                   ;Wenn der Puls schon aus ist, Überprüfung skippen
            mov r17,s1pos                   
            ANDI r17,0xF0                   ;Low-Nibble von S1pos löschen
            SWAP r17                        ;Und Nibbles tauschen - effektiv durch 16 teilen
            SUBI r17,-S1Offset              ;Offset hinzufügen
            cp  r16,r17                     ;S1pos mit Timer vergleichen, Ausmachen skippen, wenn Timer kleiner
            brlo S1Fertig
    
            mov r17,s1pos                   ;Sonst mit dem Low-Teil des Timers vergleichen
            ANDI r17,0x0F                   ;H-Nibble von S1pos löschen
            SWAP r17                        ;Und Nibbles tauschen - effektiv mit 16 multiplizieren
            cp r18,r17                       
            brlo S1Fertig                   ;Wenn Timer kleiner, anlassen
    
            SBI portb,0                     ;Servo1 Puls ausmachen
    S1fertig:
            ;ÜBERPRÜFEN,OB PULS FÜR SERVO2 FERTIG
            SBIC portb,1
            rjmp s2fertig                   ;Wenn der Puls schon aus ist, Überprüfung skippen
            mov r17,s2pos                   
            ANDI r17,0xF0                   ;Low-Nibble von S2pos löschen
            SWAP r17                        ;Und Nibbles tauschen - effektiv durch 16 teilen
            SUBI r17,-S2Offset              ;Offset hinzufügen
            cp  r16,r17                     ;S2pos mit Timer vergleichen, Ausmachen skippen, wenn Timer kleiner
            brlo S2Fertig
    
            mov r17,s2pos                   ;Sonst mit dem Low-Teil des Timers vergleichen
            ANDI r17,0x0F                   ;H-Nibble von S2pos löschen
            SWAP r17                        ;Und Nibbles tauschen - effektiv mit 16 multiplizieren
            cp r18,r17                       
            brlo S2Fertig                   ;Wenn Timer kleiner, anlassen
    
            SBI portb,1                     ;Servo2 Puls ausmachen
    S2fertig:
            cpi r16,80                      ;Nach Ablauf von ca. 20ms neuen Zyklus starten
            brsh loop
            rjmp anloop    
    
    onRXD: 
            IN S1POS,UDR
            IN rxtemp,TCNT1L
            OUT UDR,rxtemp
            reti
    it works best if you plug it (aus leidvoller Erfahrung)

  3. #3
    Philipp_c
    Gast
    Danke erstmal. Ja, das Prinzip der Ansteuerung ist mir klar. Ich wollte damit das Gas bei meinem Auto betätigen (Sicherheitsfunktionen kommen da noch rein). Letzendlich würde ich gern die Drehzahl mit dem Controller messen und auf Knopfdruck soll er diese dann halten können (quasi Tempomat).
    Ich habe mal ein wenig mit dem Servo rumgespielt dabei das ganze allerdings einfach so gemacht ohne Timer usw. (wenig erfahrung bisher mit ASM). Jetzt würde ich es gern so weit wie möglich Interrupt gesteuert machen so das der Controller möglichst nicht in irgendwelchen Warteschleifen hängt sondern noch andere Dinge tun kann.
    Wieviele Abstufungen sind eigentlich sinnvoll mit so einem Servo, dachte mal daran ihm seriell ein Byte zu senden meinetwegen 0x00 linksanschlag und 0xFF rechts aber warscheinlich kann der eh nicht so feinabstufen oder?

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Jetzt würde ich es gern so weit wie möglich Interrupt gesteuert machen so das der Controller möglichst nicht in irgendwelchen Warteschleifen hängt sondern noch andere Dinge tun kann.
    Wenn du nur ein Servo pro Timer nimmst, kannst du den Timer immer so einstellen, dass er überläuft(und den entsprechenden Interrupt triggert), wenn das nächste mal eine Änderung am Servo-Pin nötig ist. Du schaltest also z.B. den Pin auf High und stellst den Prescaler so ein, dass ein Überlauf mindestens 2ms dauert. Dann stellst du über den Wert, den du in den Timer lädst, ein, dass er überläuft, wenn der Port auf low soll(also ja nach Stellung nach 1-2ms). Das machst du beim nächsten Überlauf und stellst dann den Timer so ein, dass er nach 18-19ms überläuft. Wenn du den 16-Bit-Timer dafür über hast, brauchst du nur immer einen anderen Wert in den Timer zu laden und kannst immer den gleichen Prescaler(meist wohl 1) nehmen. Mit 8 bit musst du den Prescaler nach jedem Schalten verändern(wenn 256 Schritte mindestens 20 ms dauern sollen, hast du bei 1 ms nurnoch 12 Stufen.).
    Wieviele Abstufungen sind eigentlich sinnvoll mit so einem Servo, dachte mal daran ihm seriell ein Byte zu senden meinetwegen 0x00 linksanschlag und 0xFF rechts aber warscheinlich kann der eh nicht so feinabstufen oder?
    Die Fernsteuerungen, mit denen Modellservos normalerweise angesteuert werden, können höchstens 64 Stufen. Also werden die Servos wohl in der Praxis auch nicht viel genauer gehen. Die Servoelektronik an sich ist(zumindest bei dem Servo, das ich auseinandergenommen hab' und den Plänen, die ich kenne) völlig analog(ein Poti misst die Stellung und stellt darüber ein Tastverhältnis ein, das über die Stellung des Servos an das PWM-Signal angeglichen wird.).
    it works best if you plug it (aus leidvoller Erfahrung)

  5. #5
    Philipp_c
    Gast
    Hmm, ich wollte eigentlich den 8bit Timer nehmen, weil ich den 16Bit Timer für die Drehzahl benötige (mit 8Bit zu ungenau von 800-6500 Um/min). Wie kritisch ist das Timing eiegntlich bei den Servos? Muss ich es so machen das ein Zyklus immer genau 20ms hat? (Also 1,6 Signal und danach dann 18,4 Pause?) oder kann ich die Pause zwischen den Pulsen fest auf 18ms oder so lassen?

    Zu dem Prescaler: Ich kann ja einen hohen Teiler einstellen um die ca 20ms zu warten und dann einen kleineren damit ich mit den 8bit die 1ms besser auflösen kann oder? und der Impuls ist ja zwischen 1 und 2ms. dann könnte ich ja zB:
    18 ms Pause
    1 ms High
    und dann zwischen 0 und 1ms genau einstellbar machen oder sehe ich da was falsch?

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Die Pause kannst du fest lassen(aber lieber 19ms als 18, bei zu kurzen Zyklen sollen manche Servos flattern).
    Zu dem Prescaler: Ich kann ja einen hohen Teiler einstellen um die ca 20ms zu warten und dann einen kleineren damit ich mit den 8bit die 1ms besser auflösen kann oder?
    Genau! Beim 8Bit-Timer kannst du es so machen(oder auch einfach die Überläufe für die langen Pausen zählen. Dann läuft deine ISR aber unnötig oft ab).
    18 ms Pause
    1 ms High
    und dann zwischen 0 und 1ms genau einstellbar machen oder sehe ich da was falsch?
    Das geht. Je nachdem, welche Taktfrequenz du verwendest, kannst du die 1-2ms auch direkt erzeugen(ohne die 1ms High einzeln), da es, wenn du nicht extra für den Zweck deinen Quarz aussuchst, den "perfekten" Prescaler wahrscheinlich ohnehin nicht gibt.
    it works best if you plug it (aus leidvoller Erfahrung)

  7. #7
    Gast
    die eine ms wollte ich nur extra erzeugen weil die ja eh konstant ist und ich so die vollen 8bit zum variieren der Servo Stellung hätte. Sonst müsste ich ja, wenn 0xff genau 2ms währen die hälfte verschenken, weil der Servo sich erst bei 0x0f anfängt so bewegen.

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Sonst müsste ich ja, wenn 0xff genau 2ms währen die hälfte verschenken
    eben
    Je nachdem, welche Taktfrequenz du verwendest, kannst du die 1-2ms auch direkt erzeugen(ohne die 1ms High einzeln), da es, wenn du nicht extra für den Zweck deinen Quarz aussuchst, den "perfekten" Prescaler wahrscheinlich ohnehin nicht gibt.
    Wahrscheinlich musst du ohnehin etwas verschenken, weil du einen Prescaler von 1ms/(CLK*255) nicht genau einstellen kannst(es sei denn, du orderst dir einen genau passenden Quarz).
    it works best if you plug it (aus leidvoller Erfahrung)

  9. #9
    Gast
    Jetzt nochmal ob ich alles richtig verstanden hab. Nehmen wir mal an ich habe ein 4MHz Quarz. Dann dauert ein Clk 0,00025ms. Nun stelle ich den Prescaler auf 1024 dann dauert ein TimerCount 0,256ms. Wenn ich nun möchte das der Timer Interrupt nach 19ms kommt müssen also ca 74 TimerCounts vergehen (18,944ms). Jetzt setze ich den TimerCounter also auf 255-74=181 und starte den Timer. Jetzt sollte der Interrupt nach ziemlich genau 19ms auslösen oder?

  10. #10
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Ja
    it works best if you plug it (aus leidvoller Erfahrung)

+ Antworten
Seite 1 von 2 12 LetzteLetzte

Benutzer, die dieses Thema gelesen haben: 0

Derzeit gibt es keine Benutzer zum Anzeigen.

Berechtigungen

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