Ansteuerung von APA102 (intelligente RGB-Leds) in einer isr

    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!

    • Ansteuerung von APA102 (intelligente RGB-Leds) in einer isr

      Hi Programmierer,
      Ich will ja einen Schwenktexter bauen, ihr wisst schon, einen Leuchtstab, der beim hin und her schwenken einen Text 'in die Luft' malt. Ein Teil einer Propelleruhr sozusagen. Die Erzeugung der Leuchtpunkte sollen APA102 Leds machen. cdn.sparkfun.com/datasheets/Components/LED/APA102C.pdf
      Der ganz grobe Ablauf: In einem Bildspeicher steht der Text drin 12x16er font, also ein Byte für die oberen 8 der 16 Leds, ein byte für die unteren 8 der 16 Leds, die übereinander angeordnet sind. Die Anzahl der bytes im Bildspeicher entspricht der Spaltenanzahl, die in einem Schwenk angezeigt werden kann. Um einen Buchstaben anzuzeigen werden also nacheinander 24 bytes des Bildspeichers in Leuchtpunkte umgesetzt. Ich finde das jetzt schwierig zu beschreiben, wenn Fragen auftauchen, nachhaken!
      Gut. Für die Ansteuerung einer APA102 sind 4 bytes notwendig, die durch die Led 'durchgeschoben werden, ähnlich wie bei den WS2812 Leds.
      APA102-bytes.PNG
      Im 'Global' steckt die Helligkeit, die ist bei mir max=&B11111, sodass das erste byte immer &HFF ist. Bei den Farben sollen bei mir auch nur die hellsten, also &HFF oder &F00 drin stehen.
      In welcher Farbe ein Text dargestellt wird, ist in einem Farbspeicher abgelegt, der für jede Spalte des Bildspeichers ein byte enthält. Ist dessen byte.0=1 gesetzt, wird die Spalte in rot dargestellt, byte.1=1 in grün, byte.2=1 in blau und daraus folgt für byte=3 eine Darstellung in gelb (rot+grün gleichzeitig). 7 Farben + schwarz sind so möglich.
      Ich nähere mich der Fragestellung. Um eine Spalte jetzt zum Leuchten zu bringen, sehe ich im Farbspeicher unter der Spaltennummer nach und weiß, welches bytes der Farbbytes der Leds &HFF enthalten muss, wenn diese gemäß dem Bildspeicher zu leuchten hat.
      Jetzt die Frage, wie komme ich am einfachsten von dem bit, was über Leuchten/Nichtleuchten entscheidet zu dem byte &HFF/&F00, das ich an die Led sende. Momentan bin ich soweit:

      BASCOM-Quellcode

      1. Anzeige: 'laden und anzeigen einer Spalte
      2. '19.Led
      3. Ausgabe(6) = Farbe_19(3)
      4. Ausgabe(7) = Farbe_19(2)
      5. Ausgabe(8) = Farbe_19(1)
      6. '18.Led
      7. Ausgabe(10) = Farbe_18(3)
      8. Ausgabe(11) = Farbe_18(2)
      9. Ausgabe(12) = Farbe_18(1)
      10. Bild = Bildspeicher_high(speicher_spalte)
      11. R = Spalten_farbe(speicher_spalte).0 * 255 : G = Spalten_farbe(speicher_spalte).1 * 255 : B = Spalten_farbe(speicher_spalte).2 * 255
      12. '17.Led
      13. Bi = Bild.7
      14. Ausgabe(14) = B * Bi
      15. Ausgabe(15) = G * Bi
      16. Ausgabe(16) = R * Bi
      17. '16.Led
      18. Bi = Bild.6
      19. Ausgabe(18) = B * Bi
      20. Ausgabe(19) = G * Bi
      21. Ausgabe(20) = R * Bi
      22. '15.Led
      23. Bi = Bild.5
      24. Ausgabe(22) = B * Bi
      25. Ausgabe(23) = G * Bi
      26. Ausgabe(24) = R * Bi
      27. '14.Led
      28. Bi = Bild.4
      29. Ausgabe(26) = B * Bi
      30. Ausgabe(27) = G * Bi
      31. Ausgabe(28) = R * Bi
      32. '13.Led
      33. Bi = Bild.3
      34. Ausgabe(30) = B * Bi
      35. Ausgabe(31) = G * Bi
      36. Ausgabe(32) = R * Bi
      37. '12.Led
      38. Bi = Bild.2
      39. Ausgabe(34) = B * Bi
      40. Ausgabe(35) = G * Bi
      41. Ausgabe(36) = R * Bi
      42. '11.Led
      43. Bi = Bild.1
      44. Ausgabe(38) = B * Bi
      45. Ausgabe(39) = G * Bi
      46. Ausgabe(40) = R * Bi
      47. '10.Led
      48. Bi = Bild.0
      49. Ausgabe(42) = B * Bi
      50. Ausgabe(43) = G * Bi
      51. Ausgabe(44) = R * Bi
      52. Bild = Bildspeicher_low(speicher_spalte)
      53. '09.Led
      54. Bi = Bild.7
      55. Ausgabe(46) = B * Bi
      56. Ausgabe(47) = G * Bi
      57. Ausgabe(48) = R * Bi
      58. '08.Led
      59. Bi = Bild.6
      60. Ausgabe(50) = B * Bi
      61. Ausgabe(51) = G * Bi
      62. Ausgabe(52) = R * Bi
      63. '07.Led
      64. Bi = Bild.5
      65. Ausgabe(54) = B * Bi
      66. Ausgabe(55) = G * Bi
      67. Ausgabe(56) = R * Bi
      68. '06.Led
      69. Bi = Bild.4
      70. Ausgabe(58) = B * Bi
      71. Ausgabe(59) = G * Bi
      72. Ausgabe(60) = R * Bi
      73. '05.Led
      74. Bi = Bild.3
      75. Ausgabe(62) = B * Bi
      76. Ausgabe(63) = G * Bi
      77. Ausgabe(64) = R * Bi
      78. '04.Led
      79. Bi = Bild.2
      80. Ausgabe(66) = B * Bi
      81. Ausgabe(67) = G * Bi
      82. Ausgabe(68) = R * Bi
      83. '03.Led
      84. Bi = Bild.1
      85. Ausgabe(70) = B * Bi
      86. Ausgabe(71) = G * Bi
      87. Ausgabe(72) = R * Bi
      88. '02.Led
      89. Bi = Bild.0
      90. Ausgabe(74) = B * Bi
      91. Ausgabe(75) = G * Bi
      92. Ausgabe(76) = R * Bi
      93. '01.Led
      94. Ausgabe(78) = Farbe_1(3)
      95. Ausgabe(79) = Farbe_1(2)
      96. Ausgabe(80) = Farbe_1(1)
      97. Spiout Ausgabe(1) , 84 'bytes werden an die Leds gesendet
      98. Incr Speicher_spalte
      99. If Speicher_spalte > Spalten_schwenk Then
      100. Speicher_spalte = Spalten_schwenk 'max Spalten des Bildspeichers werden angezeigt
      101. Comp = 0
      102. End If
      103. ' Comp = Comp + 1_sp
      104. ' Compare1a = Comp 'nächster compare-Wert
      105. Return
      Alles anzeigen
      Das wäre jetzt die isr, die für jede Spalte aufgerufen wird. Es sind 19 Leds insgesamt, nur 16 werden für die Textdarstellung verwendet.
      Ihr seht, um von einem bit aus dem Bildspeicher zu einem byte für die Ausgabe zu kommen, multipliziere ich mit 255. Das braucht mächtig Zeit. Wäre vielleicht hier nicht das Problem, aber schön schaut sowas nicht aus, eher dilettantisch. Wie könnte man es schöner/besser machen?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Hallo tscho,
      du hast vielleicht ein Glück das Michael Urlaub hat :)
      ich habe mal deine isr umgeschrieben ob das so Funktionier kA teste mal

      Quellcode

      1. Dim Z As Byte
      2. Dim Z1 As Byte
      3. Declare Sub Led(byval Bild_ As Byte , Byval Led_ As Byte)
      4. Anzeige: 'laden und anzeigen einer Spalte
      5. '19.Led
      6. Ausgabe(6) = Farbe_19(3)
      7. Ausgabe(7) = Farbe_19(2)
      8. Ausgabe(8) = Farbe_19(1)
      9. '18.Led
      10. Ausgabe(10) = Farbe_18(3)
      11. Ausgabe(11) = Farbe_18(2)
      12. Ausgabe(12) = Farbe_18(1)
      13. Bild = Bildspeicher_high(speicher_spalte)
      14. R = 255
      15. G = 255
      16. B = 255
      17. If Spalten_farbe(speicher_spalte).0 = 0 Then R = 0
      18. If Spalten_farbe(speicher_spalte).1 = 0 Then G = 0
      19. If Spalten_farbe(speicher_spalte).2 = 0 Then B = 0
      20. Z1 = 14
      21. For Z = 7 To 0 Step -1 '17-10 led
      22. Call Led(z , Z1)
      23. Z1 = Z1 + 4
      24. Next
      25. Bild = Bildspeicher_low(speicher_spalte)
      26. Z1 = 46
      27. For Z = 7 To 0 Step -1 '9-1 led
      28. Call Led(z , Z1)
      29. Z1 = Z1 + 4
      30. Next
      31. Ausgabe(78) = Farbe_1(3)
      32. Ausgabe(79) = Farbe_1(2)
      33. Ausgabe(80) = Farbe_1(1)
      34. Spiout Ausgabe(1) , 84 'bytes werden an die Leds gesendet
      35. Incr Speicher_spalte
      36. If Speicher_spalte > Spalten_schwenk Then
      37. Speicher_spalte = Spalten_schwenk 'max Spalten des Bildspeichers werden angezeigt
      38. Comp = 0
      39. End If
      40. ' Comp = Comp + 1_sp
      41. ' Compare1a = Comp 'nächster compare-Wert
      42. Return
      43. Sub Led(byval Bild_ As Byte , Byval Led_ As Byte)
      44. Bi = Bild.bild_
      45. Ausgabe(led_) = B * Bi
      46. Incr Led_
      47. Ausgabe(led_) = G * Bi
      48. Incr Led_
      49. Ausgabe(led_) = R * Bi
      50. End Sub
      Alles anzeigen
      Gruß
      businski
    • Das kann ich schon probieren, die hw liegt ja rum. Ich will auch noch eine Version erstellen. Ich schau mir deine mal nicht so genau an. Mal schau'n, was ich nach der Anregung von Michael zusammen bringe. Die if-Abfrage ist etwas schneller als die Multiplikation, ist schon mal gut.

      So, mal einen Vergleich gemacht: die oben gezeigte Version von mir braucht 2222 cycl.
      Die Multiplikationen durch if-Vergleiche ersetzt, braucht2214cycl.
      einzelne if_Vergleiche in for..next zusammen gapackt, braucht 4002 cycl.
      bei Version von Businski noch eine sub eingesetzt, braucht 4981 cycl.

      jetzt hier mal die schnellste Version des Programms. Was jetzt fehlt ist die Auslösung der timerabläufe durch die Schwenkung. Einen 'ADXL335 3-axes Analog Output Accelerometer Module Transducer for Arduino' Hab' ich schon, nur noch keinen code dafür.


      Schwenktexter-V005.bas


      font_10x16.txt
      Raum für Notizen

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

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

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

    • businski schrieb:

      Doch so viel …
      So ein sub-Aufruf macht halt doch 'viel' Aufwand, Sprungadresse auf den stack, danach Rücksprungadresse wieder holen, das scheint sich zu läppern. Ich hab' mich auch täuschen lassen, hätte auch nicht gedacht, dass eine Multiplikation nur wenig langsamer als ein if-Vergleich ist (jetzt in diesem Beispiel).
      Auch das zusammenfassen in for..next Schleifen braucht länger, weil ja der Schleifenzähler mitgeführt wird. Eine Aneinanderreihung von Befehlen geht dann schneller, braucht aber mehr code.
      So lern' ich ständig dazu...
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ohmei, ohmei, ohmei, ob das mal was wird. Ich hab' jetzt einen Beschleunigungssensor angeflanscht, der eine Spannung abhängig der Beschleunigung ausgibt. Diese wird in einer Schleife gemessen und momentan der Nulldurchgang erfasst. Das startet den timer1. Beim nächsten Nulldurchgang werden die vergangenen ticks durch die Anzahl der darzustellenden Spalten geteilt und als compare-Wert verwendet. Der timer läuft jetzt im ctc-Modus und gibt alle Spalten nacheinander aus. Dann fängt das Spielchen von vorne an. Dachte ich zumindest, warum der Text nur bei jedem 2. Schwenk aufgegeben wird a_56_df238249
      Hier ein Versuch eines Filmchens



      Der code dazu
      Schwenktexter-V011.bas
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • @Michael du wolltest doch schon immer meine Fehler korrigieren a_42_02cc30b2
      Mein Sensor gibt in senkrechte Position einen Spannungswert aus, der bei Neigung zur einen Seite verringert wird, Neigung zur anderen Seite vergrößert den Wert. Wenn ich den Sensor hin und her schwenke, erkenne ich am Oszilloskop einen sinusähnlichen Spannungsverlauf. Jetzt will ich den Umkehrpunkt der Spannung erkennen und hab' mir folgendes ausgedacht:

      BASCOM-Quellcode

      1. Offset = 100
      2. V_0 = Getadc(0) 'senkrechte Stellung messen
      3. Sp_f = Weiss
      4. Text = "hallo"
      5. Gosub Text_bildspeicher
      6. Disable Timer1
      7. Start_enable = 1
      8. Do
      9. V_x = Getadc(0)
      10. Select Case V_x
      11. Case Is > V_0 'Wert über der senkrechten Stellung
      12. V_x2 = V_0 + 1 'Vergleichswert vom anderen Schwenk zurück setzen
      13. If V_x < V_x1 And Stop_enable = 1 Then 'wenn Wert wieder kleiner wird
      14. Gosub L_rot
      15. Stop_enable = 0
      16. Start_enable = 1
      17. End If
      18. V_x1 = V_x 'neuer Vergleichswert
      19. Case Is < V_0 'Wert unter der senkrechten Stellung
      20. V_x1 = V_0 - 1 'Wert vom anderen Schwenk zurück setzen
      21. If V_x > V_x2 And Start_enable = 1 Then 'wenn Wert wieder größer wird
      22. Gosub L_gruen
      23. Start_enable = 0
      24. Stop_enable = 1
      25. End If
      26. V_x2 = V_x 'neuer Vergleichswert
      27. End Select
      28. Loop
      29. End
      Alles anzeigen
      Die sub l_rot schaltet eine Led auf rot und die Led, die vorher grün war aus, die sub l_gruen mach das Gegenteil.
      Das schaut so aus


      Wenn ich aber die Abfrage so mache und eigentlich einen Nulldurchgang habe:

      BASCOM-Quellcode

      1. V_0 = Getadc(0) 'senkrechte Stellung messen Neutralwert
      2. V_01 = V_0 + 2
      3. V_02 = V_0 - 2
      4. Sp_f = Weiss
      5. Text = "hallo"
      6. Gosub Text_bildspeicher
      7. Disable Timer1
      8. Start_enable = 1
      9. Do
      10. V_x = Getadc(0) 'Beschleunigung messen
      11. Select Case V_x
      12. Case Is > V_01 'größer als Neutralwert
      13. If Stop_enable = 1 Then
      14. Gosub L_rot
      15. Stop_enable = 0
      16. Start_enable = 1
      17. End If
      18. Case Is < V_02 'kleiner als Neutralwert
      19. If Start_enable = 1 Then
      20. Gosub L_gruen
      21. Start_enable = 0
      22. Stop_enable = 1
      23. End If
      24. End Select
      25. Loop
      26. End
      Alles anzeigen
      schaut es genauso aus, nämlich so



      Genau das Gleiche. Wo ist mein Denkfehler?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Naja, war so nix. Ich hab' jetzt das Programm so geändert, dass der Aufruf der sub l_rot und l_gruen nur einen 20msec Lichtblitz erzeugt. Bringt für mich jetzt eigentlich keine Verbesserung, weil jetzt eine Abhängigkeit der Schwenkfrequenz auf den Umschaltpunkt sichtbar wird. Damit hab' ich überhaupt nicht gerechnet. Vielleicht bin ich auch schon am Limit vom Sensor mit +-3g

      BASCOM-Quellcode

      1. V_0 = Getadc(0) 'senkrechte Stellung messen
      2. Sp_f = Weiss
      3. Text = "hallo"
      4. Gosub Text_bildspeicher
      5. Disable Timer1
      6. Start_enable = 1
      7. Do
      8. V_x = Getadc(0)
      9. Select Case V_x
      10. Case Is > V_0 'Wert über der senkrechten Stellung
      11. V_x2 = V_0 + 1 'Vergleichswert vom anderen Schwenk zurück setzen
      12. If V_x < V_x1 And Stop_enable = 1 Then 'wenn Wert wieder kleiner wird
      13. Gosub L_rot
      14. Stop_enable = 0
      15. Start_enable = 1
      16. End If
      17. V_x1 = V_x 'neuer Vergleichswert
      18. Case Is < V_0 'Wert unter der senkrechten Stellung
      19. V_x1 = V_0 - 1 'Wert vom anderen Schwenk zurück setzen
      20. If V_x > V_x2 And Start_enable = 1 Then 'wenn Wert wieder größer wird
      21. Gosub L_gruen
      22. Start_enable = 0
      23. Stop_enable = 1
      24. End If
      25. V_x2 = V_x 'neuer Vergleichswert
      26. End Select
      27. Loop
      28. End
      29. '-------------------------------------------------------------------
      30. 'sub
      31. L_rot:
      32. Ausgabe(80) = 255
      33. Ausgabe(70) = 255
      34. Ausgabe(63) = 0
      35. Spiout Ausgabe(1) , 84 'bytes werden an die Leds gesendet
      36. Waitms 20
      37. Ausgabe(80) = 0
      38. Spiout Ausgabe(1) , 84 'bytes werden an die Leds gesendet
      39. Return
      40. L_gruen:
      41. Ausgabe(63) = 255
      42. Ausgabe(70) = 255
      43. Ausgabe(80) = 0
      44. Spiout Ausgabe(1) , 84 'bytes werden an die Leds gesendet
      45. Waitms 20
      46. Ausgabe(63) = 0
      47. Spiout Ausgabe(1) , 84 'bytes werden an die Leds gesendet
      48. Return
      Alles anzeigen
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Nochmal ein Versuch, bei dem an der Max- Min-Stelle ein Lichtblitz (rot bzw grün) von 3msec abgesondert wird. Das blaue Licht in der Mitte deutet den Schwenkbereich an. Man sieht deutlich, dass die Blitze nicht sehr gleichmäßig kommen. Um die Ausgabe der Textspalten damit zu starten, kommen sie zur falschen Zeit. a_28_2c02f089 Und zu allem Überfluss nicht gleichmäßig a_52_eb39d6ae
      Raum für Notizen

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

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

    • Das ist der Sensor, ich vermute, das sind 100nF am Ausgang. So sind die auch im Datenblatt mal erwähnt. Dann gibt es die Formel Bandwidth with external capacitors = 1/(2 × π × 32 kΩ × C), da rechne ich dann bei 100nF 50Hz Bandbreite heraus. Sollte bei dem Rumrudern doch langen.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Ich glaub' ich hab' noch einen Denkfehler drin. Wenn ich meinen Schwenker in senkrechter Position habe, liefert der Sensor ca. 1,5V. Wenn ich ihn nach links neige, blitzt kurz rot auf, das heißt die Spannung am Sensor steigt, nach links geneigt blitzt grün auf, Spannung fällt. Das ist jetzt die Erdbeschleunigung, ganz normal. Nur wenn ich das langsam mache, blitzen die Leds gleich nach einer kleinen Auslenkung um die Senkrechte auf, da dürfte aber eigentlich kein Spannungshügel/Berg da sein a_27_b277ca12 , eher am größten Ausschlag von der Senkrechten. Entweder es kommt von einer zittrigen Hand, oder von einem Wurm im Gehirn.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Der y-Pfeil deutet nach unten, die Schwenkrichtung ist in der x-Richtung. Es wird auch nicht besser, wenn ich in der horizontalen Ebene schwenke. Die Min/Max sind immer zwischen den Umkehrpunkten. Vielleicht sollte ich mal den C erhöhen, um Zitterer zu eliminieren.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Genau! Y ist senkrecht
      Genau! X ist waagrecht
      Genau! Z ist waagrecht
      Ich messe x.
      Wenn der Stab senkrecht steht, liefert x die 1,5V, also Mittelstellung, da die Erdbeschleunigung nicht einfließt. Sobald ich neige, verändert sich die Spannung wegen Erdbeschleunigung.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Auf die Leds geschaut,
      waagrecht nach links=1,9V
      senkrecht=1,6V
      waagrecht nach rechts=1,3V
      Das passt mit dem Datenblatt zusammen. Der chip hat einen Spannungsregler und wird mit 3,3V betrieben

      Datenblattauszug:
      SENSITIVITY (RATIOMETRIC)2
      Each axis
      Sensitivity at XOUT, YOUT, ZOUT
      VS = 3 V
      270
      300
      330
      mV/g

      Es ist ja nicht so, das an den Umkehrspunkten die Beschleunigung am größten sein muss. Wenn ich einen Ball senkrecht hoch werfe, ist die Beschleunigung im Flug immer gleich der Erdbeschleunigung, auch am Flugbahnumkehrpunkt.

      Eine Beschleunigung ist ja eine Geschwindigkeitsveränderung/Zeit. Wenn ich den Stab schwenke, ist die Geschwindigkeit kurz vor dem Umkehrpunkt nicht sehr groß, sodass die Richtungsumkehr nicht soviel Beschleunigung ergibt. Insofern ist das max kurz vor dem Umkehrpunkt einfach die stärkste Geschwindigkeitsänderung. Wenn die immer an der gleichen Stelle wäre, wär's ja ok. Aber mein Arm ist wohl zu schlabbrig :S
      Raum für Notizen

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

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

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