# Value Log Scale

Good afternoon all i have been looking at various links up and down the web but am having trouble finding what i want. I would like to scale a value say 10-1000 between 1-255 using what i believe is called a logarithmic scale.

I have the below code:

``````void setup() {
Serial.begin(9600);
for(uint8_t i = 10; i<1000; i+=10){
Serial.println(Logarithmic(i));
delay(50);
}
}

uint8_t Logrithmic(uint8_t num){
int output = log(num+1)/log(1000)*255;
return output;
}
``````

The code above works but unfortunatley it is the inverse of what i am after where i would like the values to increment slowly at the start and become less and less incremented near the end. more incremented at the end.

I also found this code on another forum but after copying it from javascript link here it doesnt seem to work.

``````void setup() {
Serial.begin(9600);
for(uint32_t i = 0; i<1000; i+=10){
Serial.println(Logrithmic(i));
delay(50);
}
}

uint32_t Logrithmic(uint32_t num){
int minp = 0;
int maxp = 100;

uint32_t minv = log(100);
uint32_t maxv = log(10000000);

uint32_t output = (maxv-minv) / (maxp-minp);
output = exp(minv + output*(num-minp));
return output;
}
``````

If you open the Serial Plotter you can see the results of both.

Shandy:
i would like the values to increment slowly at the start and become less and less incremented near the end.

I am not a math wizard, but that sounds like an exponential function, not a log which is the inverse of exponentiation.

This helps me somewhat and means i have been searching for the wrong thing the entire time, il post back if i find something more.

Okay i think i have something although it uses a floating point which i was told to always avoid but without it i have a excessive stepped style curve, anyone got any improvements without a float?

``````void setup() {
Serial.begin(9600);
for(uint32_t i = 0; i<1000; i+=10){
Serial.println(Exponent(i));
delay(50);
}
}

uint32_t Exponent(uint32_t num){
//int output = log(num+1)/log(300000)*255;
float R = (1000 * log10(2))/(log10(255));
uint32_t output = pow(2, (num / R)) - 1;
return output;
}
``````

Code came from this link here

aarg:
I am not a math wizard, but that sounds like an exponential function, not a log which is the inverse of exponentiation.

An exponential function would increase faster and faster as the x value increased, which isn't what I took the OP to want.

Reading back my original question i have missexplained this when i said less and less incremented at the end when i was referring to the curve.

He is correct in what he is talking about it is my confusion with the graphs and explaining the relationship that made it sound incorrect.

Well I read too fast, I agree… but the statement remains quite vague:

i would like the values to increment slowly at the start and become less and less incremented near the end

which sounds almost like a sin squared curve where it is flattened at the ends and sloped in the middle.

OP, please take a few minutes to compose a clear explanation. Some actual math would help since it’s a mathematical problem, apparently.

Or even, whip out a pencil and make a drawing, shoot it with your phone and post. Or, post a link to something that looks like what you want.

The code in post #3 and the image on the weblink in post #3 is exactly what i was after, i am just hoping their is a way to avoid using float.

Too late now, but in future, never go back and edit posts. It makes the replies look crazy.

Yes lesson learned, i did edit the original post and then realised a new reply was added, strange because it usually warns you.

For conclusion and in case anyone has any improvements ive taken the original code and transplanted the line with the float variable into a single line which although messy results in the abscence of the float.

``````void setup() {
Serial.begin(9600);
for(uint32_t i = 0; i<1000; i+=10){
Serial.println(Exponent(i));
delay(50);
}
}

uint32_t Exponent(uint32_t num){
//int output = log(num+1)/log(300000)*Bval;
//float R = (1000 * log10(2))/(log10(255));
uint32_t output = pow(2, (num / ((1000 * log10(2))/(log10(255))))) - 1;
return output;
}
``````

which although messy results in the abscence of the float.

The intermediate variable of type float is gone. There is still floating point arithmetic happening, so you've accomplished nothing except for making your code harder to read.

I have a feeling that a piecewise linear function is the way to go.