www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Servo Ansteuerung funktioniert nicht / Bascom


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einen kleinen Code geschrieben (das meiste kopiert), der aber 
leider nicht funktioniert. Ich glaube das etwas mit der Timerbrechnung 
nicht stimmt. Also angeschlossen werden fünf Servos und mittels eines 
Interrups angesteuert. Der soll ja alles 20ms schalten.

Könnt ihr bitte mal drüberschauen, was da nicht passt? Wenn ich ein 
Servo anschließe, dreht es ein paar schritte in eine Richtung weiter und 
macht nichts mehr. Es fährt definitiv nicht in die Mitte!

DANKE
Lg
Peter
$regfile "m32def.dat"
$crystal = 8000000
$hwstack = 64
$swstack = 64
$framesize = 64

Config Pinc.1 = Output                                      'LCD
Config Pinc.0 = Output                                      'LCD
Config Pind.4 = Output                                      'LCD
Config Pind.5 = Output                                      'LCD
Config Pind.6 = Output                                      'LCD
Config Pind.7 = Output                                      'LCD
Config Pind.2 = Input                                       'Signal Eingang

Config Pina.7 = Output
Config Pinc.4 = Output
Config Pinc.5 = Output
Config Pinc.6 = Output
Config Pinc.7 = Output


Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.7 , Db6 = Portd.5 , Db7 = Portd.6 , E = Portc.0 , Rs = Portc.1
Config Lcd = 20 * 2
Cursor Off

Config Timer1 = Timer , Prescale = 8                        'timer für servos
Enable Timer1
Timer1 = 45536

Portc.4 = 0                                                 'hier hängt servo1
Portc.5 = 0                                                 'hier hängt servo2
Portc.6 = 0                                                 'hier hängt servo3
Portc.7 = 0                                                 'hier hängt servo4
Porta.7 = 0                                                 'hier hängt servo4

On Timer1 Servoirq
Enable Interrupts

Dim Servo(5) As Word
Dim Kanal As Byte
Kanal = 0

Do

Servo(1) = 45535                                            'Mitte
Servo(2) = 45535                                            'Mitte
Servo(3) = 45535                                            'Mitte
Servo(4) = 45535                                            'Mitte
Servo(5) = 45535                                            'Mitte


Loop
End

Servoirq:
If Kanal = 0 Then
   If Portc.4 = 0 Then                                      'wenn port low
      Timer1 = Servo(1)                                     'dann timer auf entsprechende verzögerung
      Portc.4 = 1                                           'und port anschalten
   Else                                                     'das hier passiert erst bei dem darauf folgenden interrupt
      Portc.4 = 0                                           'dann port wieder ausschalten
      Incr Kanal                                            'und den nächsten kanal bearbeiten
   End If
End If
If Kanal = 1 Then
   If Portc.5 = 0 Then
      Timer1 = Servo(2)
      Portc.5 = 1
   Else
      Portc.5 = 0
      Incr Kanal
   End If
End If
If Kanal = 2 Then
   If Portc.6 = 0 Then
      Timer1 = Servo(3)
      Portc.6 = 1
   Else
      Portc.6 = 0
      Incr Kanal
   End If
End If
If Kanal = 3 Then
   If Portc.7 = 0 Then
      Timer1 = Servo(4)
      Portc.7 = 1
   Else
      Portc.7 = 0
      Incr Kanal
   End If
End If
If Kanal = 4 Then
   If Porta.7 = 0 Then
      Timer1 = Servo(5)
      Porta.7 = 1
   Else
      Porta.7 = 0
      Incr Kanal
   End If
End If


If Kanal = 4 Then
  Timer1 = 55536                                            '10ms pause damit ich auch 20ms komme
  Kanal = 0
End If
Return


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:

> leider nicht funktioniert. Ich glaube das etwas mit der Timerbrechnung
> nicht stimmt.

Genau.

Wenn dein µC mit 8 Mhz Taktet und der Vorteiler auf 8 steht, dann zählt 
der Timer mit 1Mhz ( 8000000 / 8 )

Der Timer muss von 45535 bis 65536 hochzählen, das sind über den Daumen 
20000 Zählschritte.

Wie lang braucht er dafür, wenn er in 1 Sekunde bis 1 Mio zählen könnte?

20000 / 10000000 = 0.02 also 20 Millisekunden.

Das ist zu lang für den Servopuls. Der sollte für Mittelstellung bei ca 
1.5 Millisekunden sein und nicht bei 20


> Also angeschlossen werden fünf Servos und mittels eines
> Interrups angesteuert. Der soll ja alles 20ms schalten.

Bei 4 Servos hintereinander brauchst du den 20ms keine großartige 
Beachtung mehr schenken. Die sich ergebende Pause nach den Pulsen ist 
mit einiger Sicherheit lang genug, dass kein Servo mehr ins straucheln 
kommt. Zumindest ist mir noch nie eines untergekommen.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

danke für die Infos.

Nun gut, Mittelstellung ist 1,5ms. das wäre bei 1000000 hz =1500 
Zählschritte.

also 65536-1500=64036

Nun gut, leider funkt der Code dadurch auch noch nicht...

Für was genau ist der Timerwert am Anfang des programms? Also bei meinem 
Beispiel 45536? Das ist doch dafür da, dass alle 20ms die Signal 
ausgeschickt werden?

Und ganz unten im Programm ist nochmal ein Timer, der quasi die 20ms 
"auffüllt".Bei fünf Servos müssen da noch 10ms offen sein.

Kannst du bitte nochmal drüberschauen?

Sorry wenn ich lästig bin, bin noch Anfänger...
Config Timer1 = Timer , Prescale = 8                        'timer für servos
Enable Timer1
Timer1 = 45536

Portc.4 = 0                                                 'hier hängt servo1
Portc.5 = 0                                                 'hier hängt servo2
Portc.6 = 0                                                 'hier hängt servo3
Portc.7 = 0                                                 'hier hängt servo4
Porta.7 = 0                                                 'hier hängt servo4

On Timer1 Servoirq
Enable Interrupts

Dim Servo(5) As Word
Dim Kanal As Byte
Kanal = 0

Do

Servo(1) = 64035                                            'Mitte
Servo(2) = 64035                                            'Mitte
Servo(3) = 64035                                            'Mitte
Servo(4) = 64035                                            'Mitte
Servo(5) = 64035                                            'Mitte


Loop
End

Servoirq:
If Kanal = 0 Then
   If Portc.4 = 0 Then                                      'wenn port low
      Timer1 = Servo(1)                                     'dann timer auf entsprechende verzögerung
      Portc.4 = 1                                           'und port anschalten
   Else                                                     'das hier passiert erst bei dem darauf folgenden interrupt
      Portc.4 = 0                                           'dann port wieder ausschalten
      Incr Kanal                                            'und den nächsten kanal bearbeiten
   End If
End If
If Kanal = 1 Then
   If Portc.5 = 0 Then
      Timer1 = Servo(2)
      Portc.5 = 1
   Else
      Portc.5 = 0
      Incr Kanal
   End If
End If
If Kanal = 2 Then
   If Portc.6 = 0 Then
      Timer1 = Servo(3)
      Portc.6 = 1
   Else
      Portc.6 = 0
      Incr Kanal
   End If
End If
If Kanal = 3 Then
   If Portc.7 = 0 Then
      Timer1 = Servo(4)
      Portc.7 = 1
   Else
      Portc.7 = 0
      Incr Kanal
   End If
End If
If Kanal = 4 Then
   If Porta.7 = 0 Then
      Timer1 = Servo(5)
      Porta.7 = 1
   Else
      Porta.7 = 0
      Incr Kanal
   End If
End If


'If Kanal = 4 Then
'  Timer1 = 55536                                            '10ms pause damit ich auf 20ms komme
'  Kanal = 0
'End If
Return

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> Hallo Karl Heinz,
>
> danke für die Infos.
>
> Nun gut, Mittelstellung ist 1,5ms. das wäre bei 1000000 hz =1500
> Zählschritte.
>
> also 65536-1500=64036
>
> Nun gut, leider funkt der Code dadurch auch noch nicht...

Hast du deine 8Mhz überprüft?

> Für was genau ist der Timerwert am Anfang des programms?
> Also bei meinem Beispiel 45536?

Für nix

> Und ganz unten im Programm ist nochmal ein Timer,

Im ganzen Programm gibt es nur 1 Timer, der nacheinander die Pulse in 
jedem Overflow Interrupt erzeugt. Die Zahl die jedesmal in den Timer 
geladen wird, betimmt die Zeit bis dann der nächste Overflow auftreten 
wird.

> Bei fünf Servos müssen da noch 10ms offen sein.
Die kannst du getrost ignorieren. Die sind nicht das Problem.

Wahrscheinlich wird dein Mega nicht mit 8Mhz arbeiten, sondern mit dem 
1Mhz mit dem er von Atmel ausgeliefert wird.

Autor: MIR Mitentwickler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oszillograph vorhanden ???

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> 'If Kanal = 4 Then
> '  Timer1 = 55536                                            '10ms pause
> damit ich auf 20ms komme
> '  Kanal = 0
> 'End If
> Return
> 

Du musst die Kanalnummer schon auf 0 setzen!
Sonst kommt da auf jedem Kanal nur 1 Puls raus!
Lass es erst mal so wie es ist (auch mit der Zuweisung an den Timer)

Das ganze lebt davon, dass die Variable Kanal nacheinander die Werte 0, 
1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, .... annimmt. Wenn du Kanal nie auf 0 
setzt ... von alleine passiert das nicht.

Da ist im Original übrigens ein Fehler.
Es muss
If Kanal = 5 then
  Timer1 = 55536
  Kanal = 0
end if

heissen, wenns 5 Servos sein sollen.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

vielen Dank!

Genau das war der Fehler. Funktioniert nun einwandfrei!

Kleiner Fehler mit großer Auswirkung ;o)
Lg
Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.