'Slowmotion frames' und deren Umsetzung

    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!

    • Hallo Tschoeatsch,
      warum benutzt du für die PWM nicht die Hardware? Ich denke, das der Fast-PWM Modus genau das machen würde, was du hier mit den Interrupts und zusätzlicher Steuerung über die Variable Bereit selber programmiert hast. Sehe ich im Moment noch nicht den Sinn.
      Außerdem kann der eine Interrupt den anderen etwas verzögern, wenn auch nur wenig.
      Aber ich würde das definitiv in Hardware machen, dann hättest du überhaupt keine Interrupts und könntest die Werte für Fequenz und ED einfach irgendwann setzen. Durch das Buffern werden die erst beim Erreichen des Top Wertes übernommen.
      Allerdings müsstest du dann die Ausgänge OC0B und OC1B verwenden.
    • Du verwendest für fast alle deine Programme die Timer, eigentlich auch immer im CTC oder PWM Modus.
      Solltest du lieber mal etwas Zeit investieren, um das zu verstehen, dann sind die nächsten Programme einfacher. Dann musst du nämlich nicht mit einem Standard Timer solche HW Funktionalität nachbilden.
      Was dann meistens auch mit Kompromissen (hier die Blitze) verbunden ist.
    • Ein kleine Ergänzung zur Verwendung der Timer Hardware, wenn zur Laufzeit Timerregister geändert werden.

      Die Timer-Hardware generiert, wie bekannt, die gewünschten Impulse bzw. Impulsfolgen, ohne dass eine laufende Programm-Loop dadurch behindert wird, aber völlig asynchron zur Programm-Loop. Diese Asynchronität führt dazu, dass Blitze auftreten können, immer zu dem Zeitpunkt, wenn das laufende Programm die Timerregister ändert und die Timer-Hardware gerade den Impuls ausgeben will.

      Die Timerregister sollten nur dann beschrieben werden, wenn die Timer-Hardware die Impuls-Ausgabe abgeschlossen hat.
    • Sagst du so leicht! Zeitweise vergess' ich schneller, als ich dazu lerne. Jetzt, wo ich ctc so leidlich verinnerlicht hab', soll ich was neues Lernen und du lockst mich dazu, dass ich es in Zukunft leichter hab'. Ich weiß das jetzt schon, in der Zukunft muss ich das wieder lernen, weil ich alles vergessen hab'. Meine Erfahrung sagt mir das. Aber gut, ich will nicht bockig erscheinen, ich schau mit das Datenblatt und Ulrichs thread noch mal an...

      Zu Ulrichs Ergänzung:
      dann müsste man vor der Änderung des Registers einen passenden interrupt einschalten und auf den warten, dann Register schreiben und interrupt wieder aus.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ulrich schrieb:

      Diese Asynchronität führt dazu, dass Blitze auftreten können, immer zu dem Zeitpunkt, wenn das laufende Programm die Timerregister ändert und die Timer-Hardware gerade den Impuls ausgeben will.
      Das hat Atmel auch bedacht und dafür die OCR Register gebuffert.
      Außer im CTC Modus werden die neuen Werte erst beim Erreichen der TOP bzw. Bottom Werte übernommen. Dadurch sind die Blitze in den PWM Modi ausgeschlossen, weil es eben doch wieder synchron geht.
      Im CTC Modus muss man eben im Compare Interrupt schreiben. Führt dann aber dazu, dass bei ganz kurzen Impulsen, also sehr kleinen Compare Werten, dass Aufrufen der ISR schon zu lange dauern kann.

      Aber wie gesagt, hier würde ich Fast-PWM benutzen, dann hast du damit keine Probleme.

      Edit: Muss das hier
      If Hell < 100 Then Hell = 100
      nicht so sein?
      If Hell > 100 Then Hell = 100

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

    • Was mich bisschen bremst/stört ist dieses 'Zusammenklauben' der bits für die Register. Der bascom-Befehl config timer=pwm...prescale.. macht das ja leicht, aber halt nur für einen bestimmten Modus. Jetzt müsste nach diesem Befehl doch nur die bits gesetzt werden, damit compare1a als der top-Wert verwendet wird, oder?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ja genau:
      Config Timer1 = Pwm , Prescale = 8 , Compare_b_pwm = Clear_up
      Set Tccr1a.wgm11 'mit normalen PWM (WGM1=&b0001) wird daraus
      Set Tccr1b.wgm12 'WGM1=&b1111 = FAST-PWM mit OCR1A as Top
      Set Tccr1b.wgm13

      Ein kleiner Haken noch: Der Start Timer Befehl kümmert sich leider nicht um die Bits, die zwischenzeitlich gesetzt worden sind. Daher muss man danach die Bits wieder setzen.
    • Ist das mit config bei 10bit dann mode 7? Und ich brauch dann hier mode 15?

      Dass das Register gepuffert ist, erkennst du das an dem 'update of OCR1x at bottom'?
      (Tabelle 16-4 Seite 132/133)
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Wenn du kein PWM=8,9,10 angibst, dann ist 8 der Default, also Modus 1. Gibst du 10 an, ist das Modus 3, du musst dann nur noch WGM12 und WGM13 setzen.

      Das Double-Buffering steht irgendwo im Text darüber, aber die Spalte zeigt dir das an.
      Bei PWM zählt der Timer ja erst rauf, dann wieder runter. Bei einem match wird eingeschaltet, beim anderen aus. Nimmst du einen Mode, wo OCR1x im TOP Wert gesetzt wird, dann wird beim runterzählen bei dem neuen Match umgeschaltet, deswegen ist das nicht Frequenz-korrekt.
      Bei BOTTOM macht der Timer erst die ganze Periode zu Ende, bevor die Werte geändert werden.
    • War ich immer auf dem falschen Dampfer, ich dachte bislang mit dem config wird fast pwm aktiviert?
      Ist ja jetzt eine ziemliche Lehrstunde für mich, hoffentlich kann ich mir das größtenteils merken a_27_b277ca12
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • hero schrieb:

      Das hat Atmel auch bedacht und dafür die OCR Register gebuffert.
      Ein genialer Hinweis, das ist genau ein Grund, warum es den Fast-PWM Mode gibt, nämlich das es keine solchen Synchronisationsprobleme geben kann.

      In meinem Slomo-Programm verwende ich den WGM 8 Modus, d.h. "Phase and Frequency correct" und habe dabei eben festgestellt, dass es eine Schwebung bei den Blitz-Eindrücken gab. Meine Abhilfe (keine Blitze) war es, das Impulsende (definiert durch Output Compare B) abzuwarten und unmittelbar danach erst die Timer-Register zu ändern.

      Wenn sich diese zusätzliche Synchronisation durch Verwendung des Fast PWM Mode vermeiden läßt, würde sich die Sache schon etwas vereinfachen. Werde ich in den nächsten Tagen testen.

      Im Prinzip ist meine zusätzliche Synchronisation auf das Impulsende, das gleiche, was auch im Fast PWM mode geschieht. Die Übernahme der neuen Registerwerte bei Erreichen von Bottom geschieht ja bei Fast-PWM genau auch zum Zeitpunkt des Impulsendes, wenn man sich die Sägezahnbilder vor Augen führt, da nach Top die steile Flanke nach Bottom erfolgt.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Ulrich ()

    • Double buffering gilt für alle PWM Modi, dein Problem wird also woanders liegen.
      Evtl in deinen Befehlen zur Synchronisation. Müsste man in deinem Programm mal analysieren.

      ICR1 in deinem Mode 8 ist übrigens nicht gebuffered sondern wird direkt gesetzt.

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

    • @hero

      Meine Antwort bezog sich auf deinen gesamten Hinweis diesbezüglich, nicht nur auf das double Buffering, ich hatte ich nicht deinen kompletten Hinweis zu zitiert, sorry.


      Wie ich verstehe, wenn die Timer-Register at Bottom aktualisiert werden, ist eine Synchronisation von Haus aus gegeben.
      Sowohl im "Fast-PWM Mode" als auch im "Phase-and-Frequency-correct Mode" werden die Timer1 Register at Bottom übernommen, also jedesmal zu Beginn einer Periode. Somit hätte es keine Unsynchronität geben dürfen.

      Die Untersuchung der Blitz-Eindrücke jedoch hatte ergeben, dass die Impulsbreite periodisch (Schwebung) von min. bis max. der definierten Breite schwankte. Meine Abhilfe war die Synchronisation (d.h. Zeitpunkt der Timer1 Register Beschreibung).
      Diese Synchronisation ist einfach, aber wie ich meine wirkungsvoll. Dazu habe ich den LED-Fet Ansteuerimpuls zusätzlich auf einen freien Pin, hier "LED_Signal" genannt, verdrahtet und diesen innerhalb der Programm-Loop mit den beiden zusätzlichen Bitwait-Befehlen abgefragt. Danach blieb die Impulsbreite stabil und die Blitz-Effekte waren verschwunden.

      Bitwait Led_signal , Set 'Warten auf Led-Impuls
      Bitwait Led_signal , Reset 'Impulsende war da

      Icr1h = High(timer1_icr1a)
      Icr1l = Low(timer1_icr1a)

      Compare1a = Led_dauer_int 'ist mit ADC1 variabel, obere Schwelle

      'Print "Compare1a = " ; Compare1a ; " ==>Schwelle Impulsbreite Timer1"


      Deshalb ist mir noch nicht ganz klar, was zu den Blitz-Erscheinungen geführt haben könnte.
    • So, ich hab' jetzt mein Programm auf fast PWM umgestellt, es läuft jetzt ohne interrupts

      BASCOM-Quellcode

      1. 'fast PWM
      2. $regfile = "m168pdef.dat"
      3. $crystal = 16000000
      4. $hwstack = 34
      5. $swstack = 32
      6. $framesize = 64
      7. Led Alias Portb.2 'OC1B-Ausgang
      8. Config Led = Output
      9. Magnet Alias Portd.5 'OC0B-Ausgang
      10. Config Magnet = Output 'Pwm-Ausgang
      11. Pot_frequenz Alias Pinc.0 'Poti Blitzfrequenz
      12. Config Pot_frequenz = Input
      13. Pot_amplitude Alias Pinc.1 'Poti Amplitude
      14. Config Pot_amplitude = Input
      15. Config Adc = Single , Prescaler = Auto , Reference = Avcc
      16. Ende_magnet Alias Compare0b
      17. Magnet_frequenz Alias Compare0a
      18. Ende_blitz Alias Compare1b
      19. Blitz_frequenz Alias Compare1a
      20. Config Timer0 = Pwm , Prescale = 1024 , Compare_b_pwm = Clear_up
      21. Tccr0a.1 = 1 : Tccr0b.3 = 1 '8bit fast PWM compare0a=top-Wert
      22. Config Timer1 = Pwm , Pwm = 10 , Prescale = 8 , Compare_b_pwm = Clear_up
      23. Tccr1b.3 = 1 : Tccr1b.4 = 1 '10bit fast PWM compare1a=top-Wert
      24. Dim Blitz_frequenz_start As Word
      25. Blitz_frequenz_start = 32768 + 2000
      26. Dim Magnet_frequenz_start As Byte
      27. Magnet_frequenz_start = 255
      28. Dim Freq As Word , Frequenz_l As Word , Frequenz_m As Byte 'Grundfrequenz
      29. Dim Led_frequenz As Word 'feineinstellung Led-Frequenz
      30. Dim Amplitude As Word , Amp As Dword 'ED-Magnet
      31. Dim Helligkeit As Word , Hell As Dword 'ED-Led
      32. Dim Versatz_ist As Word , Versatz_soll As Word , Zufall As Word
      33. Dim Versatz_ist_ As Word
      34. Dim Bereit As Bit , Z As Byte
      35. Versatz_ist = 100
      36. Versatz_soll = 100
      37. Do
      38. Zufall = Rnd(200)
      39. Freq = Getadc(0) 'Grundfrequenz einstellung lesen
      40. Freq = Freq / 10 'Wertebereich 0..102
      41. Frequenz_m = Freq
      42. Frequenz_l = Freq * 128
      43. Magnet_frequenz = Magnet_frequenz_start - Frequenz_m 'compare-Wert neu festsetzen
      44. Led_frequenz = Getadc(1) 'Schwebungsfrequenz
      45. Select Case Led_frequenz
      46. Case Is < 10 : Gosub Breakdance
      47. Case 10 To 20 : Gosub Schwebung_slow 'zufällige Änderungen
      48. Case 21 To 1013 : Gosub Schwebung_manuell
      49. Case Is > 1013 : Gosub Schwebung_fast 'zufällige Änderungen
      50. End Select
      51. Amplitude = Getadc(2) 'Stärke derSchwingung
      52. Amplitude = Amplitude / 20 'Wertebereich 0..51
      53. Amp = Magnet_frequenz
      54. Amp = Amp * Amplitude
      55. Amp = Amp / 100
      56. If Amp < 10 Then Amp = 10
      57. Ende_magnet = Amp 'compare-Wert neu festsetzen
      58. Helligkeit = Getadc(3) 'Helligkeit
      59. Helligkeit = Helligkeit / 20 'Wertebereich 0..51
      60. Hell = Blitz_frequenz
      61. Hell = Hell * Helligkeit
      62. Hell = Hell / 1000
      63. If Hell < 100 Then Hell = 100
      64. Ende_blitz = Hell 'compare-Wert neu festsetzen
      65. Blitz_frequenz = Blitz_frequenz_start - Frequenz_l 'compare-Wert neu festsetzen
      66. If Helligkeit < 10 Then 'Ausschalten
      67. Else
      68. End If
      69. Waitms 100
      70. Loop
      71. End
      72. Breakdance:
      73. If Z > 8 Then 'Z zählt den Durchlauf der main als Verzögerung der Aktion
      74. Z = 0
      75. Versatz_ist_ = Zufall * 20
      76. Frequenz_l = Frequenz_l + Versatz_ist_ 'der Versatz zwischen Blitz und Magnet wird zufällig verändert
      77. Else
      78. Incr Z
      79. Frequenz_l = Frequenz_l + 2000 'hier sind Blitz und Magnet auf gleicher Frequenz
      80. End If
      81. Return
      82. Schwebung_manuell: 'die Schwebung (sichtbare langsame Bewegung des Objekts) wird mit dem Poti eingestellt
      83. Led_frequenz = Led_frequenz * 4
      84. Frequenz_l = Frequenz_l + Led_frequenz
      85. Return
      86. Schwebung_slow:
      87. If Versatz_ist = Versatz_soll Then Versatz_soll = Zufall 'die Schwebung verändert sich zufällig
      88. If Versatz_ist < Versatz_soll Then Incr Versatz_ist
      89. If Versatz_ist > Versatz_soll Then Decr Versatz_ist
      90. Versatz_ist_ = Versatz_ist * 20 'Versatz_ist_ soll einen Wert 0..4000 annehmen
      91. Frequenz_l = Frequenz_l + Versatz_ist_
      92. Return
      93. Schwebung_fast:
      94. If Versatz_ist = Versatz_soll Then Versatz_soll = Zufall 'die Schwebung verändert sich zufällig
      95. If Versatz_ist < Versatz_soll Then Incr Versatz_ist
      96. If Versatz_ist > Versatz_soll Then Decr Versatz_ist
      97. If Versatz_ist < Versatz_soll Then Incr Versatz_ist
      98. If Versatz_ist > Versatz_soll Then Decr Versatz_ist
      99. Versatz_ist_ = Versatz_ist * 20
      100. Frequenz_l = Frequenz_l + Versatz_ist_
      101. Return
      Alles anzeigen
      Was jetzt noch fehlt, ist meine Ausschaltfunktion. Vorher konnte ich ja ganz einfach den interrupt ausschalten und war eigentlich fertig. Geht jetzt nicht mehr. Wenn ich jetzt die OC1b und OC0b -Ausgänge per Registermanipulation auf normale Ausgänge umschalte, wäre das vernünftiges, oder macht man das anders besser?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Bei dieser Gelegenheit ist mir aufgefallen, dass die Registerbezeichnungen irgendwie nicht so passen.
      Im Editor schaut es so aus
      RegisterEditor.PNG
      da gibt es das TCCR0A und ein TCCR0B, wird aber nicht hervorgehoben, wie das TCCR1B. Die Bezeichnungen passen mit dem Datenblatt zusammen.
      Im Simulator schaut das so aus
      RegisterSimulator.PNG
      da gibt's jetzt das TCC0B nicht, setzt man bits im TCCR0B, werden die bei TCCR0 angezeigt. 8|
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ja, mit
      Reset Tccr0a.com0a1 '0C0B abschalten
      Reset Tccr1a.com1a1 '0C1B abschalten
      und einschalten mit
      Set Tccr0a.com0a1 '0C0B abschalten
      Set Tccr1a.com1a1 '0C1B abschalten

      @Ulrich Zeige doch mal dein Programm, wie du es jetzt benutzt. In dem anderen Thread sind mehrere enthalten, sodass nicht klar ist, welches aktuell ist.
      Vielleicht auch noch die Version, bei der die Blitze auftreten.
    • hero schrieb:

      Ja, mit
      Reset Tccr0a.com0a1 '0C0B abschalten
      Reset Tccr1a.com1a1 '0C1B abschalten
      und einschalten mit
      Set Tccr0a.com0a1 '0C0B abschalten
      Set Tccr1a.com1a1 '0C1B abschalten
      fast, nur muss ich Kanal 'b' nehmen. Es funktioniert :thumbsup:
      Raum für Notizen

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

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