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!

    • Kerzenflamme-Simulation auf einer Ledmatrix

      Vor Jahren hat ja mal ein Künstler die 'Kerze 2.0' (weiß jetzt nicht seinen Titel, evtl. 'my new flame', oder so) entwickelt und auch zum Kauf angeboten.

      Vor ein paar Jahren hab' ich die auch entdeckt und für interessant befunden, aber nicht weiter darüber nachgedacht, wie man sowas mit bascom machen könnte. Jetzt hab' ich drüber nachgedacht, bin aber nicht fertig geworden. Meine bisherigen Erkenntnisse wären:
      Die Ledmatrix (8 Spalten und 16 Reihen = 128 Leds) aus warmweißen Leds werden per Multiplex angesteuert. Ein paar Helligkeitsstufen, 4 könnten schon reichen, bei dem Raster ist der Randbereich sowieso nicht breit, sollten sein, um eine allzu scharfe Abgrenzung zu vermeiden. Soft-pwm in der üblichen Art mit if- Abfragen bei 128 Leds, wird nicht schnell genug gehen. Mein Gedanke dazu wäre so: die Matrix wird spaltenweise angesteuert, 2 komplette ports steuern alle 16 Reihen an, durch einen weiteren port, mit einem ULN-Treiber verstärkt, werden einzelne Spalten angesteuert. Es leuchten also bis zu 16 Leds gleichzeitig, nach Durchschalten der 8 Spalten ist ein Bild komplett dargestellt. Der Inhalt wird dazu in 8 words oder 16 bytes vorgehalten. Jedes bit aus diesem Speicherarray entspricht einer Led. Jetzt geht nur an oder aus. Reiht man aber noch 3x solche array dazu, die nacheinander ausgegeben werden, hat man pro Led 4 bits, deren Zustand die mittlere Helligkeit der Led bilden. Alle bits=0, Led dunkel, 1 bit=1, Led leuchtet mit 1/4 Helligkeit, 2 bits gesetzt, halbe Helligkeit, na ja, so geht's halt weiter. Man muss also nur! das gewünschte Bild in die 4 Speicherarrays schreiben, wobei unterschiedliche Bilder die Helligkeitsabstufungen erzeugen. Je öfter ein bit dabei gesetzt wird umso heller leuchtet die betreffende Led. Da man aber nur 4x16=64 bytes bearbeiten muss, sollte sich das auch zeitlich machen lassen.
      Die isr für das Multiplexen muss nur 3 bytes in einem Durchgang an die ports senden. Wenn jetzt 30 Komplettbilder mit 4 Helligkeitsstufen pro Sekunde angezeigt werden sollen, dann müsste die isr pro Sekunde 8Spalten x 4Helligkeitsbilder x 30Gesamtbilder = 960 mal pro Sekunde aufgerufen werden. Das klingt jetzt auch nicht so dramatisch.

      Wo ich aber noch nicht groß weiter gekommen bin, wie bekommt man jetzt ein wechselndes Bild der Flamme in den Bildspeicher, samt den Helligkeitsabstufungen.
      Welche Ideen hättet ihr denn?
      Raum für Notizen

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

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

      Wo ich aber noch nicht groß weiter gekommen bin, wie bekommt man jetzt ein wechselndes Bild der Flamme in den Bildspeicher, samt den Helligkeitsabstufungen.
      Welche Ideen hättet ihr denn?
      Hallo.

      Wag es kaum zu schreiben aber der Maxim MAX7219 LED-Display Treiber ist doch genau des.

      Zitat:

      Er bietet unschätzbare Vorteile gegenüber anderen Ansteuerungsmethoden:

      • minimalen Außenbeschaltung, von nur einem Widerstand

      • Ansteuerung von bis zu 8 7-Segment Digits oder 64 einzelnen LEDs

      • „On-chip BCD Code-B“ Dekoder und „No-Decode“ Modus

      • Interner Multiplexer

      • Segment und Digit Treiber

      • 8x8 statisches RAM

      • Belegung von nur 3 I/O Pins des Mikrokontrollers

      • 150>A Shutdown Mode zum Stromsparen

      • Analoge und digitale Helligkeitskontrolle

      • Test Mode für einen Funktionstest der 7-Segmente (alle LEDs eingeschaltet)

      Durch den eingebauten RAM und dem Multiplexer, entlastet der MAX7219 den

      Mikrokontroller enorm. Außerdem ist der MAX7221, eine verbesserte Variante im

      Bereich EMV, mit den Ansteuerungsmethoden SPI, QSPI und Microwire kompatibel.

      Mich begeistert die sehr, sehr einfache „Bedienung“ mit SPI. Somit sind auch keine Zeitprobleme zu erwarten. Das Cascading und die interne Helligkeitseinstellungen sind doch schon mal ein Test wert.

      Gruß
    • @fredred An den hab' ich auch schon gedacht, andererseits wird der seriell betrieben. Auch wenn man mit SPI arbeitet, ich glaube eine parallele Ansteuerung geht schneller. Dafür braucht man halt genug pins.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Vollfarbleds sind vielleicht übertrieben. Außerdem relativ groß. Eine 8x16 Matrix ist schon ein Brummer. Ok, es gibt auch riesige Kerzen.
      Aber das sind alles Themen der Darstellung. Das schwierige ist für mich das Generieren des Inhalts, also das Flammenbild. Beim Original wurde möglicherweise ein Video der Flamme eingesetzt. Das begrenzt die Varietät (gibt's das Wort?). Man kann sich ja mal an den Flammenalgorithmus des Kunstfeuers orientieren...
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ein schneller Blick auf die software ergibt für mich ein ständiges Übertragen von datas auf das display. Es sind wohl alle Flammenformen in datas abgelegt. Wäre natürlich eine Möglichkeit und ist dann die Umsetzung von einem Video zur Ausgabe auf der matrix.
      Ein Errechnen einer Flamme würde mich jetzt eher reizen, zumal man dann auch äußere Einflüsse, wie Wind, berücksichtigen könnte.
      Hat wer eine Formel? :whistling:
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Galahat schrieb:

      tschoeatsch schrieb:

      zumal man dann auch äußere Einflüsse, wie Wind, berücksichtigen könnte.
      Mit PTC, zum Kerzeauspusten.
      Oder mit Mikrophone links, rechts und eins oben. Das geht dann doch nur, wenn man beständig die Flamme berechnet. Wenn keine äußeren Einflüsse da sind, dann hat man ein stehendes Bild der Flamme. Das könnte man auf einer 8x16-byte-Matrix mit eingetragenen Hitzewerten darstellen. Die einzelnen bytes werden dann für unterschiedliche Helligkeitswerte der entsprechenden Led auf die bits der 4 Speicherarrays umgerechnet und angezeigt (siehe post#1).
      Ein äußerer Einfluß müsste diese Hitzewerte temporär verändern, ist die Frage wie?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Wenn du jetzt wegen der Helligkeit für eine LED in der Matrix einfach ein Byte nimmst, wird es vielleicht einfacher.
      Ich würde auch Bilder der Flamme ablegen. Ein Bild benötigt dann 16x8Byte=128Byte.

      Mit wenigen Bildern, vielleicht 10 kann man bestimmt ausreichend verschiedene Flammen abbilden.

      Damit die Flamme z.B. auf Pusten reagiert, müsste sich die Abbildung abhängig von der aktuell dargestellten ändern.
      Das könnte man mit Zuständen machen (Einfach ne Variable).

      Ist die variable z.B. Bild 1, dann darf die Flamme beim Pusten nicht in Bild 2 wechsln, sondernnach 4 oder 6 etc.

      Das erinnert mich wieder an einen Zustandsautomat.

      Mit Ausgabe der der Helligkeit per Softpwm.

      Was meinst du?
    • Meine noch nix, weil ich noch nicht groß weiter gedacht hab'. X/
      Was meinst du mit 'Ausgabe der Helligkeit per soft-pwm'? Was nützt mit das byte für jede Led, wenn mehrere, wirklich gleichzeitig, leuchten? Die Helligkeitsverteilung innerhalb der Flamme hätte ich durch die verschiedenen Einzelbilder gemacht, die ja wiederum ein einziges unbewegtes Bild der Flamme darstellen. Dadurch entsteht ja im Prinzip auch eine soft-pwm, aber nur durch die Häufigkeit, mit der die jeweils einzelne Led in den Einzelbildern angesteuert wird. Dann bräuchte ich für die 10 verschiedenen Bilder, die eine bewegte Flamme darstellen noch jeweils vielleicht 6 Bilder für die Helligkeitsabstufung, macht 60 Bilder.
      Raum für Notizen

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

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

      Was meinst du mit 'Ausgabe der Helligkeit per soft-pwm'?
      Du hast doch eine Matrix von 8 LED's in X-Richtung und 16 in Y-Richtung.
      Man könnte das so organisieren, dass die Flamme Zeilenweise von oben nach unten geschrieben wird. Zu hast also 16 Zeilen, die du nacheinander ansteuerst.
      In einer Zeile sind ja 8 LED's, also brauchst du 8 PWM-Kanäle. So kannst du bei der Ansteuerung der 1. Zeile die 8 Werte für die PWM setzen, und wenn die 2. Zeile anzuzeigen ist andere 8 PWM-Werte.
      Damit die Zuweisung der PWM-Werte einfach ist und nicht Bitweise zerfuselt werden muss, könnte man einfach ein Byte für die Helligkeit nehmen.

      Wenn du 2 Bit für 4 Helligkeitsstufen annimmst, ist das möglich, wird aber bei der Zuweisung der PWM-Werte (Die ja mehr als 2 Bit haben) deutlich mehr Zeit kosten. Das könnte sich dann mit negativen Effekten bemerkbar machen. Wenn du aber schon ein Byte hast, brauchst du es nur noch zuzuweisen.

      Man bräuchte also ein Byte-Array (PWM-Array) mit 8 Werte für 8 PWM-Kanäle. Die Soft-PWM holt sich daraus die Helligkeitswerte direkt. Immer wenn die nächste Zeile anzuzeigen ist, wird aus den Datazeilen (oder wegen mir aus anderen Arrays) einfach die 8 Werte (Helligkeit) für die PWM kopiert ins PWM-Array.

      In dem Fall würde ich ja auch die Helligkeitsunterschiede durch die Bilder machen. Die Werte sind bereits fix im Flash abgelegt und werden nur aufgerufen und angezeigt.

      Was du meinst ist, so verstehe ich das, pro Flammen-Bild eigentlich 2 Bilder zu nehmen, die sich nur am Rand unterscheiden. Durch abwechselndes Anzeigen eines Bildes mit Rand und dann das Bild ohne Rand würde so auch eine "Halbe" Helligkeit ergeben. Da hast du recht, das könnte man als PWM bezeichnen.

      Ja jetzt gibts wohl schon 2 Ideen, wie man das mit der Helligkeit umsetzen könnte. Oder 3 wenn ich die Methode mit 2 Bit für 4 Stufen mitrechne.
    • Mitch64 schrieb:

      Was du meinst ist, so verstehe ich das, pro Flammen-Bild eigentlich 2 Bilder zu nehmen, die sich nur am Rand unterscheiden. Durch abwechselndes Anzeigen eines Bildes mit Rand und dann das Bild ohne Rand würde so auch eine "Halbe" Helligkeit ergeben.
      mehr Bilder, 6 Bilder für 6 Helligkeitsabstufungen. Ich glaube, eine soft-pwm für jede der 8 gleichzeitig leuchtenden Leds haut zeitlich nicht hin. Da ist man ja nur noch im interrupt. Wenn ich 20 Einzelbilder für die Bewegung der Flame ansetze, mit 6 Teilbildern für die Helligkeitsunterschiede, dann hab' ich 120 Bilder darzustellen. Jedes Teilbild hat 16 Zeilen, die per interrupt aus dem Speicher an den port geladen werden, macht 192 interrupts/Sekunde, das ist schlimm genug. Wobei die 6 Teilbilder ruhig öfters gezeigt werden sollten, bevor das nächste Einzelbild kommt. Was ja auch noch nötig ist, ist eine Dunkelzeit. Ich kann ja nicht ein byte nach dem anderen an den port anlegen, wenn die Zeile umgeschaltet wird, mussen die Leds aus sein, sonst wird der optische Eindruck schlecht.
      Wenn du für jede Led einen Helligkeitswert hast, dann brauchst du für jedes Einzelbild 8x16=128 bytes.
      Mit meiner Version, die zugegebenerweise weniger Helligkeitsstufen kennt, brauche ich 16X6=96 bytes.
      Man könnte ja mal eine hardware andenken, wo man bisschen spielen kann. Mein Vorschlag: ein kompletter port für die Zeile, die Zeilen-Umschaltung mit einen Zähler 74xx138, 2 Stück kaskadiert und mit lowside-Treiber.
      Man könnte für den Anfang erstmal nur 3 Zeilen anzeigen lassen, dann genügen die 3 pins für die Zeilenumschaltung und ein lowside-Treiber und man spart sich die Decodierer.
      Raum für Notizen

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

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

      die Zeilen-Umschaltung mit einen Zähler 74xx138, 2 Stück kaskadiert und mit lowside-Treiber.
      Da würde noch ein inverter dazwischen fehlen. Besser wäre ein HCC4514B, der hätte logik 1=high und könnte so gleich den lowside richtig ansteuern.
      ti.com/lit/ds/symlink/cd74hc4515.pdf
      Raum für Notizen

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

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

      Da ist man ja nur noch im interrupt. Wenn ich 20 Einzelbilder für die Bewegung der Flame ansetze
      Das kann man gut ausprobieren im Simulator.

      Ich habe mir mal Gedanken gemacht dazu.
      Ich will dir nicht die Freude am Programmieren nehmen.

      Aber hier mal ein Ansatz, wie ich mir das vorstelle. Ist aber nicht komplett. Eher als Konzept zu sehen.

      BASCOM-Quellcode

      1. $Regfile = "m8def.dat"
      2. $crystal = 8000000 ' interner RC-Generator
      3. $hwstack = 40
      4. $swstack = 32
      5. $framesize = 32
      6. Config Base = 0 ' Arrays beginnen ab Index 0
      7. ' Ausgabe-Pins der 8 PWM Kanäle (Soft-PWM)
      8. pinPWM0 Alias PortD.0
      9. pinPWM1 Alias PortD.1
      10. pinPWM2 Alias PortD.2
      11. pinPWM3 Alias PortD.3
      12. pinPWM4 Alias PortD.4
      13. pinPWM5 Alias PortD.5
      14. pinPWM6 Alias PortD.6
      15. pinPWM7 Alias PortD.7
      16. DDRD = &hFF
      17. Dim PWMChannel(8) as Byte ' Array für 8 PWM-Kanäle
      18. Dim AbbildNr as Byte ' Nr. der zu zeigenden Kerzenabbildung
      19. ' -------------------------------------------
      20. ' Generierung Zeilenfrequenz
      21. ' -------------------------------------------
      22. Dim ZeileNr as Byte ' aktuelle Zeilen-Nummer [0 .. 15]
      23. Config Timer2 = Timer , Prescale = 128 , Clear Timer = 1
      24. OCR2 = 130 - 2 ' Zeilenfrequenz 480Hz einstellen
      25. On OC2 ISR_Zeilen
      26. Enable OC2
      27. ' -------------------------------------------
      28. ' Generierung PWM
      29. ' -------------------------------------------
      30. Const PWMCountMax = 3 ' 4 Helligkeitsstufen [0 .. 3]
      31. Dim PWMCount as Byte ' PWM-Zählerwert
      32. ' Die PWM-Frequenz ergibt sich aus Overflow-Frequent Timer0 / (PWMCountMax+1)
      33. ' Hier also 8MHz / Prescaler / 256 / (PWMCountMax+1) = ca. 976Hz
      34. Config Timer0 = Timer , Prescale = 8
      35. On OVF0 ISR_PWM
      36. Enable OVF0
      37. Enable Interrupts
      38. ' ------------------------------------------------------------------------------------------------
      39. ' Hauptschleife
      40. ' ------------------------------------------------------------------------------------------------
      41. Do
      42. ' Hier kommt die Zuordnung rein, welches Kerzen-Abbild zu zeigen ist
      43. Loop
      44. ' ------------------------------------------------------------------------------------------------
      45. ' Unterprogramme
      46. ' ------------------------------------------------------------------------------------------------
      47. ' -------------------------------------------
      48. ' Die Zeilen müssen nacheinander durchgeschaltet werden.
      49. ' Damit Flackerfrei müssen 16 Zeilen min. 30x je Sekunde
      50. ' angezeigt werden. Bedeutet eine Aufruf-Frequenz von
      51. ' 30x16 = 480 Hz
      52. ' -------------------------------------------
      53. ISR_Zeilen:
      54. ' Kopieren der Daten für die aktuelle Zeile in das PWM-Array
      55. ' ..
      56. Select Case AbbildNr
      57. Case 0 ' Abbild 0 soll angezeigt werden
      58. LoadWordAdr KerzeAbbild0 ' Pointer nach Z
      59. Case 1 ' Abbild 1 soll angezeigt werden
      60. '' ..
      61. End Select
      62. Incr ZeileNr
      63. If ZeileNr >= 16 then
      64. ZeileNr = 1
      65. End If
      66. Return
      67. ' -------------------------------------------
      68. ' Hier wird die Software-PWM ausgegeben für
      69. ' die 8 Kanäle (Spalten)
      70. ' -------------------------------------------
      71. ISR_PWM:
      72. If PWMChannel(0) = PWMCount then Reset PinPWM0
      73. If PWMChannel(1) = PWMCount then Reset PinPWM1
      74. If PWMChannel(2) = PWMCount then Reset PinPWM2
      75. If PWMChannel(3) = PWMCount then Reset PinPWM3
      76. If PWMChannel(4) = PWMCount then Reset PinPWM4
      77. If PWMChannel(5) = PWMCount then Reset PinPWM5
      78. If PWMChannel(6) = PWMCount then Reset PinPWM6
      79. If PWMChannel(7) = PWMCount then Reset PinPWM7
      80. Incr PWMCount
      81. If PWMCount > PWMCountMax then
      82. PWMCount = 0
      83. Set PORTD ' Alle LED's in der Zeile An
      84. End If
      85. Return
      86. ' Datenformat der Kerzen-Abbilder
      87. ' Wert 0 -> LED aus
      88. ' Wert 1 -> LED 33% hell
      89. ' Wert 2 -> LED 66% hell
      90. ' Wert 3 -> LED 100% hell
      91. ' 8 Datenwerte in einer Zeile sind eine Zeile in der LED-Matrix
      92. ' 16 Zeilen ergeben so ein gesamtes Abbild
      93. KerzeAbbild0:
      94. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' 0. Zeile (oben)
      95. Data 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 ' 1. Zeile (oben)
      96. Data 0 , 0 , 0 , 1 , 3 , 1 , 0 , 0 ' 2. Zeile
      97. Data 0 , 0 , 0 , 1 , 3 , 1 , 0 , 0
      98. Data 0 , 0 , 0 , 1 , 3 , 1 , 0 , 0
      99. Data 0 , 0 , 0 , 1 , 3 , 1 , 0 , 0
      100. Data 0 , 0 , 1 , 2 , 3 , 2 , 1 , 0
      101. Data 0 , 0 , 1 , 3 , 3 , 2 , 1 , 0
      102. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      103. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      104. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      105. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      106. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      107. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      108. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      109. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
      110. Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' 15. Zeile (unten)
      Alles anzeigen

      tschoeatsch schrieb:

      Mit meiner Version, die zugegebenerweise weniger Helligkeitsstufen kennt, brauche ich 16X6=96 bytes.
      Du willst aber 6 Bilder. Dann sind das 6x 96 Byte?

      Wie willst du die Helligkeiten kodieren? Vielleicht hab ich deine Methode noch nicht ganz geblickt!