Fractional scrolling problem Hi,

Fractional scrolling problem

Hi, I´m stuck and I´m not sure if it´s a construction or a implementation bug.

What do I want to do? It´s about fractional shifting of the content of a line of leds. I want to move the content without changing it. I want to be able to rotate it in a circle frame by frame for a long time.

I do it the following way: I have an leds array with the origin data. For the shifting I need to merge the data of 2 leds into the destination led.
The destination is a second CRGB array leds2 of the same size. I go through the origin array, take the 2 involved pixels and get their RGB value:

CRGB PixelA = leds[ i ];
CRGB PixelB = leds[ i + 1];

I do it only within the valid range with an extra handling for the last pixel. With integer shifting I tested it and it woks fine.

Back to the fractions: The amount of shifting is defined by a byte variable “fractions”. Based on that I scale the data:

CRGB PixelA %= fractions;
CRGB PixelB %= 255 - fractions;

The sum of these 2 I write back into the second array:

leds2[ i ] = PixelA + PixelB;

From there I copy it back into leds. (Within an extra loop.)

When calling this repeatedly I would expect the content to move slowly in one direction. After 256 calls by one pixel. And this happens, but it gets brighter while doing so. After many calls the result is just white. Somehow an error sums up and maipulates the color/saturation.

Any idea what I´m doing wrong or wrongly assume?
Thanks for any thoughts!

Two thoughts here. First, I don’t know where the brightness problem is exactly. BUT, the second thing is that I think you CAN’T do fractional scrolling of an LED pattern without separate source and destination buffers; you have to keep the source buffer unmodified.

Here’s why I think it can’t work with a single buffer. The first iteration goes perfectly, but the subsequent iterations just get blurrier.

Imagine you have just one red (255,0,0) pixel, in LED 0, and you’re scrolling by a quarter pixel. The imagine that the first iteration goes PERFECTLY, and the result is this:
(192,0,0) (64,0,0) (0,0,0) (0,0,0) …

Great. But now what?

What you want is this:
(128,0,0) (128,0,0) (0,0,0) (0,0,0) …
(64,0,0) (192,0,0) (0,0,0) (0,0,0)
and finally
(0,0,0) (255,0,0) (0,0,0) (0,0,0)

BUT if the algorithm just moves 1/4 of the light from each pixel to its neighbor, you get this:
(144,0,0) (96,0,0) (16,0,0) (0,0,0) …
and then
(108,0,0) (108,0,0) (36,0,0) (4,0,0) …
and so on… it just smears. There’s no way to ever get to this!
(0,0,0) (255,0,0) (0,0,0) (0,0,0)

At least, there’s no way to do it without keeping separate source and destination buffers. If you have separate source and destination buffers, you can always do a ‘fractional shift’ rendering from src to dest, and have it come out right. It just takes a whole separate buffer.

Oh, and I think I know why the code might be accumulating extra light, too. I bet the code is looping the index from 0->N, and writing to L[i] and L[i+1], which means it’s adding light to the next LED-- and then processing that LED next. If you switch the loop to be from N->0, that part of the problem will probably go away, and you’ll be left with just that smearing. (Which will actually get darker over time due to loss of precision.). I think.

Thanks for your elaboration Mark, now I see the mistake in my aproach. Ok, so it needs a complete different design. Realtive smearing is an enirely different thing than absolute moving.
I will think about a solution. Thanks for making me see!