0

I am changing a variable with a predetermined rate. When my variable gets too large, I cap it back to the largest value I want to make it, and change the sign on the rate to make the change go the other direction.

x += rate;
if (x > 255){
  rate = -rate;
  x = 255;
}
if (x < 0) {
  rate = -rate;
  x = 0;
}

However (when I execute this code and use the variable to control the brightness of some LEDs), once x goes to or above my highest threshold, it resets to the lower value and goes up again.

None of the other code manipulates or uses x, unless when I am setting CRGB values with x to an LED array. This code runs in void(loop).

JRE
  • 67,678
  • 8
  • 104
  • 179
pdustin101
  • 13
  • 3
  • 3
    Is x a byte variable? – jonk Oct 27 '16 at 22:02
  • Where is x defined? What is it's type? It would be helpful to include both the definition of x and the loop this is in from your code. And the definition (type) of rate, too. – Jack B Oct 27 '16 at 22:03
  • I have tried changing it back and forth between a byte and an int, both exhibit this behavior and have no effect. BTW, rate = 4, which is not evenly divisible into 255, but my code should catch that. EDIT: I found out X was a byte the whole time, and that I didn't change it in debugging. – pdustin101 Oct 27 '16 at 22:04

1 Answers1

1

If \$x\$ is a byte variable (uint8_t, for example), then it makes sense that your code doesn't work. Also, your code presumes a signed value. That may be another problem. However, C compilers can violate rules, too. Try something like this:

if ( x > (255 - rate) ) {
    rate= -rate; /* not sure why you want to do that */
    x= 255;
} else
    x += rate;

Similar logic would apply in the negative direction, I think.

This allows you to keep it as a byte variable, though you need to think closely here. If x is a byte variable and it is signed, then even the code above won't work right. The maximum value is 127, then. Not 255.

Let's suppose you want x as a uint8_t. And you want this to go up and then down and then up and then down, etc. You now have another problem. That is that rate itself needs to be signed. So let's assume the following definitions:

uint8_t x;    /* unsigned from 0 to 255 */
int8_t rate;  /* signed from -128 to 127 */

Then try something like this:

if ( rate > 0 && x > (255 - (uint8_t) rate) ) {
    rate= -rate;
    x= 255;
} else if ( rate < 0 && x < (uint8_t) (-rate) ) {
    rate= -rate;
    x= 0;
} else
    x += rate;

Rate will then flip directions here, appropriately, and this allows you to keep the variables with small sizes, too.

jonk
  • 77,059
  • 6
  • 73
  • 185
  • I change the rate because x is supposed to go up until it is past 255, is set to 255, and then goes down until it is less than 0, is set to 0, etc. But your explanation of the byte being unsigned (or signed, I'll do my research on that more) pointed out the flaw in my code. – pdustin101 Oct 27 '16 at 22:10
  • @Philcat101 Okay. So it's like a triangle wave of sorts. – jonk Oct 27 '16 at 22:11
  • Exactly! It just makes my leds fade up to maximum and makes them go down. And I solved the problem, x is an integer now, and fixed the problem. RIP 1 extra byte of RAM I thought I could save :( – pdustin101 Oct 27 '16 at 22:13
  • @Philcat101 Well, I've done similar things. But the LED brightness won't scale linearly from a human perspective. Humans see brightness on a log scale. Not a linear one. I have developed a lesson plan on operating LEDs with the MSP430, which discusses human perceptions (several different laws here) and culminates in a geometric progression so that the LED actually appears very linear in its brightness changes to a human. – jonk Oct 27 '16 at 22:20
  • I know about the wave being more of a geometric one than a linear one. I personally like it, because it seems more dynamic, and I do not have lots of space on my trinket for code, with only about 5300 bytes available. I might experiment with it in the future though. Thanks again! – pdustin101 Oct 27 '16 at 22:30
  • @Philcat101 I have the MSP430 timer hardware do ALL the work. There's only very tiny code involved -- perhaps a hundred bytes? And that includes all the setup, too. – jonk Oct 27 '16 at 22:31
  • WOW, that is cool. Can I have a link? – pdustin101 Oct 27 '16 at 22:32
  • @Philcat101 Sure. Download this ZIP file: http://www.infinitefactors.org/misc/EZLED.ZIP – jonk Oct 27 '16 at 22:47