1

I have a general programming challenge for you all. I've been scratching my head trying to figure out the best way to do this...

I'm working in C and I've got a "speed" value that is passed to my program. It ranges from 0-255. This speed value needs to correspond to a millisecond time delay built into the program.

    unsigned char currentSpeed; //this is passed into my function, range 0-255
    unsigned long SlowestSpeedMillis = 3000; //in milliseconds
    if (currentSpeed > 0)
    {
       unsigned long Interval = ((256 - currentSpeed)*SlowestSpeedMillis)/255;

    }else{ //currentSpeed = 0
       //When Interval is zero, the program will freeze
       Interval = 0;
    }

Here's some sample results:
currentSpeed of 1 results in 3000 milliseconds (slowest)
currentSpeed of 128 results in ~1500 milliseconds (exactly half)
currentSpeed of 255 results in ~11 milliseconds (fastest)

The problem is that I would like it to be a curved result where it stays in the lower numbers and then quickly goes to 3000 at the end... I want the user to have the choice to make the program go as slow as 3000, but most values leading up to it aren't as important. Such as this:
currentSpeed of 1 results in 3000 milliseconds (slowest)
currentSpeed of 128 results in ~750 milliseconds (1/4th of potential)
currentSpeed of 255 results in ~11 milliseconds (fastest, anything close to zero)

Any ideas how to do this programmatically? Perhaps with some kind of equation?

sscode
  • 137
  • 1
  • 1
  • 7
  • 1
    There are many equations that start slow and grow quickly, such as Exponential, Quadratic, Tangent.... Since you don't seem picky on the details, pick one and use it until it *isn't* appropriate anymore. – abelenky Oct 18 '13 at 16:00
  • Why not just use a lookup table of 256 precalculated values? Then you can use whatever function you like to generate them. Storing `currentSpeed` as an unsigned char would make your function more stable. – r3mainer Oct 18 '13 at 16:06

2 Answers2

3

Normally in math you might do something like:

(currentSpeed / 255) * 3000

for linear, and to get a bit of a curve use a power:

((currentSpeed / 255) * (currentSpeed / 255)) * 3000

But, in integer math that doesn't work because (currentSpeed / 255) will almost always be zero.

To do this without floating point you have to scale up first before division.

((3000 * currentSpeed) * currentSpeed) / (255 * 255)
joeking
  • 2,006
  • 18
  • 29
  • This is almost perfect... except I need the inverse of it so that when currentspeed is 255, the result is almost 0. What do you think? `currentSpeed of 1 results in 3000 milliseconds (slowest) currentSpeed of 128 results in ~750 milliseconds (1/4th of potential) currentSpeed of 255 results in ~11 milliseconds (fastest, anything close to zero)` – sscode Oct 18 '13 at 17:09
  • Just invert it then ... "int x = 255 - currentSpeed", then use "x" in the equation instead of currentSpeed. You can scale currentSpeed a litte like "x = RANGE*(255-currentSpeed)+N" to make it invert range from N to RANGE+N. You can also adjust "3000" a bit, like "((3000-11)*x)*x/(255*255)+11" - this gives your desired result of 11 to 3000 milliseconds. – joeking Oct 18 '13 at 23:21
0

You can use

unsigned char currentSpeed; // range 0-255
unsigned long SlowestSpeedMillis = 3000; // in milliseconds
unsigned long Interval;
if (currentSpeed > 0)
{
   Interval = SlowestSpeedMillis/currentSpeed;

} else {
   Interval = 0;
}

1 is mapped to 3000, and 255 is mapped to 11.

damienfrancois
  • 52,978
  • 9
  • 96
  • 110