Skip to content

Commit

Permalink
Prepare for release (update all samples to the new interface, refine …
Browse files Browse the repository at this point in the history
…readme)
  • Loading branch information
tinue committed Dec 24, 2021
1 parent 7be3ae2 commit 89d6876
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 137 deletions.
11 changes: 10 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@
## Ideas
Possible contributions:
* Test multiple strips using different chip select pins
* Test multiple strips using the hardware SPI buses, specifically on the Pi 4
* Allow to reorder the LEDs, see below
* Simplify SPI handling, see below

## Reordering the LEDs
For most of the effects, the order of the LEDs is important. A color swipe through the rainbow,
or a marquee effect only look good if the LEDs are arranged in line with the expectations of the
person looking at the effect. For example, if you warp a strip around a Christmas tree, then
the effects will look strange: One would expect them to go from top to bottom, or from left to right, and not around the tree.
This is even visible with the small, 25 LED xmas tree from Pi Hut: The rainbow effect just does not look good. To fix this, we would need a lookup table that allows to rearrange the individual LEDs in a flexible manner. Matt Parker from the Youtube channel "Stand-up Maths" did an entire episode about this matter, and he promised to do another one this year (2021).

## On SPI handling
All that the library needs to do with SPI is write data as quickly as possible. For this, it needs to open the SPI bus, change the bus speed, and then write the data.
To make matters slightly more complicated is the fact that some APA102 LEDs (notably the Pimoroni Blinkt!) do not use any of the physical SPI buses of the Raspberry Pi. Instead, they use two of the general purpose IO pins for MOSI and SCLK. The SPI protocol must therefore be implemented in software, which is also known as "bitbang" mode.
Expand All @@ -19,4 +28,4 @@ In order to go back to this library, bitbang would have to be implemented. It's

So, if anyone wants to give this a go, then please try!

Once this works, some clever boilerplate needs to be added to select hardware or software SPI, and to select the proper hardware bus.
DONE, thanks @KAN-PC046: ~~Once this works, some clever boilerplate needs to be added to select hardware or software SPI, and to select the proper hardware bus.~~
112 changes: 0 additions & 112 deletions README.adoc

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,4 @@ the value from your application. Check `sample.py` to see how this is done.
- 2.3.0 (2019-11-24): Untested fix for SK9822 type LEDs; Fix name space; Update readme. Note: The namespace fix breaks compatibility with the previous version, hence the minor upgrade in the version number.
- 2.4.0 (2020-05-28): SPI: Switch from the deprecated Adafruit_GPIO to the Adafruit CircuitPython libraries; Re-test with Raspberry Pi OS 2020-05-27.
- 2.4.1 (2020-12-04): Remove global brightness parameter from the constructor; Re-test with Raspberry Pi OS 2020-12-02 (kernel 5.4) and latest Adafruit libraries. Fix default global brightness: The "conservative" value of 31 was actually 100%, because this is a 5 bit value. Also changing the branch names in Github to reflect current standards.
- 2.4.2 (2021-12-23): Add methods get_pixel and get_pixel_rgb, support to use all hardware SPI buses on RPI 4 (by explicit choice between hardware spi and bitbanging), thanks @KAN-PC046! Test with Raspberry Pi OS bullseye and Python 3.9. Add instructions on using a virtual env.
- 2.5.0 (2021-12-26): Add methods get_pixel and get_pixel_rgb, support to use all hardware SPI buses on RPI 4 (by explicit choice between hardware spi and bitbanging), thanks @KAN-PC046! Test with Raspberry Pi OS bullseye and Python 3.9. Add instructions on using a virtual env. Note: The interface changes, so the minor version is getting increased.
14 changes: 9 additions & 5 deletions apa102_pi/driver/colorcycletemplate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""The module contains templates for colour cycles"""
import time

from apa102_pi.driver import apa102


Expand All @@ -12,7 +13,8 @@ class ColorCycleTemplate:
"""

def __init__(self, num_led, pause_value=0, num_steps_per_cycle=100,
num_cycles=-1, order='rbg', bus_method = 'spi', spi_bus=0, mosi=None, sclk=None, ce=None):
num_cycles=-1, order='rbg', bus_method='spi', spi_bus=0, mosi=None, sclk=None, ce=None,
bus_speed_hz=8000000, global_brightness=4):
self.num_led = num_led # The number of LEDs in the strip
self.pause_value = pause_value # How long to pause between two runs
self.num_steps_per_cycle = num_steps_per_cycle # Steps in one cycle.
Expand All @@ -23,6 +25,8 @@ def __init__(self, num_led, pause_value=0, num_steps_per_cycle=100,
self.mosi = mosi # Master out slave in of the SPI protocol (ignored on spi)
self.sclk = sclk # Clock line of the SPI protocol (ignored on spi)
self.ce = ce # Chip select
self.bus_speed_hz = bus_speed_hz # Bus speed
self.global_brightness = global_brightness # Overall brightness of the strip

def init(self, strip, num_led):
"""This method is called to initialize a color program.
Expand Down Expand Up @@ -66,7 +70,8 @@ def start(self):
try:
strip = apa102.APA102(num_led=self.num_led, bus_method=self.bus_method, spi_bus=self.spi_bus,
mosi=self.mosi, sclk=self.sclk,
order=self.order, ce=self.ce) # Initialize the strip
order=self.order, ce=self.ce, bus_speed_hz=self.bus_speed_hz,
global_brightness=self.global_brightness) # Initialize the strip
strip.clear_strip()
self.init(strip, self.num_led) # Call the subclasses init method
strip.show()
Expand All @@ -80,9 +85,8 @@ def start(self):
strip.show() # repaint if required
time.sleep(self.pause_value) # Pause until the next step
current_cycle += 1
if self.num_cycles != -1:
if current_cycle >= self.num_cycles:
break
if self.num_cycles != -1 and current_cycle >= self.num_cycles:
break
# Finished, cleanup everything
self.cleanup(strip)

Expand Down
14 changes: 9 additions & 5 deletions runcolorcycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,41 @@
from apa102_pi.colorschemes import colorschemes

NUM_LED = 576
BRIGHTNESS = 15


def main():
# One Cycle with one step and a pause of three seconds. Hence three seconds of white light
print('Three Seconds of white light')
my_cycle = colorschemes.Solid(num_led=NUM_LED, pause_value=3,
num_steps_per_cycle=1, num_cycles=1, order='rgb')
num_steps_per_cycle=1, num_cycles=1, order='rgb', global_brightness=BRIGHTNESS)
my_cycle.start()

# Go twice around the clock
print('Go twice around the clock')
my_cycle = colorschemes.RoundAndRound(num_led=NUM_LED, pause_value=0,
num_steps_per_cycle=NUM_LED, num_cycles=2, order='rgb')
num_steps_per_cycle=NUM_LED, num_cycles=2, order='rgb',
global_brightness=BRIGHTNESS)
my_cycle.start()

# One cycle of red, green and blue each
print('One strandtest of red, green and blue each')
my_cycle = colorschemes.StrandTest(num_led=NUM_LED, pause_value=0,
num_steps_per_cycle=NUM_LED, num_cycles=3, order='rgb')
num_steps_per_cycle=NUM_LED, num_cycles=3, order='rgb',
global_brightness=BRIGHTNESS)
my_cycle.start()

# One slow trip through the rainbow
print('One slow trip through the rainbow')
my_cycle = colorschemes.Rainbow(num_led=NUM_LED, pause_value=0,
num_steps_per_cycle=255, num_cycles=1, order='rgb')
num_steps_per_cycle=255, num_cycles=1, order='rgb', global_brightness=BRIGHTNESS)
my_cycle.start()

# Five quick trips through the rainbow
print('Five quick trips through the rainbow')
my_cycle = colorschemes.TheaterChase(num_led=NUM_LED, pause_value=0.04,
num_steps_per_cycle=35, num_cycles=5, order='rgb')
num_steps_per_cycle=35, num_cycles=5, order='rgb',
global_brightness=BRIGHTNESS)
my_cycle.start()

print('Finished the test')
Expand Down
11 changes: 7 additions & 4 deletions runcolorcycle_blinkt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@
from apa102_pi.colorschemes import colorschemes

NUM_LED = 8
MOSI = 23 # Hardware SPI uses BCM 10 & 11. Change these values for bit bang mode
SCLK = 24 # e.g. MOSI = 23, SCLK = 24 for Pimoroni Phat Beat or Blinkt!
BRIGHTNESS = 31 # With only 8 LEDs there is no risk in overloading the Pi, so go for full brightness
MOSI = 23 # We need bitbang mode, and have to specify the GPIO pins used
SCLK = 24


def main():
# Paint white, red, green and blue once for one second
print('White, red, green, blue on all LEDs')
my_cycle = colorschemes.Solid(num_led=NUM_LED, pause_value=1, order='rgb',
num_steps_per_cycle=4, num_cycles=1, mosi=MOSI, sclk=SCLK)
num_steps_per_cycle=4, num_cycles=1, bus_method='bitbang', mosi=MOSI, sclk=SCLK,
global_brightness=BRIGHTNESS)
my_cycle.start()

# Five trips through the rainbow
print('Five trips through the rainbow')
my_cycle = colorschemes.Rainbow(num_led=NUM_LED, pause_value=0, order='rgb',
num_steps_per_cycle=255, num_cycles=5, mosi=MOSI, sclk=SCLK)
num_steps_per_cycle=255, num_cycles=5, bus_method='bitbang', mosi=MOSI, sclk=SCLK,
global_brightness=BRIGHTNESS)
my_cycle.start()

print('Finished the test')
Expand Down
11 changes: 7 additions & 4 deletions runcolorcycle_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@
from apa102_pi.colorschemes import colorschemes

NUM_LED = 25
MOSI =12 # Tree uses 12
SCLK = 25 # Tree uses 25
BRIGHTNESS = 10 # My Pi 4 managed full brightness of 31 (1.25A current draw); Increase the value at your own risk!
MOSI = 12 # We need bitbang mode, and have to specify the GPIO pins used
SCLK = 25


def main():
# Paint white, red, green and blue once for one second
print('White, red, green, blue on all LEDs')
my_cycle = colorschemes.Solid(num_led=NUM_LED, pause_value=1, order='rgb',
num_steps_per_cycle=4, num_cycles=1, bus_method='bitbang', mosi=MOSI, sclk=SCLK)
num_steps_per_cycle=4, num_cycles=1, bus_method='bitbang', mosi=MOSI, sclk=SCLK,
global_brightness=BRIGHTNESS)
my_cycle.start()

# Five trips through the rainbow
print('Five trips through the rainbow')
my_cycle = colorschemes.Rainbow(num_led=NUM_LED, pause_value=0, order='rgb',
num_steps_per_cycle=100, num_cycles=10, bus_method='bitbang', mosi=MOSI, sclk=SCLK)
num_steps_per_cycle=100, num_cycles=10, bus_method='bitbang', mosi=MOSI, sclk=SCLK,
global_brightness=BRIGHTNESS)
my_cycle.start()

print('Finished the test')
Expand Down
6 changes: 2 additions & 4 deletions sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@


def main():
# Initialize the library and the strip
strip = apa102.APA102(num_led=430, mosi=10, sclk=11, order='rbg')
# Initialize the library and the strip. This defaults to SPI bus 0, order 'rgb' and a very low brightness
strip = apa102.APA102(num_led=430)

# Increase the brightness to 100% (from the default of 12.5%)
strip.set_global_brightness(31)
# Turn off all pixels (sometimes a few light up when the strip gets power)
strip.clear_strip()

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="apa102-pi",
version="2.4.2",
version="2.5.0",
author="Martin Erzberger",
author_email="[email protected]",
description="Driver for APA102 LEDs on a Raspberry Pi",
Expand Down
Binary file modified xmastree.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions xmastree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
"""Ultra simple sample on how to use the library. Light up the xmas tree in red"""
from apa102_pi.driver import apa102
import time


def main():
# Initialize the library and the strip. The xmas tree needs bitbang. Default order 'rgb' is fine.
strip = apa102.APA102(num_led=25, bus_method='bitbang', mosi=12, sclk=25, global_brightness=31)

# Clear the buffer
strip.clear_strip()

# Loop over all pixels snd set them to red
for i in range(25):
strip.set_pixel_rgb(i, 0xFF0000) # Red

# Show the buffer, sleep 20 seconds
strip.show()
time.sleep(20)

# Clear the strip and shut down
strip.clear_strip()
strip.cleanup()

if __name__ == '__main__':
main()

0 comments on commit 89d6876

Please sign in to comment.