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

[Bug] Colors on 3x3 Color Matrix Light on Robot Inventor Hub #619

Closed
johnscary-ev3 opened this issue Jan 26, 2022 · 14 comments
Closed

[Bug] Colors on 3x3 Color Matrix Light on Robot Inventor Hub #619

johnscary-ev3 opened this issue Jan 26, 2022 · 14 comments
Labels
bug Something isn't working software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime) topic: lights Issues involving lights

Comments

@johnscary-ev3
Copy link

I am using the 3x3 Color Matrix device on RI Hub.
All the standard colors in documentation work fine except for Violet and Magenta.
Color.VIOLET produces Red light and Color.MAGENTA produces Orange light.

These colors work fine with the color light built into the hub and also the color light on the Lego Remote control.

Thanks

@johnscary-ev3 johnscary-ev3 added the triage Issues that have not been triaged yet label Jan 26, 2022
@dlech
Copy link
Member

dlech commented Jan 26, 2022

Thanks for reporting. It looks like the hue is being truncated to a uin8_t, so don't work for hues greater than 255.

https://github.com/pybricks/pybricks-micropython/blob/126bbda90ed211d329dc8f31f608ad76f776f4c8/pybricks/util_pb/pb_conversions.c#L8

@dlech dlech added bug Something isn't working software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime) topic: lights Issues involving lights and removed triage Issues that have not been triaged yet labels Jan 26, 2022
dlech added a commit to pybricks/pybricks-micropython that referenced this issue Jan 26, 2022
The pb_powered_up_color_id_from_hue() function used uint8_t for the hue
argument, but expected values from 0-359, so values > 255 where being
truncated. This is fixed by changing the parameter type to uint16_t.

Also add doc comments and use macros instead of hard coded constants
while we are touching this.

Also wikipedia says the name of the hue at 150 deg is teal rather than
turquoise (other common names are *something* green, but teal is shorter).

Fixes: pybricks/support#619
dlech added a commit to pybricks/pybricks-micropython that referenced this issue Jan 26, 2022
The pb_powered_up_color_id_from_hue() function used uint8_t for the hue
argument, but expected values from 0-359, so values > 255 where being
truncated. This is fixed by changing the parameter type to uint16_t.

Also add doc comments and use macros instead of hard coded constants
while we are touching this.

Also wikipedia says the name of the hue at 150 deg is spring green
rather than turquoise. https://en.wikipedia.org/wiki/Tertiary_color

Fixes: pybricks/support#619
@johnscary-ev3
Copy link
Author

Hi Guys,
Thanks for the quick response and work on this issue.
I assume that your fix would go into next update/release of hub firmware.
Not sure when that will be, but in the meantime can we do a work around?
Since problem is in converting the hue to a "color number" for the 3x3 light device, can I just write that color number directly to the device. I am looking at the PUPDevice class docs and it seems like it would allow that, but I don't see enough info in docs to know how to use it for this. Do you have any info on that?
Thanks.

@dlech
Copy link
Member

dlech commented Jan 26, 2022

You can always grab the latest firmware from https://github.com/pybricks/pybricks-micropython/actions/workflows/build.yml?query=is%3Asuccess+branch%3Amaster if you don't want to wait for a release.

@johnscary-ev3
Copy link
Author

Hi, thanks for the input.
I will wait for new release, I think.

In meantime I found some info that allows me to use your PUPDevice class to directly set the 3x3 LED Matrix colors.
This allows me to set the Mode and Tuple data using the write(mode,tuple_data) method. Works great!
Can also use info() method to get id of matrix to check if correct module. It is 64 for this Matrix LED.
Note this allows me to use Mode 3, "Transitions" which is defined below. The "fade" one is sort of cool.
And you can set the brightness also in Mode 2, which I tested also. Mode 0 also works if you need that.
Maybe you can add some of these features to your ColorLightMatrix class in the future.
Take care.

`

0 1 2 3 4 5 6 7 8 9 10
off magenta violet blue turquoise mint green yellow orange red white
`

`mode 0 = M0 = "LEV O" = level output
Mode 0 has an argument 0..9 that enables green bands showing a sort of battery level form 0=empty to 9=full

mode 1 = M1 = "COL O" = color output
Mode 1 has an argument from 0 to 10, and all LEDs will light up brightly in that color (see table above).

mode 2 = M2 = "PIX O" = pixel output
Mode 2 has nine arguments: b*16+c, where b is brightness (0..9) and c is color (0..10)

mode 3 = M3 = "TRANS" = transitions
Mode 3 has one argument the transition effect: 0 is none (default), 1 is row-by-row, and 2 fade-down-fade-up.`

@laurensvalk
Copy link
Member

Note this allows me to use Mode 3, "Transitions" which is defined below. The "fade" one is sort of cool.

It's been a while since I looked at this, but I could not get this to work in the way I had hoped. I was hoping this could fade one set of 9 colors smoothly into the next. But it seems to always fully turn off, and then fade back in after a few seconds.

So I ended up using just mode 2 which lets you do (almost) everything manually.

Did you find other functionality that we missed?

@laurensvalk
Copy link
Member

In meantime I found some info that allows me to use your PUPDevice class to directly set the 3x3 LED Matrix colors.
This allows me to set the Mode and Tuple data using the write(mode,tuple_data) method. Works great!
Can also use info() method to get id of matrix to check if correct module. It is 64 for this Matrix LED.

Nice! This is usually how we explore sensor functionality when a new device comes out. If you find any interesting features on the other sensors that we don't support, feel free to let us know :)

@johnscary-ev3
Copy link
Author

Thanks for the comments.
I realize now that your Color class includes the brightness (v) parameter and your ColorLightMatrix class makes use of that to set the LED brightness. So, this class does basically everything you can need. You can make your own fade and bar graphs, so don't really need those built-in ones (mode 0 and 3). ( I also found the built-in fade goes down and then up. )

One thing I did notice is that the PUPDevice has a read method which returns info on each pixel. Not sure how to decode that yet, but that read back function might be useful for something. I suppose you could set the pixel Colors at one point and then read them back later before making changes, but not sure why one would need that ;0)
Thanks again for the support.

@dlech
Copy link
Member

dlech commented Jan 29, 2022

The read method probably doesn't check that the mode is actually receiving data, so what you are seeing is probably leftover data from something else.

@johnscary-ev3
Copy link
Author

Actually, after playing with this some, I found that the PUPDevice read(2) function, mode=2, returns a useful pixel status tuple.
Other read modes (0,1,3), just turn off the LEDs.
With mode =2 the tuple has a number for each pixel, 9 elements.
Each number is the combination of the color_number and the brightness b*16+c like shown in post above.
The read function seems to interpret the 8bit numbers as signed 8bits and so sometimes you get negative numbers for the higher brightness settings when you print the output.
Take care.

@Novakasa
Copy link

Novakasa commented Feb 4, 2022

Did this issue affect other devices as well, e.g. the Color & Distance Sensor? I had some reliability issues with detecting colors, but since have moved on to custom filtering of the hsv values.
Funnily enough, when debugging the procedure I made the same mistake when sending the hue as a bytearray, truncating it to 1 byte.

@laurensvalk
Copy link
Member

No, this was a mapping issue from HSV to lego color ids (not the other way around.)

I had some reliability issues with detecting colors

Did you try setting the detectable colors?

but since have moved on to custom filtering of the hsv values.

This is essentially what the aforementioned method does --- you specify the HSV values of your desired colors and then we find the best match when you try to detect the color.

@Novakasa
Copy link

Novakasa commented Feb 4, 2022

Yes, I did use detectable colors, but I've found that weighting the saturation more than the hue in the error function worked better for me, since my use case was detecting colorful markers on train tracks on black/white floor.
But even that was not reliable enough so I finally made it so hsvs can be logged and dumped over bluetooth so I could develop a reliable criterion on my PC:
image
image
So, my latest iteration uses a quite custom criterion that in my experience works very reliably by having a threshold based on sat*value and then averaging over the hue when below the threshold:

class TrainSensor:
    ...
    def update(self, delta):
        color = self.get_hsv()
        h, s, v = color.h, color.s, color.v
        h = (h-20)%360
        if s*v>3500:
            self.marker_samples += 1
            self.marker_hue += h
            return
        if self.marker_samples>0:
            if self.marker_samples>2: #filter out 9V train crossing artifact
                self.marker_hue//=self.marker_samples
                colorname = None
                colorerr = 361
                for color, chue in COLOR_HUES.items():
                    err = abs(chue-self.marker_hue)
                    if colorname is None or err<colorerr:
                        colorname = color
                        colorerr = err
                self.marker_exit_callback(colorname)
            self.marker_hue = 0
            self.marker_samples = 0

Surprisingly, this also works on a white floor, since the white areas between the "track sleepers" is small, so the value actually is still lower than for the color markers. I'm guessing it breaks down for saturated and bright floors though.

@laurensvalk
Copy link
Member

Nice work.

I've found that weighting the saturation more than the hue in the error function worked better for me, since my use case was detecting colorful markers on train tracks on black/white floor.

It could be interesting to make the weighing factors (or method?) configurable - feel free to start a dedicated discussion about this.

@Novakasa
Copy link

Novakasa commented Feb 4, 2022

Yeah I think that would be useful, I'll open an issue about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime) topic: lights Issues involving lights
Projects
None yet
Development

No branches or pull requests

4 participants