Kerzenflamme-Simulation auf einer Ledmatrix

    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!

    • tschoeatsch schrieb:

      ISR_PWM:
      If Pwmchannel(0) = Pwmcount Then Reset Pinpwm0
      If PWMChannel(1) = PWMCount then Reset PinPWM1
      If PWMChannel(2) = PWMCount then Reset PinPWM2
      If PWMChannel(3) = PWMCount then Reset PinPWM3
      If PWMChannel(4) = PWMCount then Reset PinPWM4
      If PWMChannel(5) = PWMCount then Reset PinPWM5
      If PWMChannel(6) = PWMCount then Reset PinPWM6
      If PWMChannel(7) = PWMCount then Reset PinPWM7
      Incr PWMCount
      If PWMCount > PWMCountMax then
      PWMCount = 0
      Set Porta ' Alle LED's in der Zeile An
      End If
      Return
      Ich glaube ich habe den Fehler.

      Weil alle LED's anfangs eingeschaltet werden, ist es für ein gewisse Zeit an, daher geht es nicht aus.
      War ein Denkfehler.

      Das liegt daran, weil erst beim Erreichen des PWM-Werts die LED aus geht.

      Der PWM-Count sollte vielleicht vom Maxwert nach 0 zählen.
      Und dann bei den Abfragen nicht die LED löschen, sondern einschalten.
      Du verstehst?

      BASCOM-Quellcode

      1. ISR_PWM:
      2. If Pwmchannel(0) = Pwmcount Then Set Pinpwm0
      3. If PWMChannel(1) = PWMCount then Set PinPWM1
      4. If PWMChannel(2) = PWMCount then Set PinPWM2
      5. If PWMChannel(3) = PWMCount then Set PinPWM3
      6. If PWMChannel(4) = PWMCount then Set PinPWM4
      7. If PWMChannel(5) = PWMCount then Set PinPWM5
      8. If PWMChannel(6) = PWMCount then Set PinPWM6
      9. If PWMChannel(7) = PWMCount then Set PinPWM7
      10. If PWMCount=0 then
      11. PortA=0 ' Alle LED's aus
      12. PWMCount=PWMCountMax
      13. End If
      14. Decr PWMCount
      15. Return
      Alles anzeigen

      Und diese Zeile ändern:

      Quellcode

      1. 'Const PWMCountMax = 3 ' 4 Helligkeitsstufen [0 .. 3]
      2. ' ändern in:
      3. Const PWMCountMax = 4 ' 4 Helligkeitsstufen [1 .. 4]
    • Ich werd's mal ändern. Die soft-pwm und die Ablage in den datas hat schon was. Es wäre dadurch ein 'Hinüberpolieren' (neues Wort für das Interpolieren von einem Wert zum anderen) von einen Flammenbild zu anderen leichter möglich. Das hebt den höheren Datenverbrauch für ein Bild auf, weil Zwischenbilder berechnet werden können..
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Noch eine Kleinigkeit in der soft-pwm geändert, jetzt geht sie gut. Vor der Änderung wurden die dunklen Leds bei pwmcount=0 auch kurz eingeschaltet, bevor die in der if.. wieder ausgeschaltet wurden. Man sah ein leichtes Glimmen. Jetzt ist bei Helligkeit=0 auch wirklich die Led aus

      BASCOM-Quellcode

      1. ISR_PWM:
      2. If Pwmcount = 0 Then
      3. Porta = 0 ' Alle LED's aus
      4. Pwmcount = Pwmcountmax
      5. Else
      6. If Pwmchannel(0) = Pwmcount Then Set Pinpwm0
      7. If Pwmchannel(1) = Pwmcount Then Set Pinpwm1
      8. If Pwmchannel(2) = Pwmcount Then Set Pinpwm2
      9. If Pwmchannel(3) = Pwmcount Then Set Pinpwm3
      10. If Pwmchannel(4) = Pwmcount Then Set Pinpwm4
      11. If Pwmchannel(5) = Pwmcount Then Set Pinpwm5
      12. If Pwmchannel(6) = Pwmcount Then Set Pinpwm6
      13. If Pwmchannel(7) = Pwmcount Then Set Pinpwm7
      14. End If
      15. Decr Pwmcount
      16. Return
      Alles anzeigen

      Was jetzt noch blöd ist, beim Zeilenwechsel werden ja die neuen PWM-Werte für diese Zeile eingelesen und die Zeile umgeschaltet. In dieser Zeit bleibt ja die ISR_PWM zwar nicht am Zug, die Leds leuchten aber weiter. Das heißt, der aktuelle Leuchtstand der vorhergehenden Zeile wird durch das Zeilenumschalten auf die neue Zeile übertragen, bis die ISR_PWM wieder anspringt und neue Werte liefert. Das ist mit einem Flackern sichtbar, gerade wenn die Led in der einen Zeile volle Helligkeit hat und in der unteren aus sein soll.
      Ein Abschalten der Leds in der ISR_Zeilen verhindert das Übersprechen.
      Ein flackerfreies Bild bekommt man mit jetzt mit diesem code

      BASCOM-Quellcode

      1. $Regfile = "m32def.dat"
      2. $crystal = 16000000
      3. $hwstack = 40
      4. $swstack = 32
      5. $framesize = 32
      6. '$SIM
      7. Config Base = 0 ' Arrays beginnen ab Index 0
      8. ' Ausgabe-Pins der 8 PWM Kanäle (Soft-PWM)
      9. Pinpwm0 Alias Porta.0
      10. Pinpwm1 Alias Porta.1
      11. Pinpwm2 Alias Porta.2
      12. Pinpwm3 Alias Porta.3
      13. Pinpwm4 Alias Porta.4
      14. Pinpwm5 Alias Porta.5
      15. Pinpwm6 Alias Porta.6
      16. Pinpwm7 Alias Porta.7
      17. Ddra = &HFF
      18. ' Pins für Zeilen-Auswahl
      19. Ddrc = &HFF ' Zeile 0 bis 7
      20. DDRD = &hFF ' Zeile 8 bis 15
      21. Dim PWMChannel(8) as Byte ' Array für 8 PWM-Kanäle
      22. Dim AbbildNr as Byte ' Nr. der zu zeigenden Kerzenabbildung
      23. Dim Pointer as Word
      24. Dim tmpByte as Byte ' Berechnung Offset in ISR
      25. Declare Sub CopyAbbildZeile()
      26. ' -------------------------------------------
      27. ' Generierung Zeilenfrequenz
      28. ' -------------------------------------------
      29. Dim ZeileNr as Byte ' aktuelle Zeilen-Nummer [0 .. 15]
      30. Config Timer2 = Timer , Prescale = 128 , Clear Timer = 1
      31. Ocr2 = 128 ' Zeilenfrequenz einstellen
      32. On OC2 ISR_Zeilen
      33. Enable OC2
      34. ' -------------------------------------------
      35. ' Generierung PWM
      36. ' -------------------------------------------
      37. Const Pwmcountmax = 4 ' 4 Helligkeitsstufen [0 .. 3]
      38. Dim PWMCount as Byte ' PWM-Zählerwert
      39. ' Die PWM-Frequenz
      40. Config Timer0 = Timer , Prescale = 8 , Clear_timer = 1
      41. Compare0 = 128
      42. On Compare0 Isr_pwm
      43. Enable Compare0
      44. Enable Interrupts
      45. ' ------------------------------------------------------------------------------------------------
      46. ' Hauptschleife
      47. ' ------------------------------------------------------------------------------------------------
      48. Do
      49. ' Hier kommt die Zuordnung rein, welches Kerzen-Abbild zu zeigen ist
      50. AbbildNr = 0 ' KerzenAbbild 0 anzeigen
      51. Loop
      52. ' ------------------------------------------------------------------------------------------------
      53. ' Unterprogramme
      54. ' ------------------------------------------------------------------------------------------------
      55. ' -------------------------------------------
      56. ' OC2-Interrupt Timer2
      57. ' Die Zeilen müssen nacheinander durchgeschaltet werden.
      58. ' Damit Flackerfrei müssen 16 Zeilen min. 30x je Sekunde
      59. ' angezeigt werden. Bedeutet eine Aufruf-Frequenz von
      60. ' 30x16 = 480 Hz
      61. ' -------------------------------------------
      62. ISR_Zeilen:
      63. ' Kopieren der Daten für die aktuelle Zeile in das PWM-Array
      64. Call CopyAbbildZeile()
      65. Porta = 0 ' Alle LED's aus
      66. ' Multiplexer ansteuern / Zeile aktivieren
      67. Select Case ZeileNr
      68. Case 0 : Portc = &H01 : Portd = &H00
      69. Case 1 : Portc = &H02
      70. Case 2 : Portc = &H04
      71. Case 3 : Portc = &H08
      72. Case 4 : Portc = &H10
      73. Case 5 : Portc = &H20
      74. Case 6 : Portc = &H40
      75. Case 7 : Portc = &H80
      76. Case 8 : Portd = &H01 : Portc = &H00
      77. Case 9 : PortD = &h02
      78. Case 10 : PortD = &h04
      79. Case 11 : PortD = &h08
      80. Case 12 : PortD = &h10
      81. Case 13 : PortD = &h20
      82. Case 14 : PortD = &h40
      83. Case 15 : PortD = &h80
      84. End Select
      85. Incr Zeilenr
      86. If Zeilenr > 15 Then
      87. Zeilenr = 0
      88. ' Hier kann eine Synchronisation mit dem Hauptprogramm erfolgen
      89. End If
      90. Return
      91. ' -------------------------------------------
      92. ' OVF2-Interrupt Timer0
      93. ' Hier wird die Software-PWM ausgegeben für
      94. ' die 8 Kanäle (Spalten)
      95. ' -------------------------------------------
      96. ISR_PWM:
      97. If Pwmcount = 0 Then
      98. Porta = 0 ' Alle LED's aus
      99. Pwmcount = Pwmcountmax
      100. Else
      101. If Pwmchannel(0) = Pwmcount Then Set Pinpwm0
      102. If Pwmchannel(1) = Pwmcount Then Set Pinpwm1
      103. If Pwmchannel(2) = Pwmcount Then Set Pinpwm2
      104. If Pwmchannel(3) = Pwmcount Then Set Pinpwm3
      105. If Pwmchannel(4) = Pwmcount Then Set Pinpwm4
      106. If Pwmchannel(5) = Pwmcount Then Set Pinpwm5
      107. If Pwmchannel(6) = Pwmcount Then Set Pinpwm6
      108. If Pwmchannel(7) = Pwmcount Then Set Pinpwm7
      109. End If
      110. Decr Pwmcount
      111. Return
      112. ' ----------------------------------------------
      113. ' Berechnet die anzuzeigende Abbild-Zeile und
      114. ' kopiert die Daten ins PWMChannel() Array
      115. ' ----------------------------------------------
      116. Sub Copyabbildzeile()
      117. Select Case Abbildnr
      118. Case 0 ' Abbild 0 soll angezeigt werden
      119. Restore KerzeAbbild0 '
      120. Case 1 ' Abbild 1 soll angezeigt werden
      121. Restore KerzeAbbild1
      122. ' ..
      123. ' ..
      124. End Select
      125. ' Hier greifen wir etwas in die Trickkiste, um den Offset zu berechnen
      126. ' Pointer von Restore (Abbild) in Variable 'Pointer' merken
      127. !STS {Pointer+0},r8
      128. !STS {Pointer+1},r9
      129. ' Berechnung Offset der Zeile
      130. Tmpbyte = Zeilenr * 8
      131. Pointer = Pointer + tmpByte
      132. ' Pointer zurück nach r9:r8 um ReadData zu verwenden
      133. !LDS r8,{Pointer+0}
      134. !LDS r9,{Pointer+1}
      135. ' Trickkiste wieder zu
      136. ' Daten in PWMArray kopieren
      137. Read PWMChannel(0)
      138. Read PWMChannel(1)
      139. Read PWMChannel(2)
      140. Read PWMChannel(3)
      141. Read PWMChannel(4)
      142. Read PWMChannel(5)
      143. Read PWMChannel(6)
      144. Read PWMChannel(7)
      145. End Sub
      146. ' Datenformat der Kerzen-Abbilder
      147. ' 8 Datenwerte in einer Zeile sind eine Zeile in der LED-Matrix
      148. ' 16 Zeilen ergeben so ein gesamtes Abbild
      149. Kerzeabbild0:
      150. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' 0. Zeile (oben)
      151. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' 1. Zeile (oben)
      152. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' 2. Zeile
      153. Data 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3
      154. Data 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
      155. Data 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1
      156. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      157. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      158. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      159. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      160. Data 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3
      161. Data 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
      162. Data 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1
      163. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      164. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      165. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      166. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' 15. Zeile (unten)
      167. Kerzeabbild1:
      168. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      169. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      170. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      171. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      172. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      173. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      174. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      175. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      176. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      177. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      178. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      179. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      180. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      181. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      182. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      183. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      Alles anzeigen
      Wobei die kleinste Helligkeitstufe immer noch recht hell ist, aber da kann man jetzt wenig ändern.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • tschoeatsch schrieb:

      Wobei die kleinste Helligkeitstufe immer noch recht hell ist, aber da kann man jetzt wenig ändern.
      Doch kann man.

      Du kannst der Wert PWMCountMax erhohen.
      Damit erhöhst du die möglichen Abstufungen der Helligkeit.
      Kannst ka mal 16 reinschreiben, dann ist PWMWert 1 nur 1/16tel der maximalen Helligkeit.

      Aber irgendwann kommt der Punkt, wo du die Taktfrequent des Timers erhöhen musst (Prescaler verkleinern).

      Dann solltest du die Kelligkeiten feines einstellen können in den Datazeilen.

      Eine 1 wäre ja die geringste Helligkeit. Einfach mal PWMCountMax erhöhen und schauen wann es passt.
    • Da hab' ich schon rumgespielt. Die Frequenz hab' ich sowieso schon höher schrauben müssen, sonst flackerts.
      Ich bin mir auch noch nicht im klaren, wie es weiter geht. Vielleicht eine Sammlung von Einzelbilder, die nacheinander rechnerisch überblendet werden. Bei 4 Helligkeitsstufen mit 3 Zwischenbildern.

      Was mir grad noch einfällt, die Pwm ist immernoch nicht richtig. Bei voller Helligkeit darf die Led nie aus gehen. Bei pwmcount=0 wird sie aber trotzdem mal ausgeschaltet.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • tschoeatsch schrieb:

      Da hab' ich schon rumgespielt. Die Frequenz hab' ich sowieso schon höher schrauben müssen, sonst flackerts.
      Ich bin mir auch noch nicht im klaren, wie es weiter geht. Vielleicht eine Sammlung von Einzelbilder, die nacheinander rechnerisch überblendet werden. Bei 4 Helligkeitsstufen mit 3 Zwischenbildern.

      Was mir grad noch einfällt, die Pwm ist immernoch nicht richtig. Bei voller Helligkeit darf die Led nie aus gehen. Bei pwmcount=0 wird sie aber trotzdem mal ausgeschaltet.

      Hab gesehen dass du an den Frequenzen geschraubt hast.

      PWMCountMax gibt an, wieviel Abstufungen / Schritte deine PWM hat. Auf 0 mach ja keinen Sinn! (0 Schritte = PWM mit 0 Bit)

      Wenn du da 16 angibt, hast du 16 mögliche Helligkeitsstufen.
      Gibst du da 8 ein, dann eben nur 8 Helligkeitsstufen.
      Du kannst damit die PWM frei einstellen (in Grenzen).

      In der ISR_PWM wird ja festgelegt, wie die LED's geschaltet werden. Da kannst du ja die IF-Abfragen anpassen.
      Es ist auch ein Unterschied, ob du von 4 bis 1 oder bis 0 zählst. Und wann du den PWMCount dekrementierst.

      Wenn die LED bei voller Helligkeit ausgeht, wie meinst du das?

      Du gibst PWMCountMax=4 ein und bei den Data-Werten auch 4? Dann geht die LED aus?
      Oder was genau meinst du?
    • Mitch64 schrieb:

      Du gibst PWMCountMax=4 ein und bei den Data-Werten auch 4? Dann geht die LED aus?
      Oder was genau meinst du?
      so ist es, bei dem obigen code.
      Besser ist dieser

      BASCOM-Quellcode

      1. Const Pwmcountmax = 3
      2. ISR_PWM:
      3. Porta = 0
      4. If Pwmchannel(0) > Pwmcount Then Set Pinpwm0
      5. If Pwmchannel(1) > Pwmcount Then Set Pinpwm1
      6. If Pwmchannel(2) > Pwmcount Then Set Pinpwm2
      7. If Pwmchannel(3) > Pwmcount Then Set Pinpwm3
      8. If Pwmchannel(4) > Pwmcount Then Set Pinpwm4
      9. If Pwmchannel(5) > Pwmcount Then Set Pinpwm5
      10. If Pwmchannel(6) > Pwmcount Then Set Pinpwm6
      11. If Pwmchannel(7) > Pwmcount Then Set Pinpwm7
      12. If Pwmcount = 0 Then
      13. Pwmcount = Pwmcountmax
      14. End If
      15. Decr Pwmcount
      16. Return
      Alles anzeigen
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Probier's mal so:

      BASCOM-Quellcode

      1. ISR_PWM:
      2. If PwmCount > 0 Then
      3. If Pwmchannel(0) = Pwmcount Then Set Pinpwm0
      4. If Pwmchannel(1) = Pwmcount Then Set Pinpwm1
      5. If Pwmchannel(2) = Pwmcount Then Set Pinpwm2
      6. If Pwmchannel(3) = Pwmcount Then Set Pinpwm3
      7. If Pwmchannel(4) = Pwmcount Then Set Pinpwm4
      8. If Pwmchannel(5) = Pwmcount Then Set Pinpwm5
      9. If Pwmchannel(6) = Pwmcount Then Set Pinpwm6
      10. If Pwmchannel(7) = Pwmcount Then Set Pinpwm7
      11. Else
      12. Porta = 0 ' Alle LED's aus
      13. End If
      14. If PWMCount = 0 then
      15. PwmCount = PwmCountMax
      16. End If
      17. Decr PwmCount
      18. Return
      Alles anzeigen
      PWMCountMax mit Zählweise ab 1 angeben (4 = 4 Helligkeitsstufen)

      DataWerte 0 - 3 angeben.
    • Spiel's mal durch, data wäre 3
      Bei pwmcount=3 Led an
      bei pwmcount=2 Led noch an
      bei pwmcount=1 Led noch an
      bei pwmcount=0 Led geht aus und erst bei der nächsten isr wieder an. :huh:

      Bei meiner Version geht die Led zwar immer aus, aber gegebenenfalls sofort wieder an. :D
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ja hier ist Grips-Gymnastik gefragt.

      Im Moment fällt mir nix besseres ein.

      Wenn du bei PWMCount=0 die LED's nicht hart ausschaltest, würde beim PWMWert = 0 ja die LED'wieder angemacht,
      weil PWMCount = PWM-Wert ist.

      Sie soll aber aus bleiben.

      Der einzige Nachteil ist, dass du nur 3 Zeiteinheiten von 4 als max. Helligkeit bekommst.
      Bei 50 wären es 49 von 50.

      Aber wenn der PWM-Wert = 0 ist, bleibt die LED aus.
    • Eine Lösung habe ich noch:

      BASCOM-Quellcode

      1. ISR_PWM:
      2. If PWMCount = 0 then
      3. PortA = &hFF ' Alle LED's ausschalten
      4. End If
      5. If PWMCount = PWMChannel(0) then Reset pinPWM0
      6. If PWMCount = PWMChannel(1) then Reset pinPWM1
      7. If PWMCount = PWMChannel(2) then Reset pinPWM2
      8. If PWMCount = PWMChannel(3) then Reset pinPWM3
      9. If PWMCount = PWMChannel(4) then Reset pinPWM4
      10. If PWMCount = PWMChannel(5) then Reset pinPWM5
      11. If PWMCount = PWMChannel(6) then Reset pinPWM6
      12. If PWMCount = PWMChannel(7) then Reset pinPWM7
      13. Incr PWMCount
      14. If PWMCount >= PWMCountMax then
      15. PWMCount = 0
      16. End If
      17. Return
      Alles anzeigen
      Bei Wert 0 werden zwar alle LED's eingeschaltet, werden aber sofort wieder ausgemacht, wenn PWM-Wert 0 ist. Bei LED-PWM sollte das nicht stören. Das Aufleuchten ist so kurz, das wird das Auge nicht erfassen.

      Wenn das stört hätte ich noch ne Idee.

      Aber probier das mal aus.
    • Merksatz: Ein kurzes Ausschalten einer Led ist unauffälliger als ein kurzes Einschalten.
      kurzes-Ausschalten.jpgkurzes-Einschalten.jpg
      Jetzt sind die Einschaltimpulse wirklich nicht lang, aber trotzdem sichtbar.

      Ich mach' jetzt mal bei dem Thema 'Künstliche Flamme' eine kreative Pause. Ich warte jetzt auf eine Eingebung, wie ich am leichtesten verschiedene Flammenbilder in das Programm bringe und nacheinander abspielen kann. a_221_2cffa601
      Raum für Notizen

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

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