-         

Ergebnis 1 bis 9 von 9

Thema: Ansteuerung Servo mit Servo Fkt. oder mit PWM?

  1. #1

    Ansteuerung Servo mit Servo Fkt. oder mit PWM?

    Anzeige

    Hallo,

    ich habe schon einige Threads gelesen und bin mir unschlüssig, ob die SERVO Funktion in Bascom die beste Möglichkeit zur Ansteuerung eines Servos darstellt.

    Grundsätzlich sollte die Steuerung der Servos auch über PWM funktionieren, jedoch habe ich noch eine Unwissenheitslücke:
    Wie kann ich in PWM Mode den Zähler einschränken, damit ich genau auf meine gewünschte Trägerfrequenz komme.
    Quarz 3686400 Hz, Prescale 64, 10bit, Zielfrequenz=50Hz bekomme ich nach 575 Zähler (Formel: fziel=fclk/(2*prescaler*(1+Zähler))

    Den Timer allein kann ich zb.: mit einem Interrupt vorstellen, damit ich die Frequenz erhalte.
    Wie macht man das jedoch bei PWM? Kann ich hier auch einen Interrupt festlegen und den Timer vorstellen?
    Beiliegend findet ihr meinen unvollständigen Code, bitte gebt mir eine Empfehlung, was besser ist und ob man es eventuell so programmieren könnte.
    Lg
    Code:
    ' 0 sind Eingänge; 1 sind Ausgänge
    ' digitaler EIngang Pullup Widerstand ergibt 0 wenn Spannung anliegt
    ' PortB3 Endschalter Schloss-Servo nicht verriegelt
    ' PortB4 Endschalter Sperrelemt offen
    ' PortB5 Endschalter Sperrelemt geschlossen
    ' PortC0 Antriebsmotor ein/aus Relais
    ' PortC1 Ansteuerung Relais Umschalter für Antriebsmotor
    '        (dreht sich links..schließen bei 0 und rechts..öffnen bei 1)
    ' PortC2 Relais Schalten für Servo Antrieb 0..aus/ 1..ein
    ' PortC3 Analoger Eingang Messung Spannungsabfall, ob Servo dreht oder nicht
    ' PortB1 PWM Signal für Servowinkelsollsignal
    
    $regfile = "m8def.dat"
    $crystal = 3686400                                          'externer Quarz
    
    Config Adc = Single , Prescaler = Auto                      'Analoger Eingang eingeschalten
    Start Adc
    
    Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Prescale = 1
    On Timer1 Timerroutine:
    Enable Timer1
    Start Timer1
    Enable Interrupts
    Pwm1a = 741                                                 '7 Zähler entspricht ca. 40° Servobewegung
    
    
    
    Dim X As Bit
    
    Ddrb = &B00000111                                           'Alle unbenützten Eingänge auf Pullup Widerstand gesetzt
    Portb = &B11111000
    
    Ddrc = &B00000111
    Portc = &B11111000
    
    
    
    Do
    
    'HAuptprogramm
    
    Loop
    
    
    Timerroutine:
    Timer1 = 735                                                '50HZ entspricht 575 Schritte, Start TIMER1 bei 1023-(575+1)/2=735
    
    Return
    
    
    
    End

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2005
    Beiträge
    175
    Hallo und herzlich willkommen hier im Forum!

    Zur Servo-Ansteuerung würde ich Dir den Pulseout-Befehl empfehlen, ist in der Bascom-Hilfe gut beschrieben. Pulseout belegt keinen Timer, keinen Interrupt und ist auf beliebige PIN´s anwendbar.

    (Hardware)PWM ist auf bestimmte Pins beschränkt unf frisst einen Timer, der Servo-Befehl arbeitet für meinen Geschmack zu grobmotorisch und verbraucht ebenfalls einen Timer.

    Du brauchst nicht zwingend die 50Hz einzuhalten.
    Meiner (praktischen) Erfahrung nach interessieren sich die Servos lediglich für die Pulslänge, so kann man auch mit höherer Frequenz arbeiten. Keine Ahnung, wo die Untergrenze liegt, da hatte ich bislang keine Probleme. Letztens sagte einer, minimum 10ms... am besten ausprobieren.
    Nur viel länger als 20ms (=50Hz) sollte die Pause zwischen den Pulsen nicht sein, sonst verlieren die Servos an Stellkraft.

    Grüße

    Torsten

  3. #3
    Hallo Torsten,

    danke, das werde ich gleich mal ausprobieren!

    Lg
    Reinhard

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    24.01.2007
    Ort
    Hildesheim
    Beiträge
    14
    Hi,
    hast Du ein Beispiel, wie der Pulseout Befehl mit einem Servo funktioniert?
    Ich bekomme das leider nicht hin.

    Danke!

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2005
    Beiträge
    175
    Hallo Andi,

    hatte erst jetzt Deinen Beitrag entdeckt...

    Ein Beispiel kannst Du gerne haben:

    Code:
    '******************************************************
    'Projekt: Atmel-Programmierung für Einsteiger
    '
    'Prozessor: ATMega 8-16
    'Bascom-Version: 1.11.8.1
    '
    'Auswertung für Graupner Nautic Expert Baustein
    'Ansteuerung von Servos über Schalterpositionen
    '
    'Version: 1.0
    '
    'Hardware:
    'R/C-Kanal an D.2 (INT0)
    'LED an C.0
    'Servos an C.1...C.4
    '
    '15.01.2007 T. Gietenbruch
    '
    '******************************************************
    
    '======================================================
    'System-Einstellungen
    '======================================================
    'Definition für Mega 8
    $regfile "m8def.dat"
    
    'Angabe der Taktfrequenz (8Mhz)
    $crystal = 4000000
    
    '======================================================
    'Konfigurationen
    '======================================================
    
    'Konfiguration der I/O-Ports´s
    Ddrc = 11111111
    Ddrd = 11110000
    
    'Konfiguration des Timer1
    Config Timer1 = Timer , Prescale = 1
    
    'Konfiguration des INT0
    'Interrupt bei jedem Flankenwechsel (0->1 und 1->0)
    Config Int0 = Change
    
    '======================================================
    'Deklarationen
    '======================================================
    
    Dim N As Byte
    Dim N_old As Byte
    Dim Location As Byte
    Dim Signals As Byte
    Dim Reading As Bit
    Dim Rc_value(10) As Word
    Dim Error As Bit
    Dim Sync_detect As Bit
    Dim X As Word
    Dim Switch_up As Byte
    Dim Switch_dn As Byte
    Dim Sync_ok As Bit
    Dim Cycle_done As Bit
    Dim Switchhold As Byte
    Dim Number As Byte
    Dim Watchcat As Word
    Dim Servowert_1 As Word
    Dim Servowert_2 As Word
    Dim Servowert_3 As Word
    Dim Servowert_4 As Word
    
    '======================================================
    'Konstanten
    '======================================================
    Const Sync_lowlimit = 8000
    Const Sync_highlimit = 9000
    Const Switch_lowlimit = 4000
    Const Switch_highlimit = 7900
    
    Const Servo1_up_pos = 1000
    Const Servo1_nt_pos = 1500
    Const Servo1_dn_pos = 2000
    
    Const Servo2_up_pos = 1200
    Const Servo2_nt_pos = 1300
    Const Servo2_dn_pos = 2000
    
    Const Servo3_up_pos = 2000
    Const Servo3_nt_pos = 1800
    Const Servo3_dn_pos = 1000
    
    Const Servo4_up_pos = 1500
    Const Servo4_nt_pos = 2000
    Const Servo4_dn_pos = 1000
    
    '======================================================
    'Initialisierungen
    '======================================================
    
    'Zuweisung der Interrupt-Service-Routinen
    On Timer1 Rc_error
    On Int0 Rc_read
    'Timer-Freigabe
    Enable Timer1
    Stop Timer1
    
    'Ports initialisieren
    Portc = &B11111111
    
    'Freigabe der Interrupt-Routinen
    Enable Int0
    Enable Interrupts
    
    '======================================================
    'Synchronisationsschleife
    '======================================================
    Syncronize:
    Signals = 1
    N = 1
    Sync_detect = 0
    X = 0
    
    'Rücksetzen aller Schaltersignale
    For X = 0 To 7
       Switch_up.x = 0
       Switch_dn.x = 0
    Next X
    
    X = 0
    
    'Warten auf ersten Synchronisationswert
    While Sync_detect = 0
    Wend
    
    N = 2
    Sync_detect = 0
    
    'Warten auf zweiten Synchronisationswert
    'Begrenzt durch Zählschleife
    While X < 5000 And Sync_detect = 0
       Incr X
    Wend
    
    'Auswertung des Synchronisationsergebnisses
    If X < 5000 And Rc_value(1) > Sync_lowlimit And Rc_value(2) > Sync_lowlimit Then
       N = 3
       Signals = 10
    Else
       Goto Syncronize
    End If
    
    Watchcat = 0
    
    '======================================================
    'Hauptprogramm-Schleife
    '======================================================
    Do
    
    'Auswertung der gelesenen Werte (im Block)
    If Cycle_done = 1 And Reading = 0 And Error = 0 Then
       Cycle_done = 0
       'Überprüfung der Synchronisationssignale
       If Rc_value(1) > 8000 And Rc_value(2) > 8000 And Error = 0 Then
          Sync_ok = 1
       Else
          Sync_ok = 0
          Goto Syncronize
       End If
    
       'Aktualisierung der Schaltersignale
       If Sync_ok = 1 Then
          For X = 3 To Signals
             Number = X - 3
             'Schalter nach oben betätigt
             If Rc_value(x) > 7000 And Rc_value(x) < 7900 Then
                If Switchhold.number = 0 Then
                   Switchhold.number = 1
                   Toggle Switch_up.number
                End If
             'Schalter nach unten betätigt
             Elseif Rc_value(x) > 4000 And Rc_value(x) < 5500 Then
                If Switchhold.number = 0 Then
                   Switchhold.number = 1
                   Toggle Switch_dn.number
                End If
             'Schalter in Mittelstellung
             Else
                Switchhold.number = 0
                Switch_up.number = 0
                Switch_dn.number = 0
             End If
          Next X
    
          'Zuweisen der Servopositionen
          If Switch_up.0 = 1 And Switch_dn.0 = 0 Then
             Servowert_1 = Servo1_up_pos
          Elseif Switch_up.0 = 0 And Switch_dn.0 = 1 Then
             Servowert_1 = Servo1_dn_pos
          Else
             Servowert_1 = Servo1_nt_pos
          End If
          If Switch_up.1 = 1 And Switch_dn.1 = 0 Then
             Servowert_2 = Servo2_up_pos
          Elseif Switch_up.1 = 0 And Switch_dn.1 = 1 Then
             Servowert_2 = Servo2_dn_pos
          Else
             Servowert_2 = Servo2_nt_pos
          End If
          If Switch_up.2 = 1 And Switch_dn.2 = 0 Then
             Servowert_3 = Servo3_up_pos
          Elseif Switch_up.2 = 0 And Switch_dn.2 = 1 Then
             Servowert_3 = Servo3_dn_pos
          Else
             Servowert_3 = Servo3_nt_pos
          End If
          If Switch_up.3 = 1 And Switch_dn.3 = 0 Then
             Servowert_4 = Servo4_up_pos
          Elseif Switch_up.3 = 0 And Switch_dn.3 = 1 Then
             Servowert_4 = Servo4_dn_pos
          Else
             Servowert_4 = Servo4_nt_pos
          End If
    
       End If
    End If
    
    'Watchdog
    If N = N_old Then
       Incr Watchcat
       If Watchcat > 5000 Then Goto Syncronize
    Else
       N_old = N
       Watchcat = 0
    End If
    Loop
    
    'Programmende (nur formal)
    End
    
    
    '======================================================
    'ISR für INT0 - Signalfolge lesen
    '======================================================
    Rc_read:
    'Den Timer starten mit steigender Flanke
    If Reading = 0 And Pind.2 = 1 Then
       Start Timer1
       Reading = 1
    'Den Timer stoppen mit fallender Flanke
    Else
       Stop Timer1
       Rc_value(n) = Timer1
       Timer1 = 0
       Reading = 0
       'Setzen der Servopositionen
       If Sync_ok = 1 Then
          Pulseout Portc , 1 , Servowert_1
          Pulseout Portc , 2 , Servowert_2
          Pulseout Portc , 3 , Servowert_3
          Pulseout Portc , 4 , Servowert_4
       Else
          Portc.1 = 0
          Portc.2 = 0
          Portc.3 = 0
          Portc.4 = 0
       End If
       'Validierung des gelesenen Wertes
       If Rc_value(n) < 4000 Or Rc_value(n) > Sync_highlimit Then Goto Rc_error
       'Prüfung auf Sync-Signal
       If N < 3 And Rc_value(n) > Sync_lowlimit And Rc_value(n) < Sync_highlimit Then
          Sync_detect = 1
       End If
       '...wenn die Synchronisation fertig ist
       If Signals > 2 Then
          Incr N
       End If
       If N > Signals Then
          N = 1
          Cycle_done = 1
       End If
       'Statusanzeige an C.0
       Toggle Portc.0
    End If
    'Error-Bit rücksetzen
    Error = 0
    Return
    
    '======================================================
    'ISR für Timer1 - Fehlerhandling
    '======================================================
    Rc_error:
    'Error-Bit setzen
    Error = 1
    Reading = 0
    Stop Timer1
    
    Return
    Das Programm kommt aus dem Modellbau und wertet die Signale eines Graupner NauticExpert-Moduls aus. Damit werden dann vier Servos in vorgegebene Positionen gefahren.

    Anwendung ist die Getriebe- und Sperrdifferentilansteuerung eines Allrad-Wedico-Trucks.

    Die Hardware wird direkt am Empfänger angeschlossen, die ISR der Signalauswertung (rc_read) nutze ich gleichzeitig zur Aktualisierung der Pulseouts.

    "Runterbrechen" auf ein einfaches Beispiel müsstest Du es Dir bitte selbst...

    Grüße

    Torsten

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.07.2007
    Alter
    53
    Beiträge
    1.080
    Zitat Zitat von Torsten_G
    Zur Servo-Ansteuerung würde ich Dir den Pulseout-Befehl empfehlen, ist in der Bascom-Hilfe gut beschrieben. Pulseout belegt keinen Timer, keinen Interrupt und ist auf beliebige PIN´s anwendbar.
    Nur aus Neugierde meine Nachfrage:
    Wenn dieser Befehl keinen Timer und keinen Interrupt verwendet, wie erzeugt er dann z.b. einen Impuls von 1,5ms Länge? Legt er den Portpin auf High, wartet dann so lange und setzt ihn dann wieder auf Low?
    Wenn das so sein sollte, dann erkauft man sich einen gesparten Timer durch eine enorme Zeitverschwendung beim Erzeugen des Pulses. Nur das Ansteuern eines einzigen Servos würde den µC dann ja schon zu 5-10% auslasten.

    Falls ich mich irre ... einfach weiterlesen und mich nicht beachten ^^

    EDIT: den Bascom-Befehl für die Servos kann man wirklich vergessen, wenn man mit den Servos nicht grade Pinoccio in der Folge "me & xtc" steuern möchte
    Mein Hexapod im Detail auf www.vreal.de

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2005
    Beiträge
    175
    Hallo,

    nein, Pulseout wartet nicht.
    Wie das genau funzt, entzieht sich aber leider meiner Kenntnis - da wären jetzt mal die Hardcore-Bascomer gefragt...

    Gruß

    Torsten

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    24.01.2007
    Ort
    Hildesheim
    Beiträge
    14
    Hallo Torsten!
    Vielen Dank für den Quellcode, das Runterbrechen sollte ich hinbekommen!
    Kannst Du ungefähr sagen, wieviel genauer deine Variante im Vergleich zum normalen Servo Befehl ist?
    Danke!

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2007
    Beiträge
    386
    ....nein, Pulseout wartet nicht.....

    natürlich, der wartet so lange bis der puls draussen ist.

    weiterhin steht in der bascombschreibung wie lange mindestens ein pulse läuft. es kann für manche steuerungen zu lange dauern.

    pwm ist präziser und noch feinfühliger für den servo. der servo kann dadurch noch genauer positioniert werden.

    mfg

Berechtigungen

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