Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 23:26 17 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : DotStar LEDs

Author Message
MolsonB
Regular Member

Joined: 25/01/2015
Location: Canada
Posts: 48
Posted: 04:25pm 27 May 2015
Copy link to clipboard 
Print this post

The new ADAFruits Dotstar LEDs are pretty easy to command. They use the SPI out.
https://learn.adafruit.com/adafruit-dotstar-leds/overview

Below is a simple program to display the LEDS and a few little displays. The way to handle the brightness, I took from their Arduino library.



OPTION AUTORUN ON
OPTION DEFAULT NONE
OPTION EXPLICIT

CONST RED = &HFF0000
CONST YELLOW = &HFFFF00
CONST GREEN = &H00FF00
CONST CYAN = &H00FFFF
CONST BLUE = &H0000FF
CONST MAGENTA = &HFF00FF
CONST WHITE = &HFFFFFF
CONST BLACK = &H000000


' Global variables
DIM INTEGER LedDashNum=30
DIM INTEGER LedDashColors(LedDashNum-1)
DIM STRING LedDashOrder = "GBR" LENGTH 3

DIM INTEGER LedBrightness '0 to 256 See function for details

'********************** NOTE - AMPS draw ********************
' 1 LED 30 LEDS 120 LEDS
'Off 0.0012 0.036 0.145
'White 0.048 1.430 * 2.170 *
'Red 0.021 0.625 2.050
'Green 0.018 0.550 1.740
'Blue 0.018 0.540 1.700




Dotstar.SetBrightness(128,0)
LED.ColorTest()
'LED.NightRider(10, BLACK, RED, 1)
'LED.HeadChaseTail(10, BLACK, Dotstar.PackColor(0,10,0), 5)
'LED.Alert(RED)




'****************** LED Programs *****************
SUB LED.ColorTest()
Dotstar.SetBrightness(255,0)

Dotstar.SetColors(LedDashColors(), LedDashNum, RED)
Dotstar.Show
Pause(2000)

Dotstar.SetColors(LedDashColors(), LedDashNum, GREEN)
Dotstar.Show
Pause(2000)

Dotstar.SetColors(LedDashColors(), LedDashNum, Dotstar.PackColor(0,0,255))
Dotstar.Show
Pause(2000)

Dotstar.SetColors(LedDashColors(), LedDashNum, WHITE)
Dotstar.Show
Pause(2000)

Dotstar.SetBrightness(200,1)
Pause(1000)
Dotstar.SetBrightness(150,1)
Pause(1000)
Dotstar.SetBrightness(100,1)
Pause(1000)
Dotstar.SetBrightness(50,1)
Pause(1000)
Dotstar.SetBrightness(1,1)
Pause(1000)
Dotstar.SetBrightness(0,1)
Pause(1000)
ENd SUB



'LEDS bounce from 1 end to the other and back
SUB LED.NightRider (length as INTEGER, foreground as INTEGER, background as INTEGER, speed as INTEGER)

LOCAL INTEGER x, head = 0, tail = 0, direction = 0

'Start with the pre-length size already set
Dotstar.SetColors(LedDashColors(), LedDashNum, background)
For x=0 TO length-1
Dotstar.SetColor(LedDashColors(), x, foreground)
Next x
head = length-1
tail = -1

DO
Dotstar.Show
Dotstar.SetColor(LedDashColors(), head, foreground)
If tail >= 0 Then Dotstar.SetColor(LedDashColors(), tail, background)
PAUSE(speed) 'Pause 20 milliseconds (~50 FPS)

If direction = 0 Then
head = head + 1 'Forward
tail = tail + 1
Else
head = head - 1 'Backwards
tail = tail - 1
End If

if head = LEDDashNum Then
direction = 1
head = tail - 1
tail = LEDDashNum - 1
Else if head = -1 Then
direction = 0
head = tail + 1
tail = 0
End If

Loop

End Sub





' Runs 10 LEDs at a time along strip, cycling through red, green and blue.
' This requires about 200 mA for all the 'on' pixels + 1 mA per 'off' pixel.
SUB LED.HeadChaseTail(length as INTEGER, foreground as INTEGER, background as INTEGER, speed as INTEGER)
LOCAL INTEGER head = length, tail = 0

DO:
Dotstar.SetColor(LedDashColors(), head, foreground)
Dotstar.SetColor(LedDashColors(), tail, background)
Dotstar.Show 'Refresh strip
PAUSE(speed) 'Pause 20 milliseconds (~50 FPS)

head = (head + 1) MOD LedDashNum ' Increment head index. Off end of strip?
if head = 0 Then

If foreground = BLACK OR foreground = WHITE Then
foreground = RED
Else If foreground = RED Then
foreground = YELLOW
Else If foreground = YELLOW Then
foreground = GREEN
Else If foreground = GREEN Then
foreground = CYAN
Else If foreground = CYAN Then
foreground = BLUE
Else If foreground = BLUE Then
foreground = MAGENTA
Else If foreground = MAGENTA Then
foreground = WHITE
Else If foreground = WHITE Then
foreground = RED
End If

End IF

tail = (tail + 1) MOD LedDashNum 'Increment, reset tail index

LOOP
End Sub



SUB LED.Alert (foreground as INTEGER)
Dotstar.SetColors(LedDashColors(), LedDashNum, foreground)
DO
Dotstar.SetBrightness(255,1)
Pause(300)
Dotstar.SetBrightness(0,1)
Pause(100)
LOOP
End Sub



'****************** LED Code *****************


'Converts seperate RGB values into Hex notation
FUNCTION Dotstar.PackColor(redness as INTEGER, greenness as INTEGER, blueness as INTEGER) AS INTEGER
Dotstar.PackColor = ((redness and &HFF)<<16) + ((greenness and &HFF)<<8) + (blueness and &HFF)
END FUNCTION


SUB Dotstar.SetBrightness(brightness AS INTEGER, refresh as INTEGER)
' Stored brightness value is different than what's passed. This optimizes the actual scaling math later, allowing a fast 8x8-bit
' multiply and taking the MSB. Adding 1 here will intentionally roll over...so 0 = max brightness (color values are taken literally, no math),
'1 = min brightness (off), 255 = just below max brightness.
LedBrightness = (brightness + 1) MOD 256
If refresh = 1 THEN Dotstar.Show()
END SUB

FUNCTION Dotstar.GetBrightness() As INTEGER
Dotstar.GetBrightness = LEDBrightness - 1
END FUNCTION



'Set solid color lights
SUB Dotstar.SetColors(leds() as INTEGER, lednums as INTEGER, colors as INTEGER)
Local INTEGER x
FOR x=0 TO lednums-1
Dotstar.SetColor(leds(), x, colors)
NEXT x
End Sub

' Load RGB color into array
Sub Dotstar.SetColor(leds() as INTEGER, lednum as INTEGER, colors as INTEGER)
leds(lednum) = colors
end sub


'Sends SPI info to all LEDS
Sub Dotstar.Show()
LOCAL INTEGER LedDash(LedDashNum), LedUpper(LedUpperNum)
Dotstar.ProcessArray(LedDashColors(), LedDashNum, LedDashOrder, LedDash())

SPI OPEN 5000000, 3, 32 '5MHZ, Mode3, 32bits
SPI WRite 1, &H00000000
SPI WRITE LedDashNum, LedDash()
SPI WRITE 1, &HFFFFFFFF
SPI CLOSE
End SUb


SUB Dotstar.ProcessArray(leds() as INTEGER, lednums as INTEGER, order as String LENGTH 3, myArr() as INTEGER)
Local INTEGER x, redness, greenness, blueness

FOR x=0 TO lednums-1
redness = (leds(x) >> 16) and &HFF
greenness = (leds(x) >> 8) and &HFF
blueness = leds(x) and &HFF

If LEDBrightness > 0 Then '(color * brightness) /256
redness = (redness * LEDBrightness) >> 8
greenness = (greenness * LEDBrightness) >> 8
blueness = (blueness * LEDBrightness) >> 8
End If

If order = "GBR" Then
myArr(x) = (&HFF<<24) + ((greenness and &HFF ) <<16) + ((blueness and &HFF) <<8) + (redness and &HFF)
Else 'BGR
myArr(x) = (&HFF<<24) + ((blueness and &HFF ) <<16) + ((greenness and &HFF) <<8) + (redness and &HFF)
End If
NEXT x
End SUB


Edited by MolsonB 2015-05-29
MkII 44pin - v5.0

ColorMax 2 - v4.5
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 01:48am 28 May 2015
Copy link to clipboard 
Print this post

Hi Molson, great effort here. I am still waiting for my dot stars but will give this a whirl when they come in. Thanks for your code, it looks good.

EDIT... Did you have to do any level shifting to get these to work? (3.3v => 5V for the spi)Edited by viscomjim 2015-05-29
 
MolsonB
Regular Member

Joined: 25/01/2015
Location: Canada
Posts: 48
Posted: 02:28am 28 May 2015
Copy link to clipboard 
Print this post

I stored the colors in an array with RGB hex format, but did create a function to convert RGB(255,255,255) to hex. When I display to SPI, I dump it into a tmp array where I apply brightness and change the format of RGB to whatever the string of LEDs require. This keeps original data intact(I have two different Dotstars, where the mfg switched the order of GBR to BGR). Little annoying, just adds more code.
These are hungry LEDs, so a buck converter is required for each meter to bring 12volts down to 5, if running off a battery. USB cell chargers at 3amps work well and are cheap.


The power is 5volts, but the SPI is a straight connection.Edited by MolsonB 2015-05-29
MkII 44pin - v5.0

ColorMax 2 - v4.5
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2934
Posted: 10:11pm 08 Jun 2015
Copy link to clipboard 
Print this post

@MolsonB

Can you please confirm if you connected the APA's Clk and Data directly to the MM, or did you have some kind of level adjuster between the two parts?

The reason for asking is that when driving my APA's directly from the MM (at 3v3) then I get no response (as if the APA's have a floating input). Looking at the Datasheet (which contains many flaws) they quote a minimum of 0.7*Vdd for a Logic 1 input. So at 5v for the APA's power that equates to 3v3 Minimum for a logic 1 (right on the boundary of what my signal level is).

I know it is easy to try this (and I am about to) but I just wanted to know if you used any extra circuitry. Thanks

WW
 
MolsonB
Regular Member

Joined: 25/01/2015
Location: Canada
Posts: 48
Posted: 05:50am 10 Jun 2015
Copy link to clipboard 
Print this post

Connected the Clock and Data lines directly to LEDs. No messing around inbetween.

External 5volts to power the led strip, that's it. You are getting no response?
MkII 44pin - v5.0

ColorMax 2 - v4.5
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2934
Posted: 06:12am 10 Jun 2015
Copy link to clipboard 
Print this post

@MolsonB

I made a 'school-boy' error in that I forgot to connect the 5v supply ground to the MM ground

However, that said I am not getting 100% consistency on the data line without 'level shifting' the MM voltage output; the clk line works without any level shift.
I am using the APA102C variety; to ensure 100% reliability I'm thinking of level shifting both MM outputs using a simply 74HC buffer.

Making good progress on these APA LEDs - really fun to play with . . . .
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025