Dividing 765 PWM (RGB LED) Values to the 1440 minutes of a Day

Hi All,

I am currently trying to build a forced synesthesia clock. One that will tell the time, vaguely, through the RGB colour spectrum.

I have an 8x8 RGB matrix working via pin 9,10, & 11 on a UNO and a DS1307 hooked up to A4 & A5.

Everything works fine in isolation.

However as a whole...

Running through the combinations of the three PWM channels which offer 255+255+255 = 765 Values. (See pic attatched)

There are 1440 minutes in a Day

This results in a rather messy value change every 1.88235294118 minutes

What is the best day distribute the values through out the day?

Should I be thinking about the 112.941176471 intervals in the 86400 seconds in a day?

Or should I be looking at the splitting the day into six 4hr chunks and using a fade instruction?

Thanks for any help.

Very simple:

You will notice that the color changes follow the same pattern, offset by 120 degrees (1440 / 3 = 480 minutes). So if you represent one color in a table / function, the two other colors are simply 480 / 960 minutes later.

If you start with blue, its output is 0 for the 1st 480 minutes; then linearly rising to 255 for the next 480 minutes and then linearly decreasing to 0. That can be done via a table or via a function.

//return blue's color
unsigned char dc_blue(unsigned short minute) {
  minute = minute % 1440; //range bound minute
  if (minute < 480) return 0;
  if (minute < 480*2) return 255ul * (minute - 480) / 480;
  else return 255ul * (1440 - minute) / 480;
}

When you need to generate the color, you just need to do:

  analogWrite(LED_BLUE, dc_blue(minute)); //write blue led's duty cycle
  analogWrite(LED_GREEN, dc_blue(minute + 480)); //write green led's duty cycle, 480 minutes later 
  analogWrite(LED_RED, dc_blue(minute + 720)); //write red led's duty c ycle, 720 minutes later

Done.

Now, the biggest dc would be 255 * 480 / 480, and in that process, you can produce a number bigger than 64k so we used ul in the calculation. That can be costly.

If you notice the math, however, you can simplify it down to
(minute - 480) * 8 / 15. That's roughly 0.5 so you can simplify the math do (minute - 480) >> 1;

Now, if 0.5x doesn't exactly work for you, (8/15 is roughly (8/16) * (1+1/16)). So you math gets simplified to

dc = (minute - 480) >> 1;
dc += dc >> 4;

Should I be thinking about the 112.941176471 intervals in the 86400 seconds in a day?

Yes.

However note that while you can get 255+255+255 = 765 Values you will not be able to perceive 765 colours or anything like it. The response of the eye is non linear and so there will be large intervals of time when you can perceive no change at all.
You might want to build some gamma correction into your display values:-

0-255 = 256, x 3 = 768.
1440/768 = 1.875, kind of messy.
But,1440/2 = 720.
768-720 = 48. /2 = 24
So change every 2 minutes. From 11:48 to 12:12 change once a minute.

How about:
Always reset everything to the starting point at midnight including the interval timer.
change the values every 113 seconds.
You miss the last combination but I doubt it can be detected.

--- bill

Someone posted that all 3 combinations of numbers does not equal 768.
The picture presented shows cycles of combinations from 0 to 127 - or 128 chances for a combination, x 6 = 768 combinations.
Whether its 765 or 762 does not matter a whole lot, it still comes down to this: do you keep the minutes in whole increments, and if so how is that addressed, or are the minutes allowed to be partial, and how is that addressed?

Assuming "yellow" is equal portions of Red and Green:
Does a yellow composed of R=128 and G=128 (R,G 50/50) have the same brilliance as a red of R=255 or a green of G=255?
Does a yellow composed of R=255 and G=255 (R,G 50/50) have twice the brilliance as a red of R=255 or a grenn of G=255?

WIll the plot above result a significantly bright red and green but a muted yellow?

How about an RGB/minute array in PROGMEM?

The currents for the individual colors can also be controlled indepently of the time they are to change at, with external variable resistances for example, if one finds a color to be too bright at select times of the day.

I've done a rainbow "orb" using the exact same ramp up/down technique described in the OP.
It used a single diffused 5mm RGB led with a ping pong ball on top to increase the size and
diffusion. I drilled a hole just large enough to allow the ball to sit on top of the LED.
It looks pretty awesome and I did no color correction.

Visually one thing that I did notice is that the RGBs I have is that
the led itself can not perfectly generate the mixed colors because of
the location/design of the individual leds inside.
i.e. you can see the individual colors of the LEDS inside the RGB LED depending
on the viewing location and angle.
Since this is inherent in the LED there is nothing that can be done to eliminate this.
The ping-pong ball cover makes a big difference.
With the ping-pong ball cover and from a bit of distance it isn't really too noticeable.
But if you look very closely, each R,B,G color is a bit more pronounced in certain areas
of the "orb".

--- bill

I made a simple test RGB clock some months ago where the primary colours were mapped to the hours, minutes and seconds of the day.

RGB_Clock_003.ino (1.42 KB)

Perhaps the OP will rejoin the conversation on Monday.

CrossRoads:
Perhaps the OP will rejoin the conversation on Monday.

Perhaps I should!

Sorry guys for the absence and thank you for all of your thoughts.
With regard to the display quality I am quite happy with the RGB matrix I picked up. I wired all the cathodes together but I need to fine tune the green with the correct reistor to bring it line with the other two colours.
This is just a prototype for now so a couple sheets of tracing paper has helped with creating diffused colours. But all of this is details.

Here is the link http://lost-buoys.com/blog/blog/2012/12/03/forced-synesthesia-chromatic-clock-test-2/ however you guys have all seen RGB matrices and the quality of this video is not great

All the test sketches that I have ran through have used the full 0-255 values and I am happy with the luminosity balance. Not sure what an RGB minute array progmem is.... I'm pretty green.

dhenry:
You will notice that the color changes follow the same pattern, offset by 120 degrees (1440 / 3 = 480 minutes). So if you represent one color in a table / function, the two other colors are simply 480 / 960 minutes later.

Thanks dhenry. This is a smart insight, and everything else you've said seem solid. The math and logic isn't totally clear to me but I can work at it until I understand, I get the concept.

CrossRoads:
So change every 2 minutes. From 11:48 to 12:12 change once a minute.

This so simple and smart. You're a dead right about the 768 (assuming I count 0). Which makes me think, what if I "massaged" the numbers to fit the 1440? I will think on this

Grumpy_Mike:
you will not be able to perceive 765 colours or anything like it ... gamma correction

I agree, and I certainly don't intend to sit watching it. Another argument for "massaging" a 1440 friendly number. I don't know about gamma though. Lets get the heart working first.

I need to put my head down on this again. Will keep everyone posted

lost_buoy:
Not sure what an RGB minute array progmem is.... I'm pretty green.

"RGB/minute" in PROGMEM (for PROGMEM, see Flash | Arduiniana)
A data array (table) of minutes of the day where each cell would contain the particular RGB values for each particular minute of the day, if you wanted to tweak. Probably more manageable with 3 arrays (R/minutes, G/minutes, B/minutes)

Thanks Pancake, I understand what you're talking about now.

Am I to understand that such a a solution would require me to fill in a 1440 item table three times? (or am I just being stupid?)

I think I will go with an amalgam of the advice offered by both dhenry and CrossRoads

I will use three 480 minute colour cycles offset and I will distribute 240 values throughout those cycles.

If it was me, I'd just code an algorithm to calculate the brightness of a single channel by during a range check to determine which of the three parts of that profile the current position was in, and a simple linear transform for each part to calculate the brightness. Do this three times with different offsets to get the correct phase between the three channels and you have your RGB values. Now you can apply your gamma correction and output them. This involves a lot more runtime overhead than a table lookup, but the amount of effort involved in coding it is similar (you have to populate the table somehow or other) and this code doesn't seem to be performance-critical.

I will use three 480 minute colour cycles offset and I will distribute 240 values throughout those cycles.

If you intend to implement gamma correction, you can simply code the curve into a look-up table: the fastest approach.