Allgemeine Frage zum Timing im Programmablauf (Anfänger)

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Allgemeine Frage zum Timing im Programmablauf (Anfänger)

      Hallo,

      nach langen entwickeln einer Platine mit Eagle ist folgendes herausgekommen.
      Atmega2560, SPI EEprom, drei Schrittmotortreiber L293D, sieben Servos, Spannung und Stromüberwachung durch den ADC Converter und 10 Ausgänge.
      Den jungfräulichen Controller konnte ich die Frequenz auf 16MHz einstellen. Über USBASP ging es schließlich. (Frage von damals...)

      Konnte durch ein kleines Programm die Ausgänge schalten.
      Durch ein anderes Programm konnte ich an jeden Servoausgang ein "zuckeln" des Servos entlocken.

      ist es möglich alles zu benutzen?
      Die Servos brauchen doch eine Refresh Rate von 20ms.
      Dann habe ich zeit während dessen das "andere" mit Daten zu versorgen?
      (16Mhz minus 20ms der Servos = 340.000 Befehle noch schnell dazwischen auszuführen ?

      Oder wie ist das wenn ich den Timer benutze für die Servos?
      Läuft das als Unterprogramm im Hintergrund ab?
      Und ich muss nur "ab und zu" dahin springen um andere Werte für die Servos mitzuteilen?

      Ist es eine Sache des geschickten programmieren und ineinander verschachteln ?

      Später soll die Platine per Bus die Befehle bekommen..

      Bismar
    • Ich würde für die Servos auf jeden Fall einen timer (16bit) benutzen.Dabei ist es wirklich so, dass du nur die sich ändernden Daten neu schreiben musst. Ich hab' das bei meiner Mobsepu mit 3 Servos eingesetzt, sehe aber keinen Grund, warum das nicht auch mit 7 Servos geht. Bei Bedarf kann ich dir den code extrahieren. Es läuft im Hintergrund als interrupt-Routine und man braucht nur Variable ändern.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Hier mal der code für 3 Servos. Ich denke eine Erweiterung auf mehr Servos ist nicht schwer, wenn du dennoch Probleme hast, einfach sagen.

      BASCOM-Quellcode

      1. $regfile = "m8def.dat"
      2. $crystal = 16000000
      3. $hwstack = 64
      4. $swstack = 32
      5. $framesize = 30
      6. Config Timer1 = Timer , Prescale = 8 , Clear_timer = 1 '2000 Takte für 1 msec
      7. On Compare1a Timer1_isr
      8. Start Timer1
      9. Enable Interrupts
      10. Compare1a = 3000 'Startwert
      11. Enable Compare1a
      12. Config Portc = Output
      13. Servoport Alias Portc
      14. Dim Compare_rest As Word
      15. Dim Servo1 As Word
      16. Dim Servo2 As Word
      17. Dim Servo3 As Word
      18. Dim Zaehler As Byte
      19. 'Startwerte
      20. Servo1 = 3000 'ergibt 1,5msec=Mittelstellung
      21. Servo2 = 3000
      22. Servo3 = 3000
      23. Compare_rest = 40000 'Gesamtlänge der Pulskette, hier 20msec
      24. Do
      25. Loop
      26. End
      27. Timer1_isr: 'Erzeugung der Pulse für die Servos
      28. Select Case Zaehler
      29. Case 0 :
      30. Compare1a = Servo1 'min 1 msec bis max 2 msec
      31. Servoport.0 = 1
      32. Compare_rest = Compare_rest - Compare1a 'Restwert für 20msec
      33. Incr Zaehler 'Pulsnummer hochzählen
      34. Case 1 :
      35. Compare1a = Servo2
      36. Servoport.1 = 1
      37. Servoport.0 = 0
      38. Compare_rest = Compare_rest - Compare1a 'Restwert für 20msec
      39. Incr Zaehler
      40. Case 2 :
      41. Compare1a = Servo3
      42. Servoport.2 = 1
      43. Servoport.1 = 0
      44. Compare_rest = Compare_rest - Compare1a 'Restwert für 20msec
      45. Incr Zaehler
      46. Case 3 :
      47. Compare1a = Compare_rest 'Rest zu 20msec Pause
      48. Servoport.2 = 0
      49. Compare_rest = 40000
      50. Zaehler = 0
      51. End Select
      52. Return
      Alles anzeigen
      In der Variablen Servox steht der Wert für den Drehwinkel vom Servo x drin. Beim 1. Aufruf der timer1_isr (nach 3000 timertakte als Startwert), wird der pin für den Servo 1 gesetzt und bleibt solange, bis die Anzahl der timertakte aus Servo1 abgelaufen sind. Dadurch, dass Zaehler jetzt=1 ist, wird der pin auf 0 gesetzt und der pin von Servo 2 wird gesetzt... Nebenher werden die Pulslängen der Servos von den 20msec abgezogen, dass nach der Bedienung aller Servos ein Restzeit abläuft, sodass jeder Servo nur alle 20msec seinen Puls bekommt.

      Schau auch mal hier mikrocontroller.net/articles/M…vos_mittels_Timer_.28C.29, da ist es auch beschrieben.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von tschoeatsch ()

    • Hallo,
      dein Programm funktioniert tadelos im Simulator.
      Habe die reg Datei auf ATMega2560 geändert.

      Schon funktioniert es nicht mehr.
      Fehlermeldung
      bei Zeile Zähler = 0

      bei einen anderen codeschnipsel den ich gefunden habe, hängt das Programm im ISR des Zähler fest...

      Diese Meldung hatte ich auch bei deinem Programm.
      " Interrup need return"

      Hatte schon mal das Problem mit PCint..
      Programme auf mega8 müssen nicht auf 2560 zum laufen gebracht werden...
      Da gibt es eine andere Befehls Struktur - die ich erst mal suchen muß.

      Aber besten Dank.
    • Beim compilieren werden ja diverse Dateien erzeugt. Lösche mal alle außer der .bas-Datei. Dann noch mal compilieren und testen.

      Die erzeugten Fehlermeldungen wären schon interessant, also nicht nur schreiben 'es gibt eine Fehlermeldung', sondern auch die Meldung hier zeigen :rolleyes: Oder war 'interrupt need return' die einzige Meldung?
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von tschoeatsch ()

    • Ich hab's jetzt selber mal probiert, dieses Programm

      BASCOM-Quellcode

      1. 'Servo-Test
      2. $regfile = "m2560def.dat"
      3. $crystal = 16000000
      4. $hwstack = 64
      5. $swstack = 32
      6. $framesize = 30
      7. Config Timer1 = Timer , Prescale = 8 , Clear_timer = 1 '2000 Takte für 1 msec
      8. On Compare1a Timer1_isr
      9. Start Timer1
      10. Enable Interrupts
      11. Compare1a = 3000 'Startwert
      12. Enable Compare1a
      13. Config Portc = Output
      14. Servoport Alias Portc
      15. Dim Compare_rest As Word
      16. Dim Servo1 As Word
      17. Dim Servo2 As Word
      18. Dim Servo3 As Word
      19. Dim Zaehler As Byte
      20. 'Startwerte
      21. Servo1 = 3000 'ergibt 1,5msec=Mittelstellung
      22. Servo2 = 3000
      23. Servo3 = 3000
      24. Compare_rest = 40000 'Gesamtlänge der Pulskette, hier 20msec
      25. Dim Wert As Word
      26. Config Adc = Single , Prescaler = Auto , Reference = Avcc
      27. Do
      28. Wert = Getadc(0)
      29. Wert = Wert * 2
      30. Wert = 2000 + Wert 'Wertebereich 2000...4048
      31. Servo1 = Wert
      32. Servo2 = Wert
      33. Servo3 = Wert
      34. Waitms 100
      35. Loop
      36. End
      37. Timer1_isr: 'Erzeugung der Pulse für die Servos
      38. Select Case Zaehler
      39. Case 0 :
      40. Compare1a = Servo1 'min 1 msec bis max 2 msec
      41. Servoport.0 = 1
      42. Compare_rest = Compare_rest - Compare1a 'Restwert für 20msec
      43. Incr Zaehler 'Pulsnummer hochzählen
      44. Case 1 :
      45. Compare1a = Servo2
      46. Servoport.1 = 1
      47. Servoport.0 = 0
      48. Compare_rest = Compare_rest - Compare1a 'Restwert für 20msec
      49. Incr Zaehler
      50. Case 2 :
      51. Compare1a = Servo3
      52. Servoport.2 = 1
      53. Servoport.1 = 0
      54. Compare_rest = Compare_rest - Compare1a 'Restwert für 20msec
      55. Incr Zaehler
      56. Case 3 :
      57. Compare1a = Compare_rest 'Rest zu 20msec Pause
      58. Servoport.2 = 0
      59. Compare_rest = 40000
      60. Zaehler = 0
      61. End Select
      62. Return
      Alles anzeigen
      compiliert fehlerfrei. Auf einen Arduino mega aufgespielt funktioniert es auch. Bei meinem Versuchsaufbau hatte ich aber keine saubere Trennung von Servo-Versorgung und Kontrollerversorgung, aber ich konnte, zwar nicht sehr zuverlässig, weil die Spannung einbrach, mit dem Poti am ADC0-Eingang das Servo steuern.


      Bisamr schrieb:

      Da gibt es eine andere Befehls Struktur
      das ist für mich neu. Verwechselst du das mit xmegas?
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Hallo zusammen,
      das Programm vontschoeatsch funktioniert einwandfrei,
      so habe ich vor einigen Jahren den Quadwalker (aus elv-Heft) mit 8 Servos betrieben.
      ...habe übrigens gerade was gelernt mit den Interrupts.

      Ich kannte es bisher nicht :
      On Compare1a Timer1_isr

      bisher habe ich immer "on Timer1" verwendet.
      muss man den Timer extra starten - hatte ich bisher nie gemacht
      hahae immer enable timer1 und enable interrupts verwendet

      Ist doch gut, ab und zu mal anderen über die Schulter zu schauen :)

      Den letztenTimer (Comparerest) für die "20ms" hatte ich übrigens testweise mal weggelassen: Funktioniert mit den "billigservos" auch.
    • Hallo Frank,
      das sind zwei verschiedene Interrupts, Timer1 und Compare1A.
      Timer1 ist ein Synonym für den Overflow Interrupt OVF1, der ausgelöst wird, wenn der Timer seinen Top Wert erreicht.
      Neben dem Interrupt gibt es keine weiteren Aktionen.
      Compare1A funktioniert etwas anders. Da gibst du einen Vergleichswert Wert vor (der leider zur Verwirrung auch wieder Compare1A heißt).
      Erreicht der Timer diesen Wert und ist in der Timer Config "Clear_Timer=1" angegeben, dann wird auch ein Interrupt ausgelöst und der Timer geht auf 0.
      Zusätzlich kann die Hardware aber noch einen Ausgangspin (in diesem Fall OC1A) setzen, zurücksetzen oder umschalten. Dazu wird keine Interrupt Ausführung benötigt.
      Ist sehr praktisch, wenn du bestimmte Ausgangssignale an dem Pin erzeugen willst.
      Wenn dies mit hoher Frequenz, also z.B. schneller als 1/100 des Systemtaktes sein soll, dann wird das mit Interrupt und Umschalten in der ISR nicht funktionieren.
      PWM funktioniert ganz ähnlich, nur das dabei der Timer bei Erreichen des Vergleichswertes nicht auf 0 zurückspringt.