pblesi / touch_light

A wifi-enabled touch light for keeping in contact with friends and family
12 stars 20 forks source link

Clarification of Behavior of Light #4

Open coderforlife opened 5 years ago

coderforlife commented 5 years ago

I have built 1.5 of these. For the one that is essentially complete I have tested that sending touch events via command line do cause the light to change colors. However I have noticed other strange behavior and wondering if these are expected, how to fix, and how they can be changed:

It would be nice to give some information about how the device is supposed to behave with the code given. What are the timeouts? What is a touch on the device supposed to do?

(Note that at the moment my touch plate isn't actually working but I was simulating it by messing with the D3/D4 resistor)

pblesi commented 5 years ago

Hi @coderforlife,

This looks great and is largely the behavior you want. The behavior you are seeing when messing with the resistor is largely accurate. If the light has not been touched for over 10 seconds, then the first time it is touched it will change to its default color. At this point if it is touched again within a ten second window, it will pick a random color within a restricted distance of its current color. Continually touching the light will reset this 10 second timer and randomly deviate the light's color.

The "stuck" behavior you are experiencing is just a result of the randomness not being so random sometimes.

The lighter and darker effect is also programmed in as the light gets progressively brighter while it continues to be touched.

The way that the consensus algorithm works for the lights is that they broadcast their state (the messages you are seeing) every 5 seconds. At the same time the light receives messages from the other lights. If it ever detects a message with a newer timestamp, it will update its state (and color) to reflect this newer message.

Finally, the touch light does turn off after not being touched for a predefined amount of time. The time frame for this is based on the number of clock cycles but is about 1 to several hours.

I hope this helps!

coderforlife commented 5 years ago

I am going to try to fork and make the following changes if possible:

coderforlife commented 5 years ago

One major problem I have found going over the code is that the colorWheel function operates quite poorly. It seems to be very loosely based on HSV conversion - but if so is implemented incorrectly. I converted it into Python and plotted the results when going from 0 to 255 and get the following image:

colorwheel-old

The reds, greens, and blues are very prominent but other colors are difficult to get. The NeoPixel interprets the RGBs a little different and you have a dimming of about 40% by default so you get slightly better results, but still, pretty bad.

I implemented it as a more legitimate HSV conversion (but still using hue and value (brightness) from 0 to 255 with saturation fixed to max) and get the following results:

colorwheel-new

This has massively better colors I think.

On the light itself the quality difference is also noticeable doing that first run-through-the-colors and during later touches. Obviously the default values for the different colors are off now (0 is solid red, not solid green, but 170 is still solid blue).

The code below is what I am using now. I am still working on a pull request. Can you see any problems with it based on your experience with the Photon and NeoPixel? (note that the brightness scaling is done exactly as you do it right now, I just used a helped function).

byte scale(byte x, float scale) { return (byte)(x * scale + .5); }

// Converts HSV color to RGB color
// hue is from 0 to 255 around the circle
// saturation is fixed to max
// value (brightness) is from 0 to 255
uint32_t wheelColor(byte hue, byte value) {
    int H6 = 6*(int)hue;
    byte R = 0, G = 0, B = 0;
    // each 1/6 of a circle (42.5 is 1/6 of 255)
    if (hue < 43) { R = 255; G = H6; }
    else if (hue < 86) { R = 510-H6; G = 255; }
    else if (hue < 128) { G = 255; B = H6-510; }
    else if (hue < 171) { G = 1020-H6; B = 255; }
    else if (hue < 213) { R = H6-1020; B = 255; }
    else { R = 255; B = 1530-H6; }
    float brightness = value / 255.0;
    return strip.Color(scale(R, brightness), scale(G, brightness), scale(B, brightness));
}
pblesi commented 5 years ago

@coderforlife,

This looks amazing! I'll take a closer look at the code when I get a chance, but generally, this looks really exciting. Can't wait for a PR!