Skip to content

Commit 065f4da

Browse files
committed
0.1.1 version
1 parent 0e4404c commit 065f4da

File tree

10 files changed

+555
-2
lines changed

10 files changed

+555
-2
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 Rob Tillaart
3+
Copyright (c) 2011-2020 Rob Tillaart
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

MultiMap.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#pragma once
2+
//
3+
// FILE: multimap.h
4+
// AUTHOR: Rob Tillaart
5+
// VERSION: 0.1.1
6+
// PURPOSE: Arduino library for fast non-linear mapping or interpolation of values
7+
// URL: https://github.com/RobTillaart/MultiMap
8+
// URL: http://playground.arduino.cc/Main/MultiMap
9+
//
10+
// HISTORY: see playground article
11+
//
12+
13+
#define MULTIMAP_LIB_VERSION "0.1.1"
14+
15+
#include <Arduino.h>
16+
17+
// note: the in array should have increasing values
18+
template<typename T>
19+
T multiMap(T val, T* _in, T* _out, uint8_t size)
20+
{
21+
// take care the value is within range
22+
// val = constrain(val, _in[0], _in[size-1]);
23+
if (val <= _in[0]) return _out[0];
24+
if (val >= _in[size-1]) return _out[size-1];
25+
26+
// search right interval
27+
uint8_t pos = 1; // _in[0] allready tested
28+
while(val > _in[pos]) pos++;
29+
30+
// this will handle all exact "points" in the _in array
31+
if (val == _in[pos]) return _out[pos];
32+
33+
// interpolate in the right segment for the rest
34+
return (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
35+
}
36+
37+
38+
/*
39+
* speed optimized version if inputs do not change often e.g. 2 2 2 2 2 3 3 3 3 5 5 5 5 5 5 8 8 8 8 5 5 5 5 5
40+
*
41+
// note: the in array should have increasing values
42+
template<typename T>
43+
T multiMap(T val, T* _in, T* _out, uint8_t size)
44+
{
45+
46+
static T lastvalue = -1;
47+
static T cache = -1;
48+
49+
if (val == lastvalue) return cache;
50+
lastvalue = val;
51+
52+
// take care the value is within range
53+
// val = constrain(val, _in[0], _in[size-1]);
54+
if (val <= _in[0])
55+
{
56+
cache = _out[0];
57+
}
58+
else if (val >= _in[size-1])
59+
{
60+
cache = _out[size-1];
61+
}
62+
else
63+
{
64+
// search right interval; index 0 _in[0] already tested
65+
uint8_t pos = 1;
66+
while(val > _in[pos]) pos++;
67+
68+
// this will handle all exact "points" in the _in array
69+
if (val == _in[pos])
70+
{
71+
cache = _out[pos];
72+
}
73+
else
74+
{
75+
// interpolate in the right segment for the rest
76+
cache = (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
77+
}
78+
}
79+
return cache;
80+
}
81+
*/
82+
83+
// -- END OF FILE --

README.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,40 @@
11
# MultiMap
2-
Arduino library for non-linear mapping or interpolation of values
2+
3+
Arduino library for fast non-linear mapping or interpolation of values
4+
5+
## Description
6+
7+
In Arduino applications often the value of a sensor is mapped upon a more
8+
usable value. E.g. the value of analogRead() is mapped onto 0 .. 5.0 Volt.
9+
This is done by the map function which does a linear interpolation. This means
10+
```
11+
output = C1 + input * C2
12+
```
13+
As C1 and C2 are to be calculated Arduino has the **map()** that calculates the
14+
two variables runtime from two given mappings.
15+
```
16+
output = map(input, I1, I2, O1, O2):
17+
```
18+
19+
In many cases when there is no linear mapping possible, as the 'points' are not on a single line,
20+
one needs non-linear math to calculate the output. **Multimap()** just does that.
21+
22+
**Multimap()** needs two equal sized arrays of 'points', **input\[\]** and **output\[\]**, it looks up the
23+
input value in the input\[\] array and if needed it linear interpolates between two
24+
points of the output\[\] array.
25+
26+
The **input\[\]** array must have increasing values,
27+
there is no such restriction for the **output\[\]** array.
28+
29+
**Multimap()** automatically constrains the output to the first and last
30+
value in the **output\[\]** array.
31+
32+
## Operation
33+
34+
See examples
35+
36+
Please note the fail example as this shows that in the intern math overflow can happen.
37+
38+
## TODO
39+
40+
Investigate class implementation for performance.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//
2+
// FILE: multimap_NTC.ino
3+
// AUTHOR: Rob Tillaart
4+
// VERSION: 0.1.0
5+
// PURPOSE: demo
6+
// DATE: 2020-04-09
7+
// (c) : MIT
8+
//
9+
10+
#include "multimap.h"
11+
12+
uint32_t start;
13+
uint32_t stop;
14+
15+
volatile float x, y, z;
16+
17+
// Note this is a bit an extreme example,
18+
// normally you only make a multimap of the working range
19+
20+
float in[] = {
21+
0, 1, 3, 8, 13, 20, 25, 32, 50, 60, 72, 85, 100, 145, 200, 250, 300, 400, 500, 600, 650, 700, 753, 800, 830, 870, 900, 936, 964, 985, 1000, 1017, 1023
22+
};
23+
float out[] = {
24+
-273.15, -71.65, -60.69, -49.81, -43.97, -38.50, -35.54, -32.16, -25.72, -22.95, -20.08, -17.37, -14.62, -7.90, -1.43, 3.57,
25+
8.08, 16.34, 24.30, 32.64, 37.17, 42.13, 48.05, 54.19, 58.75, 66.03, 72.87, 83.85, 96.51, 111.46, 129.49, 182.82, 301.82
26+
};
27+
28+
int sz = 33;
29+
30+
void setup()
31+
{
32+
Serial.begin(115200);
33+
Serial.println(__FILE__);
34+
Serial.println();
35+
delay(10); // make sure print has ended
36+
37+
start = micros();
38+
x = val(z);
39+
stop = micros();
40+
Serial.println(stop - start);
41+
delay(10); // make sure print has ended
42+
43+
start = micros();
44+
x = multiMap<float>(z, in, out, sz);
45+
stop = micros();
46+
Serial.println(stop - start);
47+
delay(10); // make sure print has ended
48+
49+
for (int i = 0; i < 1024; i++)
50+
{
51+
x = val(i);
52+
y = multiMap<float>(i, in, out, sz);
53+
z = abs(x - y);
54+
55+
Serial.print(i);
56+
Serial.print('\t');
57+
Serial.print(x);
58+
Serial.print('\t');
59+
Serial.print(y);
60+
Serial.print('\t');
61+
Serial.print(z);
62+
Serial.println();
63+
}
64+
65+
}
66+
67+
void loop()
68+
{
69+
}
70+
71+
// NTC formula
72+
float val(int sensorValueA1)
73+
{
74+
int R10k_ntc = 9870;
75+
float U10k_ntc = sensorValueA1 * (5.0 / 1024.0);
76+
float Untc = 5.0 - U10k_ntc;
77+
float Rntc = (R10k_ntc * Untc) / U10k_ntc;
78+
float Temp = (298.15 / (1 - (298.15 / 4300.0) * log(10000.0 / Rntc))) - (273.15 + 0);
79+
80+
return Temp;
81+
}
82+
83+
// -- END OF FILE --
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//
2+
// FILE: multimap_NTC_int_FAIL.ino
3+
// AUTHOR: Rob Tillaart
4+
// VERSION: 0.1.0
5+
// PURPOSE: demo of faulty optimizing
6+
// DATE: 2020-04-09
7+
// (c) : MIT
8+
//
9+
10+
// NOTE:
11+
// use integers instead of floats to minimize RAM. uses ~320 bytes PROGMEM ~120 bytes RAM less on UNO than float version
12+
//
13+
// this example is added to show how to reduce memory but also how it can FAIL due to math overflow
14+
// E.g. see around 196-200; 340-400
15+
// to prevent this one must have more values which increases the memory usage again.
16+
//
17+
18+
19+
#include "multimap.h"
20+
21+
uint32_t start;
22+
uint32_t stop;
23+
24+
volatile float x, y, z;
25+
26+
int in[] = {
27+
0, 1, 3, 8, 13, 20, 25, 32, 50, 60, 72, 85, 100, 145, 200, 250, 300, 400, 500, 600, 650, 700, 753, 800, 830, 870, 900, 936, 964, 985, 1000, 1017, 1023
28+
};
29+
int out[] = {
30+
-27315, -7165, -6069, -4981, -4397, -3850, -3554, -3216, -2572, -2295, -2008, -1737, -1462, -790, -143, 357, 808, 1634, 2430, 3264,
31+
3717, 4213, 4805, 5419, 5875, 6603, 7287, 8385, 9651, 11146, 12949, 18282, 30182
32+
};
33+
34+
int sz = 33;
35+
36+
void setup()
37+
{
38+
Serial.begin(115200);
39+
Serial.println(__FILE__);
40+
Serial.println();
41+
delay(10); // make sure print has ended
42+
43+
start = micros();
44+
x = val(z);
45+
stop = micros();
46+
Serial.println(stop - start);
47+
delay(10); // make sure print has ended
48+
49+
start = micros();
50+
x = 0.01 * multiMap<int>(z, in, out, sz);
51+
stop = micros();
52+
Serial.println(stop - start);
53+
delay(10); // make sure print has ended
54+
55+
for (int i = 0; i < 1024; i++)
56+
{
57+
x = val(i);
58+
y = 0.01 * multiMap<int>(i, in, out, sz);
59+
z = abs(x - y);
60+
61+
Serial.print(i);
62+
Serial.print('\t');
63+
Serial.print(x);
64+
Serial.print('\t');
65+
Serial.print(y);
66+
Serial.print('\t');
67+
Serial.print(z);
68+
Serial.println();
69+
}
70+
71+
}
72+
73+
void loop()
74+
{
75+
}
76+
77+
// NTC formula
78+
float val(int sensorValueA1)
79+
{
80+
int R10k_ntc = 9870;
81+
float U10k_ntc = sensorValueA1 * (5.0 / 1024.0);
82+
float Untc = 5.0 - U10k_ntc;
83+
float Rntc = (R10k_ntc * Untc) / U10k_ntc;
84+
float Temp = (298.15 / (1 - (298.15 / 4300.0) * log(10000.0 / Rntc))) - (273.15 + 0);
85+
86+
return Temp;
87+
}
88+
89+
// -- END OF FILE --
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
//
3+
// FILE: multimap_distance.ino
4+
// AUTHOR: Rob Tillaart
5+
// VERSION: 0.1.0
6+
// PURPOSE: demo
7+
// DATE: 2020-04-09
8+
//
9+
10+
#include "multimap.h"
11+
12+
void setup()
13+
{
14+
Serial.begin(115200);
15+
Serial.println(__FILE__);
16+
Serial.println();
17+
18+
for (int i = 80; i < 512; i++)
19+
{
20+
float distance = sharp2cm(i);
21+
// Serial.print('\t');
22+
// Serial.print(i);
23+
// Serial.print('\t');
24+
Serial.println(distance, 1);
25+
}
26+
Serial.println("Done...");
27+
}
28+
29+
void loop()
30+
{
31+
}
32+
33+
34+
// for a sharp distance range finder
35+
float sharp2cm(int val)
36+
{
37+
// out[] holds the distances in cm
38+
float out[] = {150, 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20};
39+
40+
// in[] holds the measured analogRead() values for that distance
41+
float in[] = { 90, 97, 105, 113, 124, 134, 147, 164, 185, 218, 255, 317, 408, 506};
42+
43+
float dist = multiMap<float>(val, in, out, 14);
44+
return dist;
45+
}
46+
47+
// -- END OF FILE --

0 commit comments

Comments
 (0)