-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from pimoroni/master
Added Pi 3 B+ support, compatibility with legacy examples, fixed rst readme
- Loading branch information
Showing
17 changed files
with
841 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,13 @@ | ||
# RPi WS281x Python | ||
|
||
This is an unofficial Python distribution of the ws281x library: http://github.com/richardghirst/rpi_ws281x | ||
This is the official Python distribution of the ws281x library: http://github.com/richardghirst/rpi_ws281x | ||
|
||
It's intended to support the Unicorn HAT library, but can be used for driving other WS281x-based LED projects. | ||
# Installing | ||
|
||
### Based Upon rpi_ws281x | ||
## From pip | ||
|
||
`unicornhat` is based upon a modified, Pi 2/3 compatible version of the RPi ws281x Library by Jeremy Garff. | ||
Most users should simply run: | ||
|
||
The library was modified by Richard Hirst. | ||
|
||
* Modified version: https://github.com/richardghirst/rpi_ws281x | ||
* Original: https://github.com/jgarff/rpi_ws281x | ||
``` | ||
sudo pip install rpi_ws281x | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# Example of low-level Python wrapper for rpi_ws281x library. | ||
# Author: Tony DiCola ([email protected]), Jeremy Garff ([email protected]) | ||
# | ||
# This is an example of how to use the SWIG-generated _rpi_ws281x module. | ||
# You probably don't want to use this unless you are building your own library, | ||
# because the SWIG generated module is clunky and verbose. Instead look at the | ||
# high level Python port of Adafruit's NeoPixel Arduino library in strandtest.py. | ||
# | ||
# This code will animate a number of WS281x LEDs displaying rainbow colors. | ||
import time | ||
|
||
import _rpi_ws281x as ws | ||
|
||
# LED configuration. | ||
LED_CHANNEL = 0 | ||
LED_COUNT = 16 # How many LEDs to light. | ||
LED_FREQ_HZ = 800000 # Frequency of the LED signal. Should be 800khz or 400khz. | ||
LED_DMA_NUM = 10 # DMA channel to use, can be 0-14. | ||
LED_GPIO = 18 # GPIO connected to the LED signal line. Must support PWM! | ||
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest | ||
LED_INVERT = 0 # Set to 1 to invert the LED signal, good if using NPN | ||
# transistor as a 3.3V->5V level converter. Keep at 0 | ||
# for a normal/non-inverted signal. | ||
#LED_STRIP = ws.WS2811_STRIP_RGB | ||
#LED_STRIP = ws.WS2811_STRIP_GBR | ||
#LED_STRIP = ws.SK6812_STRIP_RGBW | ||
LED_STRIP = ws.SK6812W_STRIP | ||
|
||
|
||
# Define colors which will be used by the example. Each color is an unsigned | ||
# 32-bit value where the lower 24 bits define the red, green, blue data (each | ||
# being 8 bits long). | ||
DOT_COLORS = [ 0x200000, # red | ||
0x201000, # orange | ||
0x202000, # yellow | ||
0x002000, # green | ||
0x002020, # lightblue | ||
0x000020, # blue | ||
0x100010, # purple | ||
0x200010 ] # pink | ||
|
||
|
||
# Create a ws2811_t structure from the LED configuration. | ||
# Note that this structure will be created on the heap so you need to be careful | ||
# that you delete its memory by calling delete_ws2811_t when it's not needed. | ||
leds = ws.new_ws2811_t() | ||
|
||
# Initialize all channels to off | ||
for channum in range(2): | ||
channel = ws.ws2811_channel_get(leds, channum) | ||
ws.ws2811_channel_t_count_set(channel, 0) | ||
ws.ws2811_channel_t_gpionum_set(channel, 0) | ||
ws.ws2811_channel_t_invert_set(channel, 0) | ||
ws.ws2811_channel_t_brightness_set(channel, 0) | ||
|
||
channel = ws.ws2811_channel_get(leds, LED_CHANNEL) | ||
|
||
ws.ws2811_channel_t_count_set(channel, LED_COUNT) | ||
ws.ws2811_channel_t_gpionum_set(channel, LED_GPIO) | ||
ws.ws2811_channel_t_invert_set(channel, LED_INVERT) | ||
ws.ws2811_channel_t_brightness_set(channel, LED_BRIGHTNESS) | ||
ws.ws2811_channel_t_strip_type_set(channel, LED_STRIP) | ||
|
||
ws.ws2811_t_freq_set(leds, LED_FREQ_HZ) | ||
ws.ws2811_t_dmanum_set(leds, LED_DMA_NUM) | ||
|
||
# Initialize library with LED configuration. | ||
resp = ws.ws2811_init(leds) | ||
if resp != ws.WS2811_SUCCESS: | ||
message = ws.ws2811_get_return_t_str(resp) | ||
raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message)) | ||
|
||
# Wrap following code in a try/finally to ensure cleanup functions are called | ||
# after library is initialized. | ||
try: | ||
offset = 0 | ||
while True: | ||
# Update each LED color in the buffer. | ||
for i in range(LED_COUNT): | ||
# Pick a color based on LED position and an offset for animation. | ||
color = DOT_COLORS[(i + offset) % len(DOT_COLORS)] | ||
|
||
# Set the LED color buffer value. | ||
ws.ws2811_led_set(channel, i, color) | ||
|
||
# Send the LED color data to the hardware. | ||
resp = ws.ws2811_render(leds) | ||
if resp != ws.WS2811_SUCCESS: | ||
message = ws.ws2811_get_return_t_str(resp) | ||
raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message)) | ||
|
||
# Delay for a small period of time. | ||
time.sleep(0.25) | ||
|
||
# Increase offset to animate colors moving. Will eventually overflow, which | ||
# is fine. | ||
offset += 1 | ||
|
||
finally: | ||
# Ensure ws2811_fini is called before the program quits. | ||
ws.ws2811_fini(leds) | ||
# Example of calling delete function to clean up structure memory. Isn't | ||
# strictly necessary at the end of the program execution here, but is good practice. | ||
ws.delete_ws2811_t(leds) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# NeoPixel library strandtest example | ||
# Author: Tony DiCola ([email protected]) | ||
# | ||
# Direct port of the Arduino NeoPixel library strandtest example. Showcases | ||
# various animations on a strip of NeoPixels. | ||
import time | ||
|
||
from neopixel import * | ||
|
||
|
||
# LED strip configuration: | ||
LED_COUNT = 40 # Number of LED pixels. | ||
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). | ||
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) | ||
LED_DMA = 10 # DMA channel to use for generating signal (try 10) | ||
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest | ||
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) | ||
LED_CHANNEL = 0 | ||
LED_STRIP = ws.SK6812_STRIP_RGBW | ||
#LED_STRIP = ws.SK6812W_STRIP | ||
|
||
|
||
# Define functions which animate LEDs in various ways. | ||
def colorWipe(strip, color, wait_ms=50): | ||
"""Wipe color across display a pixel at a time.""" | ||
for i in range(strip.numPixels()): | ||
strip.setPixelColor(i, color) | ||
strip.show() | ||
time.sleep(wait_ms/1000.0) | ||
|
||
def theaterChase(strip, color, wait_ms=50, iterations=10): | ||
"""Movie theater light style chaser animation.""" | ||
for j in range(iterations): | ||
for q in range(3): | ||
for i in range(0, strip.numPixels(), 3): | ||
strip.setPixelColor(i+q, color) | ||
strip.show() | ||
time.sleep(wait_ms/1000.0) | ||
for i in range(0, strip.numPixels(), 3): | ||
strip.setPixelColor(i+q, 0) | ||
|
||
def wheel(pos): | ||
"""Generate rainbow colors across 0-255 positions.""" | ||
if pos < 85: | ||
return Color(pos * 3, 255 - pos * 3, 0) | ||
elif pos < 170: | ||
pos -= 85 | ||
return Color(255 - pos * 3, 0, pos * 3) | ||
else: | ||
pos -= 170 | ||
return Color(0, pos * 3, 255 - pos * 3) | ||
|
||
def rainbow(strip, wait_ms=20, iterations=1): | ||
"""Draw rainbow that fades across all pixels at once.""" | ||
for j in range(256*iterations): | ||
for i in range(strip.numPixels()): | ||
strip.setPixelColor(i, wheel((i+j) & 255)) | ||
strip.show() | ||
time.sleep(wait_ms/1000.0) | ||
|
||
def rainbowCycle(strip, wait_ms=20, iterations=5): | ||
"""Draw rainbow that uniformly distributes itself across all pixels.""" | ||
for j in range(256*iterations): | ||
for i in range(strip.numPixels()): | ||
strip.setPixelColor(i, wheel(((i * 256 // strip.numPixels()) + j) & 255)) | ||
strip.show() | ||
time.sleep(wait_ms/1000.0) | ||
|
||
def theaterChaseRainbow(strip, wait_ms=50): | ||
"""Rainbow movie theater light style chaser animation.""" | ||
for j in range(256): | ||
for q in range(3): | ||
for i in range(0, strip.numPixels(), 3): | ||
strip.setPixelColor(i+q, wheel((i+j) % 255)) | ||
strip.show() | ||
time.sleep(wait_ms/1000.0) | ||
for i in range(0, strip.numPixels(), 3): | ||
strip.setPixelColor(i+q, 0) | ||
|
||
|
||
# Main program logic follows: | ||
if __name__ == '__main__': | ||
# Create NeoPixel object with appropriate configuration. | ||
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP) | ||
# Intialize the library (must be called once before other functions). | ||
strip.begin() | ||
|
||
print ('Press Ctrl-C to quit.') | ||
while True: | ||
# Color wipe animations. | ||
colorWipe(strip, Color(255, 0, 0)) # Red wipe | ||
colorWipe(strip, Color(0, 255, 0)) # Blue wipe | ||
colorWipe(strip, Color(0, 0, 255)) # Green wipe | ||
colorWipe(strip, Color(0, 0, 0, 255)) # White wipe | ||
colorWipe(strip, Color(255, 255, 255)) # Composite White wipe | ||
colorWipe(strip, Color(255, 255, 255, 255)) # Composite White + White LED wipe | ||
# Theater chase animations. | ||
theaterChase(strip, Color(127, 0, 0)) # Red theater chase | ||
theaterChase(strip, Color(0, 127, 0)) # Green theater chase | ||
theaterChase(strip, Color(0, 0, 127)) # Blue theater chase | ||
theaterChase(strip, Color(0, 0, 0, 127)) # White theater chase | ||
theaterChase(strip, Color(127, 127, 127, 0)) # Composite White theater chase | ||
theaterChase(strip, Color(127, 127, 127, 127)) # Composite White + White theater chase | ||
# Rainbow animations. | ||
rainbow(strip) | ||
rainbowCycle(strip) | ||
theaterChaseRainbow(strip) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# NeoPixel library strandtest example | ||
# Author: Tony DiCola ([email protected]) | ||
# | ||
# Direct port of the Arduino NeoPixel library strandtest example. Showcases | ||
# various animations on a strip of NeoPixels. | ||
import time | ||
|
||
from neopixel import * | ||
|
||
# LED strip configuration: | ||
LED_COUNT = 30 # Number of LED pixels. | ||
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). | ||
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) | ||
LED_DMA = 10 # DMA channel to use for generating signal (try 10) | ||
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest | ||
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) | ||
LED_CHANNEL = 0 | ||
#LED_STRIP = ws.SK6812_STRIP_RGBW | ||
LED_STRIP = ws.SK6812W_STRIP | ||
|
||
|
||
# Define functions which animate LEDs in various ways. | ||
def colorWipe(strip, color, wait_ms=50): | ||
"""Wipe color across display a pixel at a time.""" | ||
for i in range(strip.numPixels()): | ||
strip.setPixelColor(i, color) | ||
strip.show() | ||
time.sleep(wait_ms/1000.0) | ||
|
||
|
||
# Main program logic follows: | ||
if __name__ == '__main__': | ||
# Create NeoPixel object with appropriate configuration. | ||
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP) | ||
# Intialize the library (must be called once before other functions). | ||
strip.begin() | ||
|
||
print ('Press Ctrl-C to quit.') | ||
while True: | ||
# Color wipe animations. | ||
colorWipe(strip, Color(255, 0, 0), 0) # Red wipe | ||
time.sleep(2) | ||
colorWipe(strip, Color(0, 255, 0), 0) # Blue wipe | ||
time.sleep(2) | ||
colorWipe(strip, Color(0, 0, 255), 0) # Green wipe | ||
time.sleep(2) | ||
colorWipe(strip, Color(0, 0, 0, 255), 0) # White wipe | ||
time.sleep(2) | ||
colorWipe(strip, Color(255, 255, 255), 0) # Composite White wipe | ||
time.sleep(2) | ||
colorWipe(strip, Color(255, 255, 255, 255), 0) # Composite White + White LED wipe | ||
time.sleep(2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Example of low-level Python wrapper for rpi_ws281x library. | ||
# Author: Tony DiCola ([email protected]), Jeremy Garff ([email protected]) | ||
# | ||
# This is an example of how to use the SWIG-generated _rpi_ws281x module. | ||
# You probably don't want to use this unless you are building your own library, | ||
# because the SWIG generated module is clunky and verbose. Instead look at the | ||
# high level Python port of Adafruit's NeoPixel Arduino library in strandtest.py. | ||
# | ||
# This code will animate a number of WS281x LEDs displaying rainbow colors. | ||
import time | ||
|
||
import _rpi_ws281x as ws | ||
|
||
# LED configuration. | ||
LED_CHANNEL = 0 | ||
LED_COUNT = 16 # How many LEDs to light. | ||
LED_FREQ_HZ = 800000 # Frequency of the LED signal. Should be 800khz or 400khz. | ||
LED_DMA_NUM = 10 # DMA channel to use, can be 0-14. | ||
LED_GPIO = 18 # GPIO connected to the LED signal line. Must support PWM! | ||
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest | ||
LED_INVERT = 0 # Set to 1 to invert the LED signal, good if using NPN | ||
# transistor as a 3.3V->5V level converter. Keep at 0 | ||
# for a normal/non-inverted signal. | ||
|
||
# Define colors which will be used by the example. Each color is an unsigned | ||
# 32-bit value where the lower 24 bits define the red, green, blue data (each | ||
# being 8 bits long). | ||
DOT_COLORS = [ 0x200000, # red | ||
0x201000, # orange | ||
0x202000, # yellow | ||
0x002000, # green | ||
0x002020, # lightblue | ||
0x000020, # blue | ||
0x100010, # purple | ||
0x200010 ] # pink | ||
|
||
|
||
# Create a ws2811_t structure from the LED configuration. | ||
# Note that this structure will be created on the heap so you need to be careful | ||
# that you delete its memory by calling delete_ws2811_t when it's not needed. | ||
leds = ws.new_ws2811_t() | ||
|
||
# Initialize all channels to off | ||
for channum in range(2): | ||
channel = ws.ws2811_channel_get(leds, channum) | ||
ws.ws2811_channel_t_count_set(channel, 0) | ||
ws.ws2811_channel_t_gpionum_set(channel, 0) | ||
ws.ws2811_channel_t_invert_set(channel, 0) | ||
ws.ws2811_channel_t_brightness_set(channel, 0) | ||
|
||
channel = ws.ws2811_channel_get(leds, LED_CHANNEL) | ||
|
||
ws.ws2811_channel_t_count_set(channel, LED_COUNT) | ||
ws.ws2811_channel_t_gpionum_set(channel, LED_GPIO) | ||
ws.ws2811_channel_t_invert_set(channel, LED_INVERT) | ||
ws.ws2811_channel_t_brightness_set(channel, LED_BRIGHTNESS) | ||
|
||
ws.ws2811_t_freq_set(leds, LED_FREQ_HZ) | ||
ws.ws2811_t_dmanum_set(leds, LED_DMA_NUM) | ||
|
||
# Initialize library with LED configuration. | ||
resp = ws.ws2811_init(leds) | ||
if resp != ws.WS2811_SUCCESS: | ||
message = ws.ws2811_get_return_t_str(resp) | ||
raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message)) | ||
|
||
# Wrap following code in a try/finally to ensure cleanup functions are called | ||
# after library is initialized. | ||
try: | ||
offset = 0 | ||
while True: | ||
# Update each LED color in the buffer. | ||
for i in range(LED_COUNT): | ||
# Pick a color based on LED position and an offset for animation. | ||
color = DOT_COLORS[(i + offset) % len(DOT_COLORS)] | ||
|
||
# Set the LED color buffer value. | ||
ws.ws2811_led_set(channel, i, color) | ||
|
||
# Send the LED color data to the hardware. | ||
resp = ws.ws2811_render(leds) | ||
if resp != ws.WS2811_SUCCESS: | ||
message = ws.ws2811_get_return_t_str(resp) | ||
raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message)) | ||
|
||
# Delay for a small period of time. | ||
time.sleep(0.25) | ||
|
||
# Increase offset to animate colors moving. Will eventually overflow, which | ||
# is fine. | ||
offset += 1 | ||
|
||
finally: | ||
# Ensure ws2811_fini is called before the program quits. | ||
ws.ws2811_fini(leds) | ||
# Example of calling delete function to clean up structure memory. Isn't | ||
# strictly necessary at the end of the program execution here, but is good practice. | ||
ws.delete_ws2811_t(leds) |
Oops, something went wrong.