APA102 RGB LED Strip Examples

techElder

Well-known member
I think its interesting. In the original post here with APA102 strip examples, there came some confusion on my part in understanding the code.

I'm building a project with a 1 meter strip of 144 LEDs. The main idea is to show a number as a bar of a certain percentage of the 144 LEDs in the strip. I kept running into problems with unexplained delays in the example code. I finally figured it out. Over exuberance! :D I found this situation replicated in many code examples.

The key is to send the colors for each LED in sequence, one-at-a-time. That means repeating that process to HOW_MANY_LEDS (144 in my case). The over exuberance came in when the multicolor idea came into the process with different colors for 7 LEDs in a group. Now we're sending a group of 7 LEDs information HOW_MANY_LEDS times! There is a lot of extra delay to do that, so timing is extended greatly. (Yes, I understand that any additional is just running out the end into the bit bucket! :D)

The fix is to change the FOR/NEXT loop to STEP 7 for the group of LEDs (6 in my case.) Now the FOR/NEXT count will keep up with HOW_MANY_LEDS. This also means that one has to match the LEDs in the group with HOW_MANY_LEDS so there is an integer division.

Here's a little diddy that came from the examples with a simple addition that makes it work as originally designed.

Code:
#picaxe 20x2
#no_table
#no_data

; =======================================================
; Example 7
; Set all LED modules on
; =======================================================

;          40X2                 5V -.-   Light strip
;     .-----__-----.                |
;     | RST    B.7 |                `--> RED +V
;     =            =  .--> SCK --------> BLU CK
;     | C.2    C.5 |--|--> SDO --------> GRN DI
;  .--| C.3    C.4 |  |             .--> YEL 0V
;  |  | D.0    D.3 |  |             |
;  |  | D.1    D.2 |  |         0V _|_
;  |  `------------'  |
;  `------------------'

; Set how many LED modules in the strip
Symbol HOW_MANY_LEDS = 144 '147/7

; Set the brightness of the LED while testing
; Use small values to keep current consumption low
Symbol BRIGHTNESS    = 10 ; 0 to 255 (full)

; Initialise the HSPI interface
#macro init()
  hspisetup spimode00, spifast
#endmacro

; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

; Send the start of data header
#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro

; Send a LED controlling command
#macro send( red, green, blue)
  sendPacket( $FF, blue, green, red )
#endmacro

; Send the end of data tail
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
  'sendPacket( $FF, $FF, $FF, $FF )
  'sendPacket( $FF, $FF, $FF, $FF )
#endmacro

PowerOnReset:

  ; Initialise the HSPI interface
  init

TurnAllLedsOn:
  ; Turn all LED modules on
   do
      head
      for w0 = 1 to HOW_MANY_LEDS step 6
         send( BRIGHTNESS, $00,        $00        ) ; red
         send( $00,        BRIGHTNESS, $00        ) ; green
         send( $00,        $00,        BRIGHTNESS ) ; blue
         send( BRIGHTNESS, BRIGHTNESS, $00        ) ; red + green
         send( BRIGHTNESS, $00,        BRIGHTNESS ) ; red + blue
         send( $00,        BRIGHTNESS, BRIGHTNESS ) ; green + blue
         'send( BRIGHTNESS, BRIGHTNESS, BRIGHTNESS ) ; white
         pause 50
         next
      tail
      head
      for w0 = 1 to HOW_MANY_LEDS step 6
         send( BRIGHTNESS, $00,        $00        ) ; red
         send( BRIGHTNESS, $00,        $00        ) ; red
         send( BRIGHTNESS, $00,        $00        ) ; red
         send( BRIGHTNESS, $00,        $00        ) ; red
         send( BRIGHTNESS, $00,        $00        ) ; red
         send( BRIGHTNESS, $00,        $00        ) ; red
         'send( BRIGHTNESS, $00,        $00        ) ; red
         pause 50
      next
      tail
      head
      for w0 = 1 to HOW_MANY_LEDS step 6
         send( $00,        BRIGHTNESS, $00        ) ; green
         send( $00,        BRIGHTNESS, $00        ) ; green
         send( $00,        BRIGHTNESS, $00        ) ; green
         send( $00,        BRIGHTNESS, $00        ) ; green
         send( $00,        BRIGHTNESS, $00        ) ; green
         send( $00,        BRIGHTNESS, $00        ) ; green
         'send( $00,        BRIGHTNESS, $00        ) ; green
         pause 50
      next
      tail
      head
      for w0 = 1 to HOW_MANY_LEDS step 6
         send( $00,        $00,        BRIGHTNESS ) ; blue
         send( $00,        $00,        BRIGHTNESS ) ; blue
         send( $00,        $00,        BRIGHTNESS ) ; blue
         send( $00,        $00,        BRIGHTNESS ) ; blue
         send( $00,        $00,        BRIGHTNESS ) ; blue
         send( $00,        $00,        BRIGHTNESS ) ; blue
         'send( $00,        $00,        BRIGHTNESS ) ; blue
         pause 50
      next
      tail
      head
      for w0 = 1 to HOW_MANY_LEDS step 6
         send( $00, $00, $00) ; black
         send( $00, $00, $00) ; black
         send( $00, $00, $00) ; black
         send( $00, $00, $00) ; black
         send( $00, $00, $00) ; black
         send( $00, $00, $00) ; black
         'send( $00, $00, $00) ; black
         pause 50
      next
      tail
   loop
 

hippy

Technical Support
Staff member
That's right -

Code:
head
for w0 = 1 to HOW_MANY_LEDS
  Send(...)
next
tail
will control HOW_MANY_LEDS individually. When sending sets of deta one needs to either change HOW_MANY_LEDS to HOW_MANY_SETS or add a step value for HOW_MANY_LEDS ...

Code:
head
for w0 = 1 to HOW_MANY_LEDS step 2
  Send(...)
  Send(...)
next
tail
Code:
symbol HOW_MANY_SETS = HOW_MANY_LEDS / 2
head
for w0 = 1 to HOW_MANY_SETS
  Send(...)
  Send(...)
next
tail
 

hippy

Technical Support
Staff member
Code:
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
  'sendPacket( $FF, $FF, $FF, $FF )
  'sendPacket( $FF, $FF, $FF, $FF )
#endmacro
Due to the way the APA102 ripples the data through the chain and latches the data, it may be necessary to send additional $FF,$FF,$FF,$FF packets to ensure they all latch the last data sent at the same time. The datasheet isn't exactly clear on this, but from other people who have used APA102 strips, it seems one $FF,$FF,$FF,$FF tail packet should be sent for every 64 LED's one has.

For 144 LED's; 144 / 64 = 2.25, rounded up = 3, so three sets of $FF,$FF,$FF,$FF.

Sending too many shouldn't create a problem if they aren't actually needed.
 

oracacle

Senior Member
interesting. I have only done limited work with these, The next project with them is in the works and will most likely use a 14m2
Last time I used a 20x2 due to ease of the HSPI interface for a project that I had very little time to spend on it.
I have noticed that often the LED brightness is often set with reducing each colour by the same amount instead of using the global value.
I wrote this as a little test, seemed to work well enough with 60 LEDs and should fade between colours. It seemed to work fine for 60 LEDs, they all appear to change at once.

altering 'brightness' between 0 and 31 will alter the brightness and is combined before transmitting, I use a b6 to actually send the brightness after a bit wise and 'b6 = brightness | %11100000'
The final project used a rotary encoder to change the colour and the brightness to the users requirement.

Code:
#no_table
#no_data
#terminal 9600

symbol press		= pinb.0
symbol dt   		= pinb.1
symbol clk  		= pinb.2

Symbol HOW_MANY_LEDS    = 26
Symbol BRIGHTNESS 	= b0 ; 0 to 255 (full)
symbol red_val    	= b1
symbol green_val  	= b2
symbol blue_val   	= b3
symbol tempbyte0  	= b4
symbol loop_val   	= b5
symbol reserved   	= b6		'now used for clobal brightness
symbol loop_val1  	= b7

symbol store_red  	= 0
symbol store_green	= 1
symbol store_blue 	= 2
symbol store_bright     = 3


'brightness = 1
'b6 = brightness| %11100000

'*************************************
'************Macros*******************
'*************************************
; Initialise the HSPI interface
#macro init()
  hspisetup spimode00, spifast
#endmacro

; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

; Send the start of data header
#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro

; Send a LED controlling command
#macro send( red, green, blue)
  sendPacket( b6, blue, green, red )
#endmacro

; Send the end of data tail
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
#endmacro
'*************************************
'********End Of Macros****************
'*************************************
PowerOnReset:
	let dirsb = %11111000
	
; Initialise the HSPI interface
	init
; Turn all LED modules off
	head
	for loop_val = 1 To 60 'HOW_MANY_LEDS     'enable how_many_leds when strip cut
		send( $00, $00, $00 ) ; 1 to last = Off
	next loop_val
	tail
	'------------------------------
	'brightness can be altered here
	brightness = 8
	b6 = brightness | %11100000
	'------------------------------
	'first set red to 100%
	red_val = 255
	green_val = 0
	blue_val = 0

fading_between_colours:
	do

	for loop_val1 = 0 to 254
		head
		for loop_val = 1 To HOW_MANY_LEDS
			send( red_val, green_val, blue_val )   
		next loop_val
		gosub rest_of_leds
		tail
		dec red_val
		inc green_val
	next loop_val1

	for loop_val1 = 0 to 254
		head
		for loop_val = 1 To HOW_MANY_LEDS
			send( red_val, green_val, blue_val )   
		next loop_val
		gosub rest_of_leds
		tail
		dec green_val
		inc blue_val
	next loop_val1

	for loop_val1 = 0 to 254
		head
		for loop_val = 1 To HOW_MANY_LEDS
			send( red_val, green_val, blue_val )   
		next loop_val
		gosub rest_of_leds
		tail
		dec blue_val
		inc red_val
	next loop_val1
		
	loop
	
	
rest_of_leds:
	'*****************************************************************************
	'this switches off led on end of strip - wont be needed once its cut to length
	for loop_val = 27 to 60
		send( $00, $00, $00 )
	next loop_val
	'******************************************************************************
	return
 

techElder

Well-known member
For / apa102 / next

I'm evaluating something I've noticed with my string. Pseudo code:

FOR x = 1 TO number-of-LEDs
SEND PACKET x
NEXT

My strip lights up short of the end by 2 LEDs. I changed the color of the first two LEDs, and they do indeed light the first 2 LEDs in the strip. Further investigation revealed that 2 iterations of the loop go by with no LED having been lit.

Then I had to leave town for a bit or two.
 

techElder

Well-known member
That's quite possibly the 'tail' $FF,$FF,$FF,$FF packet issue detailed in Post #3.
Yep, that was what was happening.

And, it seems that it doesn't matter what value is in that packet, either. So far, anything works as a value.

I couldn't find out why sending 32 bits every 64 LEDs latches values.

I do know that if you are short with those "tail" bits, then at least one LED on the end won't get updated (latched?) even though 144 LEDs were addressed.

I also know that if you have 144 LEDs in the string, you have to address them all before you send the "tail." Otherwise, the "tail" just becomes part of the next LEDs value.

I also know that much of this has been found out before, and I'm late for the game! :D
 

newplumber

Senior Member
texas said:
My strip lights up short of the end by 2 LEDs
I also was having a problem with that except it was only the last led on the chain
I don't have the code...but I just changed the number of leds to one more ...(only for my apa102 just white leds ... the rgb ones work perfectly)
what seems strange for me is
Code:
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
  sendPacket( $FF, $FF, $FF, $FF )
  'sendPacket( $FF, $FF, $FF, $FF )
#endmacro
does the exact same as
Code:
#macro tail()
  sendPacket( $00, $00, $00, $00 )
  sendPacket( $00, $00, $00, $00 )
 ' sendPacket( $00, $00, $00, $00 )
#endmacro

@oracacle cool code for the M2....I will have to try it out when i get back
 

techElder

Well-known member
APA102 Tail Changes

Sometimes we have to deal with LED myths and find a solution.

The problem I was having was understanding the "tail" packets. Hippy straightened me out with
... it seems one $FF,$FF,$FF,$FF tail packet should be sent for every 64 LED's one has....
Then I found out that the values one puts into the tail packet doesn't seem to make any difference ... except when you don't address all of the LEDs in the string of LEDs. Those of you that have done this accidently in your code know that those $FF make the last LEDs maximum brightness RGB or BRIGHT WHITE.

I want my LED bar to represent a percentage of the total LEDs in the string, so the easy way is to only work with 100 LEDs. That makes the math simple (I know it is simple math any way you do it, but follow along. :D )

So, I woke up this morning with the simple solution ... quit sending $FFs in the tail!

If you want to display 100 LEDs out of a 144 LED string, just set your "HOW_MANY_LEDS" constant to "100" and make sure your tail is full of "$00". $00 represents zero intensity for any LEDs beyond the 100 LEDs you are using for the bar. (You will have to clear those LEDs beyond 100 at some point, because they won't be written to while displaying the bar.)

And then you can easily start your bar with a bottom offset and not worry about the LEDs above the top of the bar. Pseudo code:

Code:
[INDENT]HEAD
FOR X = 1 TO STARTLEDMINUS1
   SEND($01,$01,$01) ; LOW WHITE
NEXT X
FOR X = STARTLED TO HOW_MANY_LEDS
   SEND($0F,$00,$00) ; YOUR BAR COLOR
NEXT X
TAIL ; with $00s instead of $FFs!
[/INDENT]
 

hippy

Technical Support
Staff member
This site has some further discussions on the data clocking and need for an end frame -

https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled

There are other sites relating to the APA102 out there, one of which is where I recall we found the information about needing multiple $FF,$FF,$FF,$FF tail packets when going beyond 64 LED's as I don't recall that being in the datasheet.

In our experimenting it also seemed that $FF,$FF,$FF,$FF tail packet was not ideal and created the 'full-on white' problem identified when not all LED's were being updated. But $FF,$FF,$FF,$FF is what the datasheets says should be sent, and that works when all LED's are refreshed, so that's what our example code deals with.

When refreshing more than a full set of LED's we are not sure exactly what is best to send; $00,$00,$00,$00, $FF,$00,$00,$00 or something else, possibly what the last data value of the first one you are not updating, but that's the same as having sent one more LED and just pushes the issue down the line.

It's a bit of a conundrum; is it even possible to just update those at the start of strip while leaving all others unaffected ?

I think we came to conclusion it might not be possible and just went with 'always refresh the lot' and send the $FF,$FF,$FF,$FF as detailed in the datasheet.
 

techElder

Well-known member
So far, I'm concluding that the tail frame $FF stuff comes from the datasheet showing all 1's in its example. Not exactly "documented."

Also, I'm concluding that the tail frame is just the last frame to be sent ... any frame will do. So, send something that does no harm! :D

It's a bit of a conundrum; is it even possible to just update those at the start of strip while leaving all others unaffected ?
My experience, so far, is that the "others" in your question are not changed. Except for the LEDs addressed in the tail frame. (Yes, I said addressed.)
 

oracacle

Senior Member
IIRC I during testing of the last project I had a strip of 60, and was going to use 26 (later used more) and had to set 27 - 60 to $00 $00 $00 before sending the standard tail. I did this with a simple sub routine which loop sending those, see code in post 4 - this is for a 20x2. I didn't realise that version of the code contained that sub procedure

newplumber,this is to fade between colours using a 14m2
Code:
#picaxe 14m2
#no_data
'#terminal 4800
setfreq m32
;define the hardware pins
Symbol SCK = C.0
Symbol PIN_SCK = pinC.0
Symbol SDO = C.1
Symbol PIN_SDO = pinC.1

;define constants
;there are only 31 levels of brightness 0 iss off and 31 brightest
;set mins as 1 so that LEDs will be on
symbol min_brightness	 = 1
symbol max_brightness 	= 31
symbol how_many_leds    = 111

;define variables
symbol sendbyte		= b0
symbol alter_bright	= b4
symbol brightness		= b5
symbol loop_val		= w4
symbol red_byte		= b10
symbol green_byte		= b11
symbol blue_byte		= b12


;Initialise the bit-banged SPI interface
#macro init()
	low SCK
	low SDO
#endmacro

;Send a four byte packet out via bit-banged SPI
;first packet is brightness.
#macro sendPacket( n1, n2, n3, n4 )
	sendbyte = n1 : gosub send_byte
	sendbyte = n2 : gosub send_byte
	sendbyte = n3 : gosub send_byte
	sendbyte = n4 : gosub send_byte
#endmacro

;send the start of data header
#macro head()
	sendPacket( $00, $00, $00, $00 )
#endmacro

;send a LED controlling command
#macro send( bright, red, green, blue)
	; when sending, the first value is brighness and can altered use bit wise and with %1110000
	sendPacket( bright, blue, green, red )
#endmacro

;send the end of data tail
#macro tail()
	sendPacket( $FF, $FF, $FF, $FF )
#endmacro

PowerOnReset:

	; Initialise the bit-banged SPI interface
	init
	; Turn all LED modules off
	head
	for loop_val = 1 To how_many_leds
		send($00, $00, $00, $00 ) 	; 1 to last = Off
	next
	tail
	brightness = 31
	red_byte = 255
	green_byte = 0
	blue_byte = 0
	alter_bright = brightness | %11100000
main:
	;do stuff here for selecting brightness and colour
	
	for green_byte = 0 to 255
		dec red_byte
		head
		for loop_val = 1 to how_many_leds
			;send led info here	
			sendpacket(alter_bright, blue_byte, green_byte, red_byte)
		next loop_val
		tail
	next green_byte
	red_byte = 0
	' pause 1000
	
	for blue_byte = 0 to 255
		dec green_byte
		head
		for loop_val = 1 to how_many_leds
			;send led info here	
			sendpacket(alter_bright, blue_byte, green_byte, red_byte)
		next loop_val
		tail
	next blue_byte
	green_byte = 0
	'pause 1000
	for red_byte = 0 to 255
		dec blue_byte
		head
		for loop_val = 1 to how_many_leds
			;send led info here	
			sendpacket(alter_bright, blue_byte, green_byte, red_byte)
		next loop_val
		tail
		
	next red_byte
	blue_byte = 0
	'pause 1000
	
	goto main


Send_byte:
	'send MSB first
	PIN_SDO = bit7 : pulsout SCK, 1
	PIN_SDO = bit6 : pulsout SCK, 1
	PIN_SDO = bit5 : pulsout SCK, 1
	PIN_SDO = bit4 : pulsout SCK, 1
	PIN_SDO = bit3 : pulsout SCK, 1
	PIN_SDO = bit2 : pulsout SCK, 1
	PIN_SDO = bit1 : pulsout SCK, 1
	PIN_SDO = bit0 : pulsout SCK, 1
	return
 

techElder

Well-known member
... before sending the standard tail.
No need to elevate the importance of the tail. Its just one more packet. As far as I can tell, its just a way to latch in the previous packet data. Use $00 and you will never see the results of sending the tail.
 

newplumber

Senior Member
thanks oracacle I'm not home so I didn't try either one of the codes but always nice to have both codes for X and M chips
I will try them out later on
One thing I don't get is...the strip wiring on the apa102s seem very small for if a person was going to
use full 5m length and have it change brightness
Why wouldn't they install SMD capacitors say every foot or so....
It seems to really make a difference when I installed them on mine (mine not SMD ...thru hole)
but over all I think the rgb apa102s is the best man invented since the 45* degree angle
 

techElder

Well-known member
Actually, on the longer runs of LEDs, others have injected power at several points along the length.
 

techElder

Well-known member
APA102 LED Brightness Variables

While playing with the original starter macros developed by RevEd, I've discovered the world of LED intensity variations. We've all seen it. LEDs of different colors look more or less bright to our eyes.

My string of APA102 LEDs are weak on blue. Red and green seem to be about the same to my eye. So, that led me to some research, and I found that there is a magic ratio for engineering TV CRT displays based on their "spectral characteristics." LEDs also have this ratio since they are manufactured to a certain dominant wavelength. However, it isn't the same ratio. The whole reason to obtain a correct ratio between the RGB is obtaining a true white.

So, rather than delve into the engineering of the ratios (that can be calculated if you know what characteristics your LEDs have), I chose the route that technicians often choose ... trial and error! :D

I set up this constant structure to allow changes to be easily made based on a ratio of green and blue to red, since my string has a more intense red color. Of course, your string may need a different strategy, but the constants and ratio calculation can easily be changed.

Code:
' Set the brightness of the LEDS based on a ratio of blue and green to red (red seems to be brightest)
symbol BRATIOGREEN   = 1                           ; RGB 1:1:5
symbol BRATIOBLUE    = 5                           ; RGB 1:1:5
Symbol BRIGHTNESSR   = 50                          ; 0 to 255 (ratios multiply this in green and blue)
symbol BRIGHTNESSG   = BRIGHTNESSR * BRATIOGREEN   ; (result must be < 255)
symbol BRIGHTNESSB   = BRIGHTNESSR * BRATIOBLUE    ; (result must be < 255)
' set the overall brightness of the string
symbol BRIGHTNESS    = 3 or %11100000              ; five LSB for intensity (required for three MSB = 1)
I've added constants for each RGB color based on the ratio of 1:1:5. I found that red and green on my string are the same but the blue needs 5 times more intensity. My white looks white and all three colors look consistent.

Now, to do this I've also added the ability to use the PWM intensity change that all APA102 strings have. The macro send( red, green, blue) masks out this feature by using a constant $FF for the brightness while adjusting RGB brightness en masse for each LED. I've put the BRIGHTNESS (CONSTANT/variable) into the send( red, green, blue) macro.

Code:
#macro send( red, green, blue)
  'sendPacket( $FF, blue, green, red )
  sendPacket( BRIGHTNESS, red, green, blue )
#endmacro
Now there are two ways to control brightness, and the BRIGHTNESS (CONSTANT/variable) can be offered to the user to control overall brightness (by changing it to a variable.)

As noted in the code, there are some limits to the BRIGHTNESSR constant due to there being a multiplier in BRIGHTNESSG and BRIGHTNESSB.

An example of the changes to the program follows:

Code:
      head
      for w0 = 1 to STARTLEDMINUS1
         send( BRIGHTNESSR, BRIGHTNESSG, BRIGHTNESSB) ; low white
      next w0
      for w0 = STARTLED to HOW_MANY_LEDS step 6
         send( BRIGHTNESSR, $00,        $00        ) ; red
         send( $00,        BRIGHTNESSG, $00        ) ; green
         send( $00,        $00,        BRIGHTNESSB ) ; blue
         send( BRIGHTNESSR, BRIGHTNESSG, $00        ) ; red + green
         send( BRIGHTNESSR, $00,        BRIGHTNESSB ) ; red + blue
         send( $00,        BRIGHTNESSG, BRIGHTNESSB ) ; green + blue
         'send( BRIGHTNESS, BRIGHTNESS, BRIGHTNESS ) ; white
         pause 50
         next
      tail
In this example, I've also added an offset to the beginning of the display. This is possible because I use $FF,$00,$00,$00 in the TAIL macro. :D

Code:
#macro tail()  ' one packet per 64 LED sets
  sendPacket( $FF, $00, $00, $00 )
  sendPacket( $FF, $00, $00, $00 )
  sendPacket( $FF, $00, $00, $00 )
#endmacro
 
Last edited:

premelec

Senior Member
As a reminder --- when the global brightness function is used the strobing rate goes way down which may be a problem/annoyance in some apps...
 

techElder

Well-known member
As a reminder --- when the global brightness function is used the strobing rate goes way down which may be a problem/annoyance in some apps...
premelec, I've read that so many times that it might just be a legend! :D

I've not seen any change in "strobing rate" in my string of LEDs by changing the global brightness. I'm not quoting what I read, but what I've seen. This legend may get into the weeds of the string's hardware design which could differ between manufacturers, but I can't prove it with my code.

Let's try real code. Please post some code that I can use to demonstrate that phenomenon. Thanks!
 

premelec

Senior Member
Sorry - it's just hearsay and in tables I've seen - I avoided using global because the rate was supposed to go from 2000 to 400 [like WS2812s] in the tables of various products that had RGB features... It's been a couple of years since I worked with any of these... the chip design certainly could have changed... whatever works! Shine on...
 

techElder

Well-known member
Well, ok, that's good to know also. The comments that I read led me to just try different combinations.

Now, I didn't put a scope on the innerds of the strip, but I would say from experience that only unique individuals are going to see much difference. Then I'll go out on a limb and say that most likely the lower "strobing rate" only makes a difference in those projects where they are swinging the LEDs around in a POV display.

premelec, thanks for your comments!
 

premelec

Senior Member
The bottom of this page has some specs - http://www.nledshop.com/pixelmini/ I think they used to show the global dim flicker rate - not shown there now. You probably need to use a photo transistor to look at the lights actual flicker - lots of people are happy with the 400Hz...
 

techElder

Well-known member
APA102 LED Flickering Legend

I did a bit more research about the APA102 and found a little more detail about the flickering possibilities (Adafruit author added hyperbole!) It kind of explains how the legend has continued (circa FEB-2018 from an Arduino library.)

Although the LED driver has an additional per-pixel 5-bit brightness setting, it is NOT used or supported here because it's a brain-dead misfeature that's counter to the whole point of {Adafruit} Dot Stars, which is to have a much faster PWM rate than NeoPixels. It gates the high-speed PWM output through a second, much slower PWM (about 400 Hz), rendering it useless for POV.
 

techElder

Well-known member
APA102 Tail Changes

So, with a little more research, time and effort :D, I discovered an interesting idea about the tail packet on my LED string.

Instead of sending this for the tail:

Code:
#macro tail()
   sendPacket($FF,$00,$00,$00)
   sendPacket($FF,$00,$00,$00)
   sendPacket($FF,$00,$00,$00)
#endm
I get the same results by sending this for the tail:

Code:
#macro tail()
   pulsout b.7, 1  ; B.7 is HSPI SCK (hspi clock) for my 20X2
#endm
Ok, this isn't done per the datasheet and could run into problems with future changes to the APA102, but it does show how superfluous the end frame is.
 

techElder

Well-known member
APA102 Clones and Updates

Ok, so my LED string is a clone. :confused: Yeah, I'm confused a lot.

What I ordered was what I received, and it works fabulously. Apparently, the original manufacturer of the APA102 has their site at http://neon-world.com/.

My clone references SK9822 and supposedly is an imperfect clone. I can't find out what imperfections it has, though.

And further research finds out that there is an "update" to the APA102 called APA102-8192 which incorporates changes to the global intensity where the color specification goes from 8-bit to 13-bit, but there is some confusion about compatibility. Supposedly this brings the color range to 8,192 colors. Here's a datasheet for that update (Chinese PDF).
 

newplumber

Senior Member
texas said:
Here's a datasheet for that update (Chinese PDF).
thanks for the datasheet and info ...although I'm still blurry when it comes to data sheets
if I read it right it says max supply volts = 5.5 so i am thinking if a person say runs the strips at
5.3 volts ...maybe that would help even more of keeping the each rgb led equal on the whole strip
in example if all leds was pushing the same color ...so in other words
if I was to add more caps and more power feed lines to the strip maybe it wouldn't hurt to ride the edge of max supply voltage too
(well maybe a little less) for myself I dont see the apa102 strip making a boost converter (which spikes voltage) but I could be wrong
just a thought
 

techElder

Well-known member
The designer has to consider that as each LED (red LED, green LED and blue LED) comes on, they pull more current through those itty-bitty power lines running down the length of the strip. The lines at the "head" end are carrying the full load of every LED on the strip, while the lines near the "tail" are only carrying the current of the last LEDs in the strip.

At low intensity levels (low current) this may not have any effect, but when you crank the current up for all of the LEDs (make them brighter), you may start seeing the effect of higher power in the power lines. The effect might be a voltage drop problem if the design starts out with a lower supply voltage.

Sprinkling capacitors along the power lines may help with those effects if they are caused by blinking LEDs, but voltage sag may be the result as more LEDs are lit up along the string. Distributed capacitance isn't going to solve a sagging voltage problem. Distributed power injection is.

What that means is to do some calculations on how many LEDs in series it will take to cause the power lines to exceed the minimum voltage required to light up that many LEDs. Common experience may say to inject new power every 60 LEDs or something similar.
 

oracacle

Senior Member
You need a fairly hefty power supply to run that many LEDs. I did a quick test the other day and with 155 at full brightness draw about 1.3amps while fading between 2 colours. I suspect it would be more if they were set to white at full brightness. I'm going to be using 110, not sure AA batteries are going to last long at that rate. Off the shelf phone chargers can provide 2.4amps @5v so that may well end up being my supply
 

Buzby

Senior Member
I asked on here about white apa102 strips, and mine have arrived today, but I'm 200 miles away from home !.

However, while searching for those white strips, I came across some RGB strings which might have a use in another part of my project.

https://wholesaler.alibaba.com/product-detail/DC5V-0-3W-christamas-digital-star_60715988336.html?spm=a2700.7724857.main07.19.7afd3b62EanAat

These have flexible wires, not flat pcb strip, between each LED. This means they can be arranged in any layout, not just straight lines. ( There are lots of different configurations available, like flat LEDS or shaped LEDs, but the link above is the only one I've listed. )

In my project the colour and brightness of each LED would be fixed during initialisation, and the main code will just turn LEDs on and off. I envisaged doing this by presetting the scratchpad in blocks of 4 bytes, each block set to '$E0,R,G,B', where the RGB values are fixed for each LED.

The main loop would then use code to set the first byte of each block to $E0 or $FF, then send the whole lot out through hspi, repeating with new $E0/$FF values each time.

I read somewhere that using this 5-bit brightness control can cause flickering, but as I'm only using full ON or OFF I don't envisage any problems.

Has anyone tried this method of switching these LEDS ?

Cheers,

Buzby
 

newplumber

Senior Member
oracale said:
Off the shelf phone chargers can provide 2.4amps @5v so that may well end up being my supply
They must have bigger/better phone chargers in the UK ..the ones I have 5vdc all seem to max .85amp +/-
and if I did find one with 2amp+ ..it seems the output wires would be to small for longer strips its just my thought.
but then again looking at the power supplys you can order with apa102 strips...they don't look much different.
I do know using a good PC power supply with 12 gauge stranded (I believe) works perfect in my project

Buzby said:
I came across some RGB strings which might have a use in another part of my project.
Thanks Buzby always good to know of other options ...even if I have to sell my car to order 5m 's worth (joking)
no but looks perfect for a analog clock etc
 

newplumber

Senior Member
texas said:
I have never seen any flickering on my LEDs no matter what I've done.
that's because your doing everything right :)
After I added extra power feed lines and extra caps to the whole 5m strip then each apa102 rgb led's brightness looked the same
but if you have the strip in a straight line for 5m (16.4 ft) and have it change colors ...even with 20X2 "Setfreq M64"
and look at a little of a angle down the strip it will show flicker from my experience...but if looking straight on 90* degrees to strip
it seems the flicker seems to go away unless you stare at it for a very long time.
 

oracacle

Senior Member
They must have bigger/better phone chargers in the UK ..the ones I have 5vdc all seem to max .85amp +/-
and if I did find one with 2amp+ ..it seems the output wires would be to small for longer strips its just my thought.
but then again looking at the power supplys you can order with apa102 strips...they don't look much different.
I do know using a good PC power supply with 12 gauge stranded (I believe) works perfect in my project
https://www.amazon.co.uk/s/ref=sr_nr_n_5?fst=as:off&rh=n:329082031,k:2.4amp+phone+charger&keywords=2.4amp+phone+charger&ie=UTF8&qid=1523520333&rnid=1642204031
Also USB is specified for up to 5 amps when called for. Copper is more conductive than steel so wire made of copper maybe of a smaller gauge and still have a higher current rating.

Most strip board is rated for 500mA, and look how small the traces are around the wholes, there is maybe 1.5mm of very thin copper there. It could be we are just used to building in margins of error and over doing things when it come to the thickness of wire we use.

If you find something that works for you then go for it. my current project has wire passing through a frame so they have to be small - the hole that each pass through is 1.8mm across so 18 gauge wire isn't going to work.
 

newplumber

Senior Member
oracacle said:
If you find something that works for you then go for it. my current project has wire passing through a frame so they have to be small - the hole that each pass through is 1.8mm across so 18 gauge wire isn't going to work.
thanks oracacle I never bought any of those kind of chargers multi ports ones but good to know
the reason I put in my two cents is when I first tried my 5m apa102 rgb strip spread straight out on a 16' board ...I had a very good power supply connected only to one end of the strip (same side of SPI connections)
and if I turned all 150 leds half brightness (127 for each RGB) for white color ... each led became dimmer within the last 30 leds
in example
121st led was showing brightness = to 125
122nd led was showing brightness = to 112
123rd led was showing brightness = to 119 ..etc even tho all leds were set for 127
maybe it was my cheap china strip of leds them selfs but after adding extra power lines ... even at full brightness all seem the same brightness
FWIW All my (16.4ft) led strips (apa102,non apa102 white leds,non apa102 rgb leds) always seem to have been soldered for connections every 3 ft +/-
its like someone is making the strips from left over ends of led strip rolls
 

techElder

Well-known member
FWIW All my (16.4ft) led strips (apa102,non apa102 white leds,non apa102 rgb leds) always seem to have been soldered for connections every 3 ft +/- its like someone is making the strips from left over ends of led strip rolls
Perhaps not made from leftovers, but certainly strips of LEDs have to be made from something of finite length. Therefore, there must be some connection somewhere that they are put together. I've cut them apart at that 3 ft. point before, but I've never desoldered one to see if it really is a junction or not.

I do have a 1M strip of 144 LEDs that is made up of two 72 LED strips. The junction is an obvious lap and the pitch is visibly incorrect.
 
Top