DotStars use two wires, unlike NeoPixel's one wire. They're very similar but you can write to DotStars much faster with hardware SPI and they have a faster PWM cycle so they are better for light painting.
Any pins can be used but if the two pins can form a hardware SPI port, the library will automatically switch over to hardware SPI. If you use hardware SPI then you'll get 4 MHz clock rate (that would mean updating a 64 pixel strand in about 500uS - that's 0.0005 seconds). If you use non-hardware SPI pins you'll drop down to about 3KHz, 1000 times as slow!
You can drive 300 DotStar LEDs with brightness control (set
brightness=1.0 in object creation) and 1000 LEDs without. That's because to adjust the brightness we have to dynamically recreate the data-stream each write.
You'll need the adafruit_dotstar.mpy library if you don't already have it in your /lib folder! You can get it from the CircuitPython Library Bundle. If you need help installing the library, check out the CircuitPython Libraries page.
You'll need to solder up your DotStars first. Verify your connection is on the DATA INPUT or DI and CLOCK INPUT or CI side. Plugging into the DATA OUT/DO or CLOCK OUT/CO side is a common mistake! The connections are labeled and some formats have arrows to indicate the direction the data must flow. Always verify your wiring with a visual inspection, as the order of the connections can differ from strip to strip!
For powering the pixels from the board, the 3.3V regulator output can handle about 500mA peak which is about 50 pixels with 'average' use. If you want really bright lights and a lot of pixels, we recommend powering direct from an external power source.
- On Gemma M0 and Circuit Playground Express this is the Vout pad - that pad has direct power from USB or the battery, depending on which is higher voltage.
- On Trinket M0, Feather M0 Express, Feather M4 Express, ItsyBitsy M0 Express and ItsyBitsy M4 Express the USB or BAT pins will give you direct power from the USB port or battery.
- On Metro M0 Express and Metro M4 Express, use the 5V pin regardless of whether it's powered via USB or the DC jack.
If the power to the DotStars is greater than 5.5V you may have some difficulty driving some strips, in which case you may need to lower the voltage to 4.5-5V or use a level shifter.
This example includes multiple visual effects. Copy and paste the code into code.py using your favorite editor, and save the file.
# CircuitPython demo - Dotstar import time import adafruit_dotstar import board num_pixels = 30 pixels = adafruit_dotstar.DotStar(board.A1, board.A2, num_pixels, brightness=0.1, auto_write=False) def wheel(pos): # Input a value 0 to 255 to get a color value. # The colours are a transition r - g - b - back to r. if pos < 0 or pos > 255: return (0, 0, 0) if pos < 85: return (255 - pos * 3, pos * 3, 0) if pos < 170: pos -= 85 return (0, 255 - pos * 3, pos * 3) pos -= 170 return (pos * 3, 0, 255 - pos * 3) def color_fill(color, wait): pixels.fill(color) pixels.show() time.sleep(wait) def slice_alternating(wait): pixels[::2] = [RED] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[1::2] = [ORANGE] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[::2] = [YELLOW] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[1::2] = [GREEN] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[::2] = [TEAL] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[1::2] = [CYAN] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[::2] = [BLUE] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[1::2] = [PURPLE] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[::2] = [MAGENTA] * (num_pixels // 2) pixels.show() time.sleep(wait) pixels[1::2] = [WHITE] * (num_pixels // 2) pixels.show() time.sleep(wait) def slice_rainbow(wait): pixels[::6] = [RED] * (num_pixels // 6) pixels.show() time.sleep(wait) pixels[1::6] = [ORANGE] * (num_pixels // 6) pixels.show() time.sleep(wait) pixels[2::6] = [YELLOW] * (num_pixels // 6) pixels.show() time.sleep(wait) pixels[3::6] = [GREEN] * (num_pixels // 6) pixels.show() time.sleep(wait) pixels[4::6] = [BLUE] * (num_pixels // 6) pixels.show() time.sleep(wait) pixels[5::6] = [PURPLE] * (num_pixels // 6) pixels.show() time.sleep(wait) def rainbow_cycle(wait): for j in range(255): for i in range(num_pixels): rc_index = (i * 256 // num_pixels) + j pixels[i] = wheel(rc_index & 255) pixels.show() time.sleep(wait) RED = (255, 0, 0) YELLOW = (255, 150, 0) ORANGE = (255, 40, 0) GREEN = (0, 255, 0) TEAL = (0, 255, 120) CYAN = (0, 255, 255) BLUE = (0, 0, 255) PURPLE = (180, 0, 255) MAGENTA = (255, 0, 20) WHITE = (255, 255, 255) while True: # Change this number to change how long it stays on each solid color. color_fill(RED, 0.5) color_fill(YELLOW, 0.5) color_fill(ORANGE, 0.5) color_fill(GREEN, 0.5) color_fill(TEAL, 0.5) color_fill(CYAN, 0.5) color_fill(BLUE, 0.5) color_fill(PURPLE, 0.5) color_fill(MAGENTA, 0.5) color_fill(WHITE, 0.5) # Increase or decrease this to speed up or slow down the animation. slice_alternating(0.1) color_fill(WHITE, 0.5) # Increase or decrease this to speed up or slow down the animation. slice_rainbow(0.1) time.sleep(0.5) # Increase this number to slow down the rainbow animation. rainbow_cycle(0)
The first thing we'll do is create the LED object. The DotStar object has three required arguments and two optional arguments. You are required to set the pin you're using for data, set the pin you'll be using for clock, and provide the number of pixels you intend to use. You can optionally set
DotStars can be driven by any two pins. We've chosen A1 for clock and A2 for data. To set the pins, include the pin names at the beginning of the object creation, in this case
To provide the number of pixels, assign the variable
num_pixels to the number of pixels you'd like to use. In this example, we're using a strip of
We've chosen to set
brightness=0.1, or 10%.
auto_write=True, meaning any changes you make to your pixels will be sent automatically. Since
True is the default, if you use that setting, you don't need to include it in your LED object at all. We've chosen to set
auto_write=False. If you set
auto_write=False, you must include
pixels.show() each time you'd like to send data to your pixels. This makes your code more complicated, but it can make your LED animations faster!
We've included a few helper functions to create the super fun visual effects found in this code.
wheel() which we just learned with the Internal RGB LED. Then we have
color_fill() which requires you to provide a
color and the length of time you'd like it to be displayed. Next, are
rainbow_cycle() which require you to provide the amount of time in seconds you'd between each step of the animation.
Last, we've included a list of variables for our colors. This makes it much easier if to reuse the colors anywhere in the code, as well as add more colors for use in multiple places. Assigning and using RGB colors is explained in this section of the CircuitPython Internal RGB LED page.
The two slice helpers utilise a nifty feature of the DotStar library that allows us to use math to light up LEDs in repeating patterns.
slice_alternating() first lights up the even number LEDs and then the odd number LEDs and repeats this back and forth.
slice_rainbow() lights up every sixth LED with one of the six rainbow colors until the strip is filled. Both use our handy color variables. This slice code only works when the total number of LEDs is divisible by the slice size, in our case 2 and 6. DotStars come in strips of 30, 60, 72, and 144, all of which are divisible by 2 and 6. In the event that you cut them into different sized strips, the code in this example may not work without modification. However, as long as you provide a total number of LEDs that is divisible by the slices, the code will work.
Our main loop begins by calling
color_fill() once for each
color on our list and sets each to hold for
0.5 seconds. You can change this number to change how fast each color is displayed. Next, we call
slice_alternating(0.1), which means there's a 0.1 second delay between each change in the animation. Then, we fill the strip white to create a clean backdrop for the rainbow to display. Then, we call
slice_rainbow(0.1), for a 0.1 second delay in the animation. Last we call
rainbow_cycle(0), which means it's as fast as it can possibly be. Increase or decrease either of these numbers to speed up or slow down the animations!
Note that the longer your strip of LEDs is, the longer it will take for the animations to complete.
We explained at the beginning of this section that the LEDs respond faster if you're using hardware SPI. On some of the boards, there are HW SPI pins directly available in the form of MOSI and SCK. However, hardware SPI is available on more than just those pins. But, how can you figure out which? Easy! We wrote a handy script.
We chose pins A1 and A2 for our example code. To see if these are hardware SPI on the board you're using, copy and paste the code into code.py using your favorite editor, and save the file. Then connect to the serial console to see the results.
To check if other pin combinations have hardware SPI, change the pin names on the line reading:
if is_hardware_SPI(board.A1, board.A2): to the pins you want to use. Then, check the results in the serial console. Super simple!
import board import busio def is_hardware_spi(clock_pin, data_pin): try: p = busio.SPI(clock_pin, data_pin) p.deinit() return True except ValueError: return False # Provide the two pins you intend to use. if is_hardware_spi(board.A1, board.A2): print("This pin combination is hardware SPI!") else: print("This pin combination isn't hardware SPI.")
For a more in depth look at what
dotstar can do, check out DotStar on Read the Docs.