Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RGBLEDBoard Class #631

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft

Add RGBLEDBoard Class #631

wants to merge 10 commits into from

Conversation

bennuttall
Copy link
Member

@bennuttall bennuttall commented Mar 25, 2018

Adding an RGBLEDBoard class which allows users to create arbitrarily sized boards comprising multiple RGB LEDs. The API is assumed based on a mix of LEDBoard and RGBLED, i.e. it has on/off/toggle/blink/pulse, optional PWM, on/off/toggle should take a numerical argument (to control a single LED or a number of LEDs rather than the whole board), blink should allow on_color, off_color, etc.

from gpiozero import RGBLEDBoard

leds = RGBLEDBoard((2, 3, 4), (5, 6, 7), (7, 8, 9))

leds.value = ((1, 0, 0), (0, 1, 0), (0, 0, 1))

This paves the way for the API for classes for smarter RGB LEDs like APA102 (#551) and neopixels (#583) when we support those underlying protocols.

@bennuttall bennuttall changed the title Provide wrappers for LED groups on add-on boards, close #81 WIP: Add RGBLEDBoard Class Mar 25, 2018
@@ -59,15 +59,15 @@ def on(self):
Turn all the output devices on.
"""
for device in self:
if isinstance(device, (OutputDevice, CompositeOutputDevice)):
if isinstance(device, (OutputDevice, CompositeOutputDevice, RGBLED)):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this. @waveform80 @lurch do you think it's possible for RGBLED to extend OutputDevice or CompositeOutputDevice rather than just Device?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I got around this by implementing on/off/toggle directly in RGBLEDBoard rather than using the parent class. Just working on getting blink to work too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC @waveform80 implemented RGBLED as a child of Device rather than as a child of OutputDevice or CompositeOutputDevice because the value of an RGBLED is a 3-tuple and not a boolean or 0 -> 1 float.
And yup, RGBLED also implements it's own on / off / toggle / blink / pulse methods.

@codecov-io
Copy link

codecov-io commented Mar 25, 2018

Codecov Report

Merging #631 into master will increase coverage by 0.09%.
The diff coverage is 93.93%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #631      +/-   ##
==========================================
+ Coverage   85.58%   85.68%   +0.09%     
==========================================
  Files          36       36              
  Lines        7258     7336      +78     
==========================================
+ Hits         6212     6286      +74     
- Misses       1046     1050       +4
Impacted Files Coverage Δ
gpiozero/__init__.py 100% <ø> (ø) ⬆️
tests/test_boards.py 100% <100%> (ø) ⬆️
gpiozero/boards.py 92.01% <82.6%> (-0.55%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5032124...a63c181. Read the comment docs.

board or collection of LEDs.

The following example turns on all the LEDs on a board containing 5 LEDs
attached to GPIO pins 2 through 6::
Copy link
Contributor

@lurch lurch Mar 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean "2 through 9" ? ;)
EDIT: 10

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy/paste error!


from gpiozero import RGBLEDBoard

leds = RGBLEDBoard((2, 3, 4), (5, 6, 7), (7, 8, 9))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, probably shouldn't be using GPIO7 twice?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops!

pins_or_board
if isinstance(pins_or_board, RGBLEDBoard) else
RGBLED(
*pins_or_board, pwm=pwm, active_high=active_high, initial_value=(initial_value, ) * 3,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have you got initial_value=(initial_value, ) * 3, ? IMHO RGBLEDBoard should have the same init-params as https://github.com/RPi-Distro/python-gpiozero/blob/master/gpiozero/output_devices.py#L581

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I grabbed some implementation from LEDCollection which uses True / False for initial_value. Why do LEDCollection and LEDBoard have boolean initial_value when .value itself is an n-tuple?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure - perhaps @waveform80 remembers more?
You could argue that the initial_value for an LEDCollection should be a tuple-of-booleans of the same size as the .value, or you could argue that the initial_value is only a default value, so you'd want to initialise every LED in an LEDCollection with the same value? https://gpiozero.readthedocs.io/en/stable/api_boards.html#ledboard

I guess another option would be to for the __init__ to support both an initial_value param (a boolean) and an initial_values param (a tuple of values), with an exception being raised if both are supplied, or an exception being raised if the number of tuples in initial_values is incorrect?

*shrug*

Oh, and is LEDCollection the class that allows nesting, i.e. each child-element can be an LED or another LEDCollection object? I guess that would also make an initial_values param slightly more complex? (because you'd need to check that nested LEDCollections have the same number of tuples / sub-nested LEDCollections etc.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need consistency foremost. So I'll go for initial_value being a single value for now. Do we have any classes where initial_value is a tuple the length (and shape) of the board itself? I do like the idea of an optional single value or tuple. The tricky thing (I think) is working out the length and shape at the point of looking it up in kwargs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on second thoughts, it makes more sense that it follows RGBLED in expecting a ringle 3-tuple (in this case all RGBLEDs would be set to the same colour). This is also consistent with LEDBoard in that LEDBoard takes the same initial_value as LED or PWMLED.

Anyone wanting to set a more specific range of colours can do so manually after init.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on second thoughts, it makes more sense that it follows RGBLED in expecting a ringle 3-tuple (in this case all RGBLEDs would be set to the same colour).

Haha, exactly as I suggested above ;-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got there in the end!

@bennuttall
Copy link
Member Author

Getting there! All tests passing except the blink ones, and I need to add some more blink and pulse tests, as well as look at nested RGBLEDBoards.

I'm not entirely happy with the implementation of the blink tests:

board.blink()
assert board.value == ((1, 1, 1), (1, 1, 1))
board.off()
board[0].blink()
assert board.value == ((1, 1, 1), (0, 0, 0))

Ping @martinohanlon

with pytest.raises(ValueError):
RGBLEDBoard(2, 3, 4)

def test_rgbledboard_bad_init_pwm():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused by these tests.

RGBLEDBoard((2, 3, 4)) is expected to raise PinPWMUnsupported because the default for pwn is True (https://github.com/RPi-Distro/python-gpiozero/pull/631/files#diff-8e73cd872390a78e8e626359ec7c5837R1074)

But why are tests such as RGBLEDBoard((2, 3, 4), (5, 6, 7)) expected to pass?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got ya.

I like the comment above it # dirty, but it does the job

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

@bennuttall bennuttall changed the title WIP: Add RGBLEDBoard Class [WIP] Add RGBLEDBoard Class Sep 20, 2018
@bennuttall
Copy link
Member Author

@lurch I'm struggling to comprehend the herculean blink method as implemented in RGBLED. Would you be able to take a look and see if you can implement it for RGBLEDBoard or perhaps we could pair on it some time?

@bennuttall bennuttall added this to v1.5 (if possible) in Roadmap Oct 4, 2018
@bennuttall bennuttall self-assigned this Oct 4, 2018
@bennuttall bennuttall moved this from v1.5 (if possible) to v1.6 (definite) in Roadmap Jan 15, 2019
@bennuttall bennuttall added this to Triage in Triage Feb 8, 2019
@bennuttall bennuttall moved this from Triage to In progress in Triage Feb 9, 2019
@bennuttall bennuttall marked this pull request as draft February 22, 2021 18:29
@bennuttall bennuttall changed the title [WIP] Add RGBLEDBoard Class Add RGBLEDBoard Class Feb 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Roadmap
v1.6 (definite)
Triage
  
In progress
Development

Successfully merging this pull request may close these issues.

None yet

4 participants