Hi,
I've managed to update the LPD8806 'advancedLEDBeltKit' to work with the WS2801 pixels library. It wasn't too much effort. However, the LPD8806 is 7-bit, whereas the WS2801 is the full 8-bit. The writers of the code were forward thinking enough to do full 8-bit calculations, but then obviously scale back to 7-bit before setting the pixel color. Not being a great programmer, I was hoping to find a simple "/ 2" in there somewhere, but it's a bit more complicated than that. Has anyone any idea how to get this working across the full 8 bits?
My second question, about the same code, is how to improve it so that it always runs at the 'fade' speed. It's great 'selling point' is that it smoothly fades between light patterns, but the speed difference is noticeable. The speed during fading is quick enough for me, so is there a simple way to 'fake' calculations during the non-fade stage so that it's always the same speed?
Thanks! Mark.
Upgrading LPD8806 Strip to WS2801 pixels - help
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
-
- Posts: 33
- Joined: Thu Dec 20, 2012 9:33 am
-
- Posts: 33
- Joined: Thu Dec 20, 2012 9:33 am
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
Bugger. I think the 'simple' 128 to 256 problem is a lot harder than I thought. I *think* it's been handled with the gammaTable
Anyone come across a true 256 level gamma table, or know how to calculate one?
Code: Select all
PROGMEM prog_uchar gammaTable[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7,
7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11,
11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16,
16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22,
23, 23, 24, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
30, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 37, 38, 38, 39,
40, 40, 41, 41, 42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50,
50, 51, 52, 52, 53, 54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 62,
62, 63, 64, 65, 66, 67, 67, 68, 69, 70, 71, 72, 73, 74, 74, 75,
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99,100,101,102,104,105,106,107,108,
109,110,111,113,114,115,116,117,118,120,121,122,123,125,126,127
};
-
- Posts: 33
- Joined: Thu Dec 20, 2012 9:33 am
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
I've put in a '* 2' here:
But the perfectionist in me, would really like a new full table...
Code: Select all
inline byte gamma(byte x) {
return pgm_read_byte(&gammaTable[x]) * 2;
}
-
- Posts: 33
- Joined: Thu Dec 20, 2012 9:33 am
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
I produced my own table from a function that I found:
The function is this (converted by me to VB.NET for speed of use, and hardcoded 0.5 as a gamma value):
Blimey! the number one hundred and eighty-six is detected by this forum as spam!! Please substitute the 'x' in 'x86' with a '1'
Code: Select all
PROGMEM prog_uchar gammaTable[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7,
7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14,
14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22,
23, 23, 24, 24, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32,
33, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45,
46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 84, 85, 86, 87, 88, 89, 91, 92, 93, 94,
95, 97, 98, 99, 100, 102, 103, 104, 105, 107, 108, 109, 111, 112,
113, 115, 116, 117, 119, 120, 121, 123, 124, 126, 127, 128, 130,
131, 133, 134, 136, 137, 139, 140, 142, 143, 145, 146, 148, 149,
151, 152, 154, 155, 157, 158, 160, 162, 163, 165, 166, 168, 170,
171, 173, 175, 176, 178, 180, 181, 183, 185, x86, 188, 190, 192,
193, 195, 197, 199, 200, 202, 204, 206, 207, 209, 211, 213, 215,
217, 218, 220, 222, 224, 226, 228, 230, 232, 233, 235, 237, 239,
241, 243, 245, 247, 249, 251, 253, 255 };
Code: Select all
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim output As String
Dim gamma As Double = 0.5
For i As Integer = 0 To 255
Dim y As Double = CDbl(i) / 255.0
y = y ^ (1.0 / gamma)
output &= CStr(CInt(Fix(Floor(255.0 * y + 0.5)))) & ", "
Next i
MsgBox(output)
End Sub
-
- Posts: 33
- Joined: Thu Dec 20, 2012 9:33 am
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
So, the only query outstanding is how to slow down the 'else' section of:
So that it is as slow as the 'then' section...
Any ideas? (note: a delay doesn't work - probably needs some dummy maths in there instead.)
Code: Select all
// Front render and composite only happen during transitions...
if(tCounter > 0) {
// Transition in progress
byte *frontPtr = &imgData[frontImgIdx][0];
int alpha, inv;
// Render front image and alpha mask based on current effect indices...
(*renderEffect[fxIdx[frontImgIdx]])(frontImgIdx);
(*renderAlpha[fxIdx[2]])();
// ...then composite front over back:
for(i=0; i<numPixels; i++) {
alpha = alphaMask[i] + 1; // 1-256 (allows shift rather than divide)
inv = 257 - alpha; // 1-256 (ditto)
// r, g, b are placed in variables (rather than directly in the
// setPixelColor parameter list) because of the postincrement pointer
// operations -- C/C++ leaves parameter evaluation order up to the
// implementation; left-to-right order isn't guaranteed.
r = gamma((*frontPtr++ * alpha + *backPtr++ * inv) >> 8);
g = gamma((*frontPtr++ * alpha + *backPtr++ * inv) >> 8);
b = gamma((*frontPtr++ * alpha + *backPtr++ * inv) >> 8);
pixelString.setPixelColor(i, r, g, b);
}
} else {
// No transition in progress; just show back image
for(i=0; i<numPixels; i++) {
// See note above re: r, g, b vars.
r = gamma(*backPtr++);
g = gamma(*backPtr++);
b = gamma(*backPtr++);
pixelString.setPixelColor(i, r, g, b);
}
}
Any ideas? (note: a delay doesn't work - probably needs some dummy maths in there instead.)
- pburgess
- Posts: 4161
- Joined: Sun Oct 26, 2008 2:29 am
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
For the timing thing, you'd need to change the interrupt interval. Near the top of the code:
Change the '60' to some lesser number of frames per second (e.g. 30). I'm guessing you're running this with a really long strand or something?
Code: Select all
Timer1.attachInterrupt(callback, 1000000 / 60); // 60 frames/second
-
- Posts: 33
- Joined: Thu Dec 20, 2012 9:33 am
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
Thanks pburgess!
That's really good, so if this ever gets up and running on the Due then I could put it back to 60fps (or more). 30 fps is plenty for developing my own patterns.
Yes - I am running 100 pixels.
So, the basic belt kit works on the Arduino Due, but the advanced belt kit doesn't. Timer/interrupts are well beyond my level of coding. Is anyone working on a way to replace the timer1 & avr/pgmspace.h with the interrupts in the Due?
I'd really like to get the Christmas tree code that I put up a while back running with the Due and WS2801 to share with the forum again.
That's really good, so if this ever gets up and running on the Due then I could put it back to 60fps (or more). 30 fps is plenty for developing my own patterns.
Yes - I am running 100 pixels.
So, the basic belt kit works on the Arduino Due, but the advanced belt kit doesn't. Timer/interrupts are well beyond my level of coding. Is anyone working on a way to replace the timer1 & avr/pgmspace.h with the interrupts in the Due?
I'd really like to get the Christmas tree code that I put up a while back running with the Due and WS2801 to share with the forum again.
-
- Posts: 5
- Joined: Wed Jun 25, 2014 11:46 pm
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
I wanted to bump this up as I am working with a WS2812b strip with 240 pixels and was interested in applying a gamma correction. I've noticed when I overlay colors with an alpha channel that the resulting colors tend to be whited out (because whenever the two colors have all three r,g,b components it is adding some white).
[BTW, I've noticed fade effects animated as transparent overlays animate same speed all the time but maybe it's just the drivers I'm using]
I would like to be able to pick colors out from my monitor and have them show up with some fidelity on the Neopixel strip, so... gamma correction!
The drivers I'm using compress everything to a table with 32 values, which the author maps to with a pwmToBrightness() function and I take to be a rudimentary gamma correction.
Here's a reference I found on the subject that is completely too technical: http://www.poynton.com/PDFs/BANNED_of_gamma.pdf
I'd like to get a gamma table that has a minimum non-zero brightness for the '0' codes, and that incorporates the relative luminous intensities from the datasheet.
I'll try out the gamma table from the NeoMatrix code and see how that works =]
[BTW, I've noticed fade effects animated as transparent overlays animate same speed all the time but maybe it's just the drivers I'm using]
I would like to be able to pick colors out from my monitor and have them show up with some fidelity on the Neopixel strip, so... gamma correction!
The drivers I'm using compress everything to a table with 32 values, which the author maps to with a pwmToBrightness() function and I take to be a rudimentary gamma correction.
Here's a reference I found on the subject that is completely too technical: http://www.poynton.com/PDFs/BANNED_of_gamma.pdf
I'd like to get a gamma table that has a minimum non-zero brightness for the '0' codes, and that incorporates the relative luminous intensities from the datasheet.
I'll try out the gamma table from the NeoMatrix code and see how that works =]
-
- Posts: 5
- Joined: Wed Jun 25, 2014 11:46 pm
Re: Upgrading LPD8806 Strip to WS2801 pixels - help
OK, so it seems the best luck I've had is with scaling the output from the LEDs proportionally to their radiant intensity (millicandelas / luminous efficacy for lambda_max)
The counter-intuitive result is that the green light is *much* brighter in millicandelas, but in terms of photon flux (through rods/cones, that's what luminous efficacy is for right?) it's actually the least intense of the LEDs, so to get better color mixing, scale the red and blue down relative to the green.
So far this seems to work very well for displaying dim colors and displaying similar colors with more contrast. It has the added benefit of leading to ranges for r,g,b that add up to white light I can display at 'full' brightness with my 5V/10A power supply (240 pixels at full white bright uses less than 10A with this color coding].
I still need a non-linear term to make gray come out as evenly as pure white is now, but am able to do things like plum vs. violet, or orange vs. brown.
The counter-intuitive result is that the green light is *much* brighter in millicandelas, but in terms of photon flux (through rods/cones, that's what luminous efficacy is for right?) it's actually the least intense of the LEDs, so to get better color mixing, scale the red and blue down relative to the green.
So far this seems to work very well for displaying dim colors and displaying similar colors with more contrast. It has the added benefit of leading to ranges for r,g,b that add up to white light I can display at 'full' brightness with my 5V/10A power supply (240 pixels at full white bright uses less than 10A with this color coding].
I still need a non-linear term to make gray come out as evenly as pure white is now, but am able to do things like plum vs. violet, or orange vs. brown.
Please be positive and constructive with your questions and comments.