This guide will cover the basic functionality of the GlowBit Python library when driving a GlowBit Stick 1x8 module.
To follow along, it's best to have:
- A GlowBit Stick 1x8
- A Raspberry Pi Pico or Raspberry Pi
- Some Pin Headers
- Three jumper wires (eg Female-Female, Male-Male, or Female-Male, as appropriate)
- (Optional) a potentiometer with appropriate jumper cables for connecting to a Raspberry Pi Pico
- Function Listing
- Soldering a Pin Header
- Connecting the GlowBit Stick
- Download MicroPython Modules
- Creating a GlowBit Stick "Object"
- Running a Test Demo
- GlowBit Colours
- Lighting up Individual Pixels
- Filling All Pixels With a Solid Colour
- The Colour Wheel
- Remix: Using a stick.graph1D() object to display an ADC value
- Tiling Multiple GlowBit Stick 1x8 Modules
A full listing of the available functions can be found in the documentation.
The GlowBit Stick 1x8 is sold without a pin header soldered so you have two options:
- Connecting to the 4-pin header at the top of the module - great for easy breadboarding!
- Connecting to the 3-pin solder pads on the edge of the module for more of an "LED strip" feel
Pictured is the use of standard 2.54mm pin headers but you can also solder wires directly to any of the appropriate pads.
The GlowBit Stick requires three wires to be connected:
- Vcc: The positive power supply pin
- Din: The data input
- GND: The negative power supply pin
If using the 4-pin header these pins are labeled , Di, and -.
The GlowBit Stick 1x8 can be powered from either 3.3V or 5V and will consume up to about 250mA. On the Raspberry Pi Pico either the 3.3V or VBUS pins can power the GlowBit Stick. If using a Raspberry Pi either the 3.3V or 5V power pins on the GPIO header can be used.
The GlowBit library defaults to using pin 18 for data on both the Raspberry Pi and Raspberry Pi Pico. On the Raspberry Pi data can be connected to either GPIO18 or GPIO12. If using a Raspberry Pi Pico any GPIO pin can be used.
If using a data pin other than GPIO18 it will need to be specified when creating the GlowBit Stick object with the pin= keyword argument. eg: stick = glowbit.stick(pin=12).
The Do / Dout connections allow multiple modules to be joined together by connecting the Dout of one module to the Din of the next. See Tiling Multiple GlowBit Stick 1x8 Modules for more information.
For this guide the Stick has been mounted in a small breadboard along with a Raspberry Pi Pico.
The GlowBit MicroPython module requires two files:
The GlowBit module can also be installed through the Thonny package manager.
If you are running from a Raspberry Pi you will also need the low-level rpi-ws281x module. It can be found through Thonny's package manager or you can install it from the console with sudo pip3 install rpi-ws281x.
The glowbit.stick() object contains all the functionality required to create fun projects with your GlowBit Stick 1x8 module.
For greater flexibility, the stick() object takes several keyword arguments which modify how the GlowBit behaves. The most crucial ones, with their default values, are:
- brightness = 20
- rateLimitFPS = 30
- pin = 18
The brightness argument can either be an integer between 1 and 255 or a decimal value between 0.0 and 1.0. The brightness of the entire display is scaled by this value.
The rateLimitFPS argument allows the update rate of the display to be limited so that delays don't need to be manually programmed.
For example, to drive a GlowBit at full brightness with an update rate of 5 frames per second the following code can be used:
import glowbit stick = glowbit.stick(brightness = 255, rateLimitFPS = 5)
To make sure the GlowBit module and Python libraries are all configured correctly you can run this 3-line program to display a series of demonstration patterns:
import glowbit stick = glowbit.stick() stick.demo()
While executing, the following output will be printed to the Python shell:
stick.rainbowDemo() stick.pulseDemo() stick.graphDemo() stick.sliceDemo()
These functions can be called individually and you can study their code in glowbit.py by searching for rainbowDemo, sliceDemo, etc.
When specifying colours for GlowBit library functions a 32-bit GlowBit colour value is required. This is an integer which contains the red, green, and blue intensity "packed" into a single number.
In order to easily create colour values the function stick.rgbColour(r,g,b) is provided. It accepts red, green, and blue (RGB) intensity values scaled from 0 to 255 (inclusive) and returns a GlowBit colour value which can be used wherever colour is needed in the GlowBit library.
For convenience, the following functions are provided and return commonly used colours:
stick.red() stick.green() stick.blue() stick.yellow() stick.purple() stick.cyan() stick.white() stick.black()
The GlowBit library provides the function stick.pixelSet(pixelNumber, colour) which will set the colour of a given pixel indexed by pixelNumber. The pixel indices start at zero, so the 8 pixels on a GlowBit Stick 1x8 will be indexed 0 to 7.
Note that the stick.pixelSet() function doesn't change the physical pixel brightness, only the values of an internal buffer (in graphics terminology this is often called the framebuffer).
To change the actual emitted colour the stick.showPixels() function must be executed. This allows multiple pixels to be changed in the frame buffer at different times while allowing the visual changes to all occur simultaneously.
The following complete example will set the first pixel to white and the second to a custom RGB value:
import glowbit stick = glowbit.stick() colour = stick.white() pixelNumber = 0 stick.pixelSet(pixelNumber, colour) red = 30 green = 100 blue = 250 colour = stick.rgbColour(red, green, blue) pixelNumber = 1 stick.pixelSet(pixelNumber, colour) stick.pixelsShow()
The GlowBit library provides the stick.pixelsFill(colour) function which will set the colour of all pixels to the GlowBit colour value in "colour".
For example, the following code sets all pixels to yellow:
import glowbit stick = glowbit.stick() stick.pixelsFill(stick.yellow()) stick.pixelsShow()
The GlowBit library provides the function stick.wheel() which returns a full-intensity pure colour from the colour wheel. The function takes a single argument which is a colour wheel "angle" from 0 to 255. Both 0 and 255 are aligned with red, with the wheel returning red-yellow-green-cyan-blue-magenta-red for other values.
The following example uses the stick.wheel() function to display a colour gradient on the GlowBit Stick:
import glowbit stick = glowbit.stick() for index in range(8): c = stick.wheel(36*index) stick.pixelSet(index, c) stick.pixelsShow()
Note that the argument to stick.wheel() is multiplied by 36 so that the pixel at index 7 gets set with a wheel "angle" of 252 - almost a complete revolution to 255. As such, the first and last pixels should be red with the full colour spectrum appearing in between.
In the GlowBit library a "pulse" is an animated object which lights up pixels which start at one end of the stick, move along its length, then disappear off the end.
Creating and drawing a pulse is a two step process:
- Call stick.addPulse() to create a pulse - you can create multiple pulses with multiple calls to stick.addPulse()
- Call stick.updatePulses() to draw the pulse to the frame buffer and update its location
As before, a call to stick.pixelsShow() is needed to draw the frame buffer to the physical LEDs.
The following example creates a pulse once per second. Note that the rateLimitFPS= keyword argument is introduced to specify a frame rate at which the pixel colours are updated. The call the stick.pixelsShow() will "block" (ie: wait) if frames are drawn too quickly.
Note that this example uses stick.pixelsFill(stick.black()) to blank out the display before drawing the updated pulse. This is needed because neither stick.updatePulses() or stick.pixelsShow() turn any pixels off. The stick.pixelsFill(stick.black()) function sets the entire frame buffer to black to remove the previously drawn pulse before stick.updatePulses() draws it in its new location. Because nothing is physically drawn to the LEDs until stick.pixelsShow() is called this does not cause any flickering.
import glowbit stick = glowbit.stick(rateLimitFPS = 20) frame = 0 while frame < 300: if (frame ) == 0: stick.addPulse() stick.pixelsFill(stick.black()) stick.updatePulses() stick.pixelsShow() frame = frame 1
Note the use of frame == 0 - this is a modulo arithmetic operation which translates to "if frame is divisible by 20". ie: every 20th frame, once per second at 20 frames per second, a new pulse is added.
For a quick extension, the speed of the pulse can be changed with the speed= keyword argument. The units are pixels per frame times 100, so a value of 200 will move two pixels per frame and 50 would move one pixel every second frame. For example, the code below adds a pulse every 10 frames, alternating between fast and slow pulses.
The colour can also be set with the colour= keyword argument. The example below colours the fast pulses green and the slow ones red.
import glowbit stick = glowbit.stick(rateLimitFPS = 20) frame = 0 while frame < 300: if (frame) == 0: if (frame % 20) == 0: stick.addPulse(speed=200, colour=stick.green()) else: stick.addPulse(speed=50, colour=stick.red()) stick.pixelsFill(stick.black()) stick.updatePulses() stick.pixelsShow() frame = frame 1
Extension: you can make a pulse that is more than one pixel long by passing a list of colours. Try replacing one of the calls to stick.addPulse() with:
stick.addPulse(colour=[stick.green(), stick.yellow(), stick.orange()])
Note that the speed= argument can also be negative. Used along with the index= argument you can create pulses which move backwards.
The code below changes the previous example by animating the red pulses forwards and the green backwards:
import glowbit stick = glowbit.stick(rateLimitFPS = 20) frame = 0 while frame < 300: if (frame) == 0: if (frame % 20) == 0: stick.addPulse(speed=-200, index=7, colour=stick.green()) else: stick.addPulse(speed=50, colour=stick.red()) stick.pixelsFill(stick.black()) stick.updatePulses() stick.pixelsShow() frame = frame 1
Pulses have many other arguments which can be used to control their speed, initial location, changing colour with position, etc. The full list of arguments can be found in the full documentation.
The GlowBit stick library supports drawing graphs. Creation and drawing of graphs is very similar to pulses; the two-step process being:
- Create a graph object with stick.newGraph1D()
- Update the graph's value with stick.updateGraph1D(graph, value)
As usual, a call to stick.pixelsShow() is needed to draw the frame buffer to the physical LEDs.
For basic graphs, the graph object accepts the following keyword arguments (with default arguments):
- minIndex = 0
- maxIndex = 7
- minValue = 0
- maxValue = 255
The minIndex and maxIndex arguments specify where on the stick the graph is to be drawn and minValue and maxValue specify the values of the graph edges.
The following example will generate a graph object and animate it with values from 0 to 255 and back to 0:
import glowbit stick = glowbit.stick() graph = stick.graph1D() for value in range(0, 256, 10): stick.updateGraph1D(graph, value) stick.pixelsShow() for value in range(255, 0, -10): stick.updateGraph1D(graph, value) stick.pixelsShow()
Note: Because the graph occupies a known "area" the stick.updateGraph1D() function can automatically turn pixels off. A call to stick.pixelsFill() is not required.
This example is specific to the Raspberry Pi Pico because it has a built-in analog to digital converter (ADC).
Connect a potentiometer to the Raspberry Pi Pico as follows:
- One side to the 3V3 pin (DO NOT use a 5V supply pin - this will damage the Pico). The GlowBit Stick is safe to power from the 5V VBUS pin.
- The other side to a GND pin
- The center "wiper" pin to GP26_A0 - This is the ADC0 input pin
import glowbit import machine adc = machine.ADC(machine.Pin(26)) stick = glowbit.stick() graph = stick.newGraph1D(minIndex = 0, maxIndex = 7, minValue = 0, maxValue = 65535) while True: adcValue = adc.read_u16() stick.updateGraph1D(graph, adcValue) stick.pixelsShow()
The GlowBit Stick 1x8 is designed to be tiled end-to-end to create arbitrarily long "strips" of LEDs.
To do this, align the modules so that the Dout and Din pins of adjacent modules match then create solder bridges (or use wires, pin headers, etc) to connect boards together.
To accomodate the increased LED count in your code the numLEDs= keyword argument can be passed to glowbit.stick(). For example, a tiled arrangement of two GlowBit Stick 1x8 modules can be specified in code with:
stick = glowbit.stick(numLEDs=16)
After doing so, you would be able to use stick.pixelSet() with an index up to 15 or create a graph with maxIndex=15. Pulses automatically continue until they hit an edge, so no modification is needed to display them over tiled modules.
For example, the following code displays a rainbow spectrum across two tiled modules:
import glowbit stick = glowbit.stick(numLEDs = 16) for i in range(16): colour = stick.wheel(10*i) stick.pixelSet(i, colour) stick.pixelsShow()