Sorry for this technicality:
1 normal post
Sorry for this technicality:
1 normal post
Now:
I guess my maps are being used wrong, and are returning improper values. The code is fully commented, so please take a look.
/* Logistic Light
This sketch fades an LED based on values defined by the logistic map
( Logistic map - Wikipedia ). It defines lower and
upper bounds a and b using the logistic equation, and then maps the
values returned from the polynomial curve -x^3+x to those bounds.Updated 3 May 2010
By Daniel D.*/
float a; //lower boundary
float b; //upper boundary
float mapValue= 0.5; //variable used to store the value of the logistic map
const int ledPin= 13;float lmap();
float smooth();void setup(){
pinMode(ledPin, OUTPUT);//_________________
Serial.begin(9600);
//-----------------
}void loop(){
lmap();
smooth();
}float lmap(){
a= mapValue; //lower bound set as initial value
mapValue= 3.8 * mapValue * (1 - mapValue); //the logistic equation
b= mapValue; //upper bound set as new value//_____________________
Serial.print("a = ");
Serial.println(a);
Serial.print("b = ");
Serial.println(b);
//----------------------
}float smooth(){
for(float i= -0.57735; i <= 0.57735; i += 0.023094){ //-x^3+x has a minimum
//at these inital values, and the norm is 1/50 of the intervalfloat aValue= map(-1 * pow(i, 3)+i, -0.38491, 0.38491, a, b); //SHOULD map
//i from -x^3+x's min and max y values to the bounds a and bfloat ledValue= map(aValue, 0, 1, 0, 255); //SHOULD map the newly-bounded
//aValue from the logistic map's bounds 0 and 1 to the LED's outputanalogWrite(ledPin, ledValue);
//_____________________________________
Serial.print("i = ");
Serial.print((-1 * pow(i, 3)+i)*10000);
Serial.print(", aValue = ");
Serial.print(aValue);
Serial.print(", ledValue = ");
Serial.println(ledValue);
//--------------------------------------delay(10);
}
}
I'm still learning C/C++ with my arduino, but I seem to recall someone recommending the following when working with floats:
Yours:
float ledValue= map(aValue, 0, 1, 0, 255); //SHOULD map the newly-bounded
//aValue from the logistic map's bounds 0 and 1 to the LED's output
Try:
float ledValue= map(aValue, 0, [glow]1.0[/glow], 0, [glow]255.0[/glow]); //SHOULD map the newly-bounded
//aValue from the logistic map's bounds 0 and 1 to the LED's output
See if that makes a difference. Maybe won't help at all, but as I said I recall someone warning about the mixing of integers with floats in expressions.
PS edit: Just read the following from the map() reference in the Arduino home page:
"The map() function uses integer math so will not generate fractions, when the math might indicate that it should do so. Fractional remainders are truncated, and are not rounded or averaged. "
So maybe you have to rework your program to deal with the fact that a 0-1 input range to map, won't handle fractional values between 0-1?
Lefty
Mapping a value in the range 0 to 1 to a value in the range 0 to 255 is a simple matter of multiplying the value by 255. No call to the map function is required.
It's the other map call that is the source of the problem.
float aValue= map(-1 * pow(i, 3)+i, -0.38491, 0.38491, a, b);
Since all the inputs to the map function are integers, the from range becomes 0 to 0.
To map using floats, you'll need to write your own function that takes 4 floats.
Also note that pow(i, 3) is equal to (i * i * i), and that (i * i * i) is much faster to process than pow(i, 3).
To map using floats, you'll need to write your own function that takes 4 floats.
Since the "map" reference page gives the source of "map", it really shouldn't take too long to nail together a "float" version.
Oops, that should be 5 floats - the value to map, two values for the from range, and 2 values for the to range.
ah, perfect. I just rewrote the map function using floats, and it works perfectly. Thanks.
Would you mind sharing how you rewrote the map function? Thanks.
Yessir:
float floatMap(float x, float inMin, float inMax, float outMin, float outMax){
return (x-inMin)*(outMax-outMin)/(inMax-inMin)+outMin;
}
Thank you kind Sir. One more question if you don't mind. Do you have to declare "inMin," "inMax," etc as variables or are they part of the map function? Thanks again for your help.
They're the function's arguments, so it'd suffice to declare them within the function's prototype and definition.
Technically, when this function is called, it copies the values passed to it into “inMin”, “inMax”, etc. Another way to do it would be to declare these variables globally (i.e. outside “main()”). Then, as long as values have been assigned before a call to floatMap(), you could omit all arguments. This isn't really necessary, but if RAM is scarce, this reads the variables without copying them. A "#define” will also help for values that don't change.
For boundary conditions that don't change:
#define inMin 0 //or whichever values you prefer
#define inMax 1024
#define outMin 0
#define outMax 5
float floatMap(float x){
return (x-inMin)*(outMax-outMin)/(inMax-inMin)+outMin;
}
...
In Flash storage, that's (4 “float” * 4 bytes per “float”) 16 bytes saved, and twice that in RAM.
Food for thought.
One problem with your #defines is that they are all integer values, so the calculations in the function will be performed using integer arithmetic. For a function called floatMap, that's not a good thing.
The #define statements need to look like:
#define inMin 0.0 //or whichever values you prefer
#define inMax 1024.0
#define outMin 0.0
#define outMax 5.0