-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFscale.cpp
More file actions
143 lines (107 loc) · 3.93 KB
/
Fscale.cpp
File metadata and controls
143 lines (107 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// URL: https://playground.arduino.cc/Main/Fscale?action=sourceblock&num=1
/* fscale
Floating Point Autoscale Function V0.1
Paul Badger 2007
Modified from code by Greg Shakar
This function will scale one set of floating point numbers (range) to another set of floating point numbers (range)
It has a "curve" parameter so that it can be made to favor either the end of the output. (Logarithmic mapping)
It takes 6 parameters
originalMin - the minimum value of the original range - this MUST be less than origninalMax
originalMax - the maximum value of the original range - this MUST be greater than orginalMin
newBegin - the end of the new range which maps to orginalMin - it can be smaller, or larger, than newEnd, to facilitate inverting the ranges
newEnd - the end of the new range which maps to originalMax - it can be larger, or smaller, than newBegin, to facilitate inverting the ranges
inputValue - the variable for input that will mapped to the given ranges, this variable is constrained to originaMin <= inputValue <= originalMax
curve - curve is the curve which can be made to favor either end of the output scale in the mapping. Parameters are from -10 to 10 with 0 being
a linear mapping (which basically takes curve out of the equation)
To understand the curve parameter do something like this:
void loop(){
for ( j=0; j < 200; j++){
scaledResult = fscale( 0, 200, 0, 200, j, -1.5);
Serial.print(j, DEC);
Serial.print(" ");
Serial.println(scaledResult, DEC);
}
}
And try some different values for the curve function - remember 0 is a neutral, linear mapping
To understand the inverting ranges, do something like this:
void loop(){
for ( j=0; j < 200; j++){
scaledResult = fscale( 0, 200, 200, 0, j, 0);
// Serial.print lines as above
}
}
*/
#include <math.h>
#ifdef DEMO
int j;
float scaledResult;
void setup() {
Serial.begin(9600);
}
void loop(){
for ( j=0; j < 200; j++){
scaledResult = fscale( 0, 200, 0, 200, j, -1.5);
Serial.print(j, DEC);
Serial.print(" ");
Serial.println(scaledResult , DEC);
}
}
#endif // DEMO
float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){
float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
int invFlag = 0;
// condition curve parameter
// limit range
if (curve > 10) curve = 10;
if (curve < -10) curve = -10;
curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function
/*
Serial.println(curve * 100, DEC); // multply by 100 to preserve resolution
Serial.println();
*/
// Check for out of range inputValues
if (inputValue < originalMin) {
inputValue = originalMin;
}
if (inputValue > originalMax) {
inputValue = originalMax;
}
// Zero Refference the values
OriginalRange = originalMax - originalMin;
if (newEnd > newBegin){
NewRange = newEnd - newBegin;
}
else
{
NewRange = newBegin - newEnd;
invFlag = 1;
}
zeroRefCurVal = inputValue - originalMin;
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float
/*
Serial.print(OriginalRange, DEC);
Serial.print(" ");
Serial.print(NewRange, DEC);
Serial.print(" ");
Serial.println(zeroRefCurVal, DEC);
Serial.println();
*/
// Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine
if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0){
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
}
else // invert the ranges
{
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}