Angepinnt Software-Schnipsel Sammelthread

    Software-Schnipsel Sammelthread

    Es wird hier im Forum ja immer wieder nach bestimmten Sachen gefragt, z.B. wie funktioniert ne SW-PWM, HSV-zu-RGB-Umrechnung, DMX-Empfang, Fernbedienung auswerten, etc.

    oft werden dann irgendwo in nem Thread SW-Schnipsel gepostet, die dort natürlich irgendwann wieder "verloren gehen", weil keiner mehr weiß, in welchem Zusammenhang was wo gepostet wurde.

    Daher dieser Thread, darin sollen solche Codes/Routinen gesammelt werden, damit man sie schneller wieder findet.

    Bitte diesen Thread "sauber" halten, keine Fragen zu SW oder geposteten Routinen, wenn die Beschreibung nicht ausführlich genug ist, dann den Ersteller des jeweiligen Posts per PN fragen, dieser soll dann ggfs. noch weitere Infos ergänzen - aber nur spezifische Dinge, bitte niemanden per PN mit Grundlagenfragen nerven, wie man Bascom installiert o.ä. - Spam in diesem Thread wird ohne Benachrichtigung gelöscht.

    Wer hier nen Code postet, sollte bitte gleich im Titel (per Abkürzung [ C] [asm] oder [Bascom]) nennen, in welcher Sprache der Code vorliegt - sowie dann den Code ausführlich genug erläutern, was er wie macht, bei asm z.B. auch, welche Register benutzt werden etc. - dies kann im Thread, oder ideal gleich direkt im Quelltext erfolgen.

    kurze Schnipsel kann man direkt in den Thread stellen (mit den "Code"-Tags), längere Teile dann bitte als .zip - ich habe den Thread abonniert, bekomme also neue Posts mit und füge die dann in's Inhaltsverzeichnis ein.

    Inhaltsverzeichnis:

    Links zu anderen Seiten:
    It's only light - but we like it!

    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Pesi“ ()

    HSV-zu-RGB-Umrechnung [Bascom]

    Hier verschiedene Routinen, um Farben aus dem HSV-Farbraum nach RGB umzurechnen.

    Der Code stammt von Neni (User "synvox"), bereits hier im Forum veröffentlicht. Dort, sowie in den nachfolgenden Posts gibt es noch weitere Infos zu den Umrechnungen.

    Die Berechnungen sind so gemacht, dass durch geschicktes Anpassen der Konstanten keine Division, ausser durch 256, nötig ist, diese kann einfach durch verschieben um 8 Bit nach rechts durchgeführt werden. Dadurch brauchen die Routinen wenig Rechenleistung, und lassen sich auch ganz einfach nach C und Assembler portieren.

    Brainfuck-Quellcode

    1. /*---------------8-Bit-PWM--------------------------
    2. hue: 0 to 1529
    3. sat: 0 to 255
    4. bri: 0 to 255
    5. all variables uint16_t
    6. */
    7. while (hue > 1529) hue -= 1530;
    8. while (hue < 0) hue += 1530;
    9. if (hue < 255) {
    10. red_val = 255;
    11. green_val = (65280 - sat * (255 - hue)) >> 8;
    12. blue_val = 255 - sat;
    13. }
    14. elseif (hue < 510) {
    15. red_val = (65280 - sat * (hue - 255)) >> 8;
    16. green_val = 255;
    17. blue_val = 255 - sat;
    18. }
    19. elseif (hue < 765) {
    20. red_val = 255 - sat;
    21. green_val = 255;
    22. blue_val = (65280 - sat * (765 - hue)) >> 8;
    23. }
    24. elseif (hue < 1020) {
    25. red_val = 255 - sat;
    26. green_val = (65280 - sat * (hue - 765)) >> 8;
    27. blue_val = 255;
    28. }
    29. elseif (hue < 1275) {
    30. red_val = (65280 - sat * (1275 - hue)) >> 8;
    31. green_val = 255 - sat;
    32. blue_val = 255;
    33. }
    34. else {
    35. red_val = 255;
    36. green_val = 255 - sat;
    37. blue_val = (65280 - sat * (hue - 1275)) >> 8;
    38. }
    39. red = ((bri + 1) * red_val) >> 8;
    40. green = ((bri + 1) * green_val) >> 8;
    41. blue = ((bri + 1) * blue_val) >> 8;
    42. /*-------8-Bit-PWM-|-Light-Emission-normalized------
    43. hue: 0 to 764
    44. sat: 0 to 127
    45. bri: 0 to 255
    46. all variables int16_t
    47. */
    48. while (hue > 764) hue -= 765;
    49. while (hue < 0) hue += 765;
    50. if (hue < 255) {
    51. red_val = (10880 - sat * (hue - 170)) >> 7;
    52. green_val = (10880 - sat * (85 - hue)) >> 7;
    53. blue_val = (10880 - sat * 85) >> 7;
    54. }
    55. elseif (hue < 510) {
    56. red_val = (10880 - sat * 85) >> 7;
    57. green_val = (10880 - sat * (hue - 425)) >> 7;
    58. blue_val = (10880 - sat * (340 - hue)) >> 7;
    59. }
    60. else {
    61. red_val = (10880 - sat * (595 - hue)) >> 7;
    62. green_val = (10880 - sat * 85) >> 7;
    63. blue_val = (10880 - sat * (hue - 680)) >> 7;
    64. }
    65. red = (uint16_t)((bri + 1) * red_val) >> 8;
    66. green = (uint16_t)((bri + 1) * green_val) >> 8;
    67. blue = (uint16_t)((bri + 1) * blue_val) >> 8;
    68. /*------------------12-Bit-PWM----------------------
    69. hue: 0 to 24569
    70. sat: 0 to 4095
    71. bri: 0 to 4095
    72. all variables uint32_t or int32_t
    73. */
    74. while (hue > 24569) hue -= 24570;
    75. while (hue < 0) hue += 24570;
    76. if (hue < 4095) {
    77. red_val = 4095;
    78. green_val = (16773120 - sat * (4095 - hue)) >> 12;
    79. blue_val = 4095 - sat;
    80. }
    81. elseif (hue < 8190) {
    82. red_val = (16773120 - sat * (hue - 4095)) >> 12;
    83. green_val = 4095;
    84. blue_val = 4095 - sat;
    85. }
    86. elseif (hue < 12285) {
    87. red_val = 4095 - sat;
    88. green_val = 4095;
    89. blue_val = (16773120 - sat * (12285 - hue)) >> 12;
    90. }
    91. elseif (hue < 16380) {
    92. red_val = 4095 - sat;
    93. green_val = (16773120 - sat * (hue - 12285)) >> 12;
    94. blue_val = 4095;
    95. }
    96. elseif (hue < 20475) {
    97. red_val = (16773120 - sat * (20475 - hue)) >> 12;
    98. green_val = 4095 - sat;
    99. blue_val = 4095;
    100. }
    101. else {
    102. red_val = 4095;
    103. green_val = 4095 - sat;
    104. blue_val = (16773120 - sat * (hue - 20475)) >> 12;
    105. }
    106. red = ((bri + 1) * red_val) >> 12;
    107. green = ((bri + 1) * green_val) >> 12;
    108. blue = ((bri + 1) * blue_val) >> 12;
    109. /*-------12-Bit-PWM-|-Light-Emission-normalized-----
    110. hue: 0 to 12284
    111. sat: 0 to 4095
    112. bri: 0 to 4095
    113. all variables int32_t
    114. */
    115. while (hue > 12284) hue -= 12285;
    116. while (hue < 0) hue += 12285;
    117. if (hue < 4095) {
    118. red_val = (5591040 - sat * (hue - 2730)) >> 12;
    119. green_val = (5591040 - sat * (1365 - hue)) >> 12;
    120. blue_val = (5591040 - sat * 1365) >> 12;
    121. }
    122. elseif (hue < 8190) {
    123. red_val = (5591040 - sat * 1365) >> 12;
    124. green_val = (5591040 - sat * (hue - 6825)) >> 12;
    125. blue_val = (5591040 - sat * (5460 - hue)) >> 12;
    126. }
    127. else {
    128. red_val = (5591040 - sat * (9555 - hue)) >> 12;
    129. green_val = (5591040 - sat * 1365) >> 12;
    130. blue_val = (5591040 - sat * (hue - 10920)) >> 12;
    131. }
    132. red = ((bri + 1) * red_val) >> 12;
    133. green = ((bri + 1) * green_val) >> 12;
    134. blue = ((bri + 1) * blue_val) >> 12;
    It's only light - but we like it!

    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Pesi“ ()

    Plasma Effekt für LED Matrix

    Hallo Forum, hab mir gerade für meine Matrix nen kleinen Plasmaeffekt ähnlich wie in Glediator erstellt.
    Möchte natürlich nicht immer den PC dafür anhaben.

    Infos dazu gibts hier:

    lodev.org/cgtutor/plasma.html


    Natürlich sind Fließkommazahlen und sinus Funktionen ganz schön harter Stoff für so nen kleines 8 Bit Rechenwerk.

    Habe mir auch mal den Sourcecode von Glediator angeschaut, aber zwei Sinusfunktionen pro Pixel und noch eine pro Line lassen die Performance auch schnell sinken... :(

    Komme mit dem Source von Pepe auf ca. 6 Bilder die Sekunde bei 24 MHz und ohne Prozessorlast um die Daten in die Matrix zu schauffeln, was bei ATMegas noch dazu kommt.

    Also gibts jetzt stat Fließkommazahlen, ganze Zahlen und für die Sinusfunktion gibts ne LUT im Flash. Der Farbraum liegt auch im Flash wie die Gammakorrektur...

    Letztendlich Schupst man ein paar Bits und schaut nur noch in den Tabellen nach den richtigen Werten...
    Wie schnell das jetzt auf dem 24 MHz 8 Bitter läuft habe ich nicht gemessen. Aber irgendwas über 100 Bilder die Sekunde, denn ich seh die LED nicht mehr toggeln ;)

    Hier nun die Funktion:

    Quellcode

    1. void float_the_plasma(uint16_t plasmacounter,uint8_t _x,uint8_t _y,type_rgb *buffer)
    2. {
    3. for(uint8_t x=0;x<_x;x++) {
    4. for(uint8_t y=0;y<_y;y++) {
    5. uint8_t temp1 = (x<<4) + plasmacounter;
    6. uint8_t temp2 = (y<<5) + plasmacounter;
    7. uint8_t temp3 = ((x<<4) + (y<<4)) + (plasmacounter>>1);
    8. uint8_t temp4 = ((x*x)<<3 + (y*y)<<3) / (x+y+1);
    9. uint16_t color =
    10. (((
    11. + sin_lut(temp1)
    12. + sin_lut(temp2)
    13. + sin_lut(temp3)
    14. + sin_lut(temp4)
    15. ) >> 4) + plasmacounter) % 256*3;
    16. buffer[mapper(x,y)].r = gamma(add_color(color*3));
    17. buffer[mapper(x,y)].g = gamma(add_color(color*3+1));
    18. buffer[mapper(x,y)].b = gamma(add_color(color*3+2));
    19. }
    20. }
    21. }


    Kann natürlich nach belieben angepasst werden, einfach die Funktionen in Temp1 bis 4 verändern...

    Die Sinus_LUT und den Farbraum hänge ich mal als Datei an... die gamma LUT sollte klar sein und die mapper lookup table ist für die Anordnung meiner Matrixpixel zuständig. Das hängt ja dann auch von euch ab...


    Ich poste das hier, weil ich noch keinen "schnellen" Source für 8 Bit Mirkrokontroller im Netz gefunden habe, aber vielleicht gibts auch schon was?!


    Viel Spaß damit

    Grüße

    Basti

    EDIT Pesi: Fragen etc. zu diesem Code bitte dort posten, danke!
    Dateien
    • plasma_luts.zip

      (4,04 kB, 255 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Pesi“ ()

    Konvertierung DMX zu WS2801 Protokoll in Bascom

    Hier ein Programm zur Ansteuerung von WS2801-Pixel per DMX

    Quellcode

    1. '#####################################
    2. '# DMX zu WS2801 Konverter #
    3. '# By Dreas99 #
    4. '# mit Hilfe aus dem LED-Styles Forum #
    5. '######################################
    6. $regfile = "m328pdef.dat"
    7. $crystal = 16000000
    8. $hwstack = 40
    9. $swstack = 32
    10. $framesize = 32
    11. Config Dmxslave = Com1 , Channels = 30 , Dmxstart = 1 , Store = 30 ' Channels und Store = Anzahl der DMX Kanäle = Anzahl der WS2801 Pixel x 3
    12. Config Pinb.2 = Output 'SS-Pin als Ausgang konfiguriert
    13. Portb.2 = 1 'SS-Pin = 1
    14. Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1
    15. Spiinit
    16. Enable Interrupts
    17. Do
    18. Spiout _dmx_received(1) , 30 ' SPI Out: PB5 = CKI, PB3 = SDI vom WS2801
    19. Waitms 10
    20. Loop


    Das Programm sollte nach Anpassen von $regfile auf allen Atmega's mit 16Mhz Quartz und mindestens 1KB Ram laufen (getestet mit Atmega328P)

    Viel Spaß bei ausprobieren

    Andreas

    Software für Bascom um WS2801 anzusteuern, vielleicht kann jemand Teile brauchen

    $regfile = "m16def.dat"
    $crystal = 15000000
    $baud = 115200

    $hwstack = 40
    $swstack = 40
    $framesize = 40

    'Timer0 konfigurieren
    '150000000 (Systemtakt) / 64 (Prescaler) = 234375 (Counts)
    Config Timer1 = Timer , Prescale = 64
    'Soft-SPI konfigurieren
    Config Spi = Soft , Din = Portd.3 , Dout = Portd.4 , Ss = None , Clock = Portd.5
    Spiinit

    'LED1 an PD.6
    Led1 Alias Portd.6
    Config Led1 = Output
    Led1 = 0

    'SCHALTER1 an PA0
    Schalter1 Alias Pina.0
    Config Schalter1 = Input
    Porta.0 = 1 'PullUp-Widerstand einschalten

    'SCHALTER2 an PA1
    Schalter2 Alias Pina.1
    Config Schalter2 = Input
    Porta.1 = 1 'PullUp-Widerstand einschalten

    'SCHALTER3 an PA2
    Schalter3 Alias Pina.2
    Config Schalter3 = Input
    Porta.2 = 1 'PullUp-Widerstand einschalten

    'SCHALTER4 an PA3
    Schalter4 Alias Pina.3
    Config Schalter4 = Input
    Porta.3 = 1 'PullUp-Widerstand einschalten

    'SCHALTER5 an PA4
    Schalter5 Alias Pina.4
    Config Schalter5 = Input
    Porta.4 = 1 'PullUp-Widerstand einschalten

    'SCHALTER6 an PA5
    Schalter6 Alias Pina.5
    Config Schalter6 = Input
    Porta.5 = 1 'PullUp-Widerstand einschalten

    'SCHALTER7 an PA6
    Schalter7 Alias Pina.6
    Config Schalter7 = Input
    Porta.6 = 1 'PullUp-Widerstand einschalten

    'SCHALTER8 an PA7
    Schalter8 Alias Pina.7
    Config Schalter8 = Input
    Porta.7 = 1 'PullUp-Widerstand einschalten
    'Dip Schalter für Pixelmengenangabe



    Dim Zaehler As Integer ' Zähler für Wertmenge zur Ausgabe von Startpunkt zu Startpunkt
    Dim Rgb(450) As Byte ' Werte für jede Farbe R-G-B * 150 LEDs
    Dim Startpunkt As Bit ' Startpunktdefinition wenn Wert 1 gefunden wurde wird Bit gesetzt
    Dim Zwischenwert As Byte ' Zwischenwert Variable die jeden durch URD übertragenen Wert annimmt
    Dim Zwischenzaehler As Byte 'Togglebit Setzen resetzen von 1 zu 1
    Dim Startausgabe As Byte
    Dim Takt As Bit
    Dim X As Byte
    Dim Test As Byte
    Dim Aktiv As Bit
    Dim Pixelmenge As Integer
    Dim Überlauf As Integer

    Aktiv = 0
    Startpunkt = 0
    Zwischenzaehler = 0
    Zaehler = 0
    Überlauf = 0




    'Interupts definieren und Einschalten
    On Urxc Onrxd 'Interupt für RS232 Schnittstelle
    Enable Urxc 'Einschalten Interupt RS232

    On Ovf1 On_ovf1
    Enable Ovf1 'Timer0 Overflow Interrupt 'Dieser Interrupt wird beim Überlauf (255 nach 0) ausgelöst
    '234375 (Counts) / 65535 (16-Bit Timer) = 3,576 (Interrupts die Sekunde)
    Enable Interrupts 'Einschalten Interupts gesamt

    Led1 = 1
    Gosub Pixelmengenrechner 'Ermitteln wieviele Lampen eingestellt sind
    Gosub Starten 'Einsprung zum löschen aller Werte der Lampen beim Einschalten

    Do





    If Takt = 1 Then
    If Zwischenwert = 1 Then Startpunkt = 1

    If Startpunkt = 1 And Zwischenwert <> 1 Then
    Incr Zaehler
    Rgb(zaehler) = Zwischenwert
    If Zaehler = Pixelmenge Then Gosub Ausgabe
    End If

    Takt = 0
    End If


    Loop
    End


    Onrxd: 'RS 232 Empfang verarbeiten
    Zwischenwert = Udr
    Takt = 1
    Überlauf = 1

    Return



    Ausgabe:
    If Zaehler <= 255 Then
    Spiout Rgb(1) , Zaehler
    Startpunkt = 0
    Zaehler = 0
    Else
    Spiout Rgb(1) , 255
    Spiout Rgb(256) , Zaehler
    Startpunkt = 0
    Zaehler = 0
    End If
    Return

    Starten: ' Unterprogramm um alle LEDs beim Start von 155 nach 0 zu löschen
    For X = 155 To 0 Step -1 ' hierbei wird ermittelt ob die Einzelnen LEDs Farbtechnisch OK sind
    Waitms 4
    For Zaehler = 1 To Pixelmenge
    Rgb(zaehler) = X
    Next Zaehler

    If Pixelmenge =< 255 Then
    Spiout Rgb(1) , Pixelmenge
    Else
    Spiout Rgb(1) , 255
    Spiout Rgb(256) , Pixelmenge
    End If
    Next X
    Startpunkt = 0
    Zwischenzaehler = 0
    Zaehler = 0

    Return


    'Anhand der Dip Schalter einstellen wieviele Pixel am Bus hängen
    Pixelmengenrechner:
    Pixelmenge = 255

    If Schalter1 = 0 Then Pixelmenge = Pixelmenge -1
    If Schalter2 = 0 Then Pixelmenge = Pixelmenge -2
    If Schalter3 = 0 Then Pixelmenge = Pixelmenge -4
    If Schalter4 = 0 Then Pixelmenge = Pixelmenge -8
    If Schalter5 = 0 Then Pixelmenge = Pixelmenge -16
    If Schalter6 = 0 Then Pixelmenge = Pixelmenge -32
    If Schalter7 = 0 Then Pixelmenge = Pixelmenge -64
    If Schalter8 = 0 Then Pixelmenge = Pixelmenge -128

    Pixelmenge = Pixelmenge * 3

    'Print "Ausgabe Kanäle R-G-B :" ; Pixelmenge
    Waitms 20

    Return



    'Timer0 Overflow Interrupt
    On_ovf1:
    Incr Überlauf
    If Überlauf => 8 Then Goto Starten

    Print Überlauf

    Return